From 222e2a7620e6520ffaf4fc4e69d79c18da31542e Mon Sep 17 00:00:00 2001
From: "Zancanaro; Carlo" <czan8762@plang3.cs.usyd.edu.au>
Date: Mon, 24 Sep 2012 09:58:17 +1000
Subject: Add the clang library to the repo (with some of my changes, too).

---
 clang/lib/Sema/AnalysisBasedWarnings.cpp       |  1016 ++
 clang/lib/Sema/AttributeList.cpp               |   126 +
 clang/lib/Sema/CMakeLists.txt                  |    58 +
 clang/lib/Sema/CodeCompleteConsumer.cpp        |   641 ++
 clang/lib/Sema/DeclSpec.cpp                    |   986 ++
 clang/lib/Sema/DelayedDiagnostic.cpp           |    56 +
 clang/lib/Sema/IdentifierResolver.cpp          |   444 +
 clang/lib/Sema/JumpDiagnostics.cpp             |   770 ++
 clang/lib/Sema/Makefile                        |    19 +
 clang/lib/Sema/Scope.cpp                       |    71 +
 clang/lib/Sema/Sema.cpp                        |  1102 +++
 clang/lib/Sema/SemaAccess.cpp                  |  1850 ++++
 clang/lib/Sema/SemaAttr.cpp                    |   426 +
 clang/lib/Sema/SemaCXXScopeSpec.cpp            |   958 ++
 clang/lib/Sema/SemaCast.cpp                    |  2112 +++++
 clang/lib/Sema/SemaChecking.cpp                |  5153 ++++++++++
 clang/lib/Sema/SemaCodeComplete.cpp            |  7178 ++++++++++++++
 clang/lib/Sema/SemaConsumer.cpp                |    14 +
 clang/lib/Sema/SemaDecl.cpp                    | 10462 +++++++++++++++++++++
 clang/lib/Sema/SemaDeclAttr.cpp                |  4171 +++++++++
 clang/lib/Sema/SemaDeclCXX.cpp                 | 11340 +++++++++++++++++++++++
 clang/lib/Sema/SemaDeclObjC.cpp                |  3121 +++++++
 clang/lib/Sema/SemaExceptionSpec.cpp           |  1086 +++
 clang/lib/Sema/SemaExpr.cpp                    | 11280 ++++++++++++++++++++++
 clang/lib/Sema/SemaExprCXX.cpp                 |  5362 +++++++++++
 clang/lib/Sema/SemaExprMember.cpp              |  1618 ++++
 clang/lib/Sema/SemaExprObjC.cpp                |  3049 ++++++
 clang/lib/Sema/SemaFixItUtils.cpp              |   204 +
 clang/lib/Sema/SemaInit.cpp                    |  6167 ++++++++++++
 clang/lib/Sema/SemaLambda.cpp                  |   820 ++
 clang/lib/Sema/SemaLookup.cpp                  |  4060 ++++++++
 clang/lib/Sema/SemaObjCProperty.cpp            |  1953 ++++
 clang/lib/Sema/SemaOverload.cpp                | 11229 ++++++++++++++++++++++
 clang/lib/Sema/SemaPseudoObject.cpp            |  1373 +++
 clang/lib/Sema/SemaStmt.cpp                    |  2663 ++++++
 clang/lib/Sema/SemaStmtAttr.cpp                |    48 +
 clang/lib/Sema/SemaTemplate.cpp                |  7192 ++++++++++++++
 clang/lib/Sema/SemaTemplateDeduction.cpp       |  4515 +++++++++
 clang/lib/Sema/SemaTemplateInstantiate.cpp     |  2621 ++++++
 clang/lib/Sema/SemaTemplateInstantiateDecl.cpp |  3502 +++++++
 clang/lib/Sema/SemaTemplateVariadic.cpp        |   794 ++
 clang/lib/Sema/SemaType.cpp                    |  4514 +++++++++
 clang/lib/Sema/TargetAttributesSema.cpp        |   278 +
 clang/lib/Sema/TargetAttributesSema.h          |    27 +
 clang/lib/Sema/TreeTransform.h                 |  9268 ++++++++++++++++++
 clang/lib/Sema/TypeLocBuilder.h                |   201 +
 46 files changed, 135898 insertions(+)
 create mode 100644 clang/lib/Sema/AnalysisBasedWarnings.cpp
 create mode 100644 clang/lib/Sema/AttributeList.cpp
 create mode 100644 clang/lib/Sema/CMakeLists.txt
 create mode 100644 clang/lib/Sema/CodeCompleteConsumer.cpp
 create mode 100644 clang/lib/Sema/DeclSpec.cpp
 create mode 100644 clang/lib/Sema/DelayedDiagnostic.cpp
 create mode 100644 clang/lib/Sema/IdentifierResolver.cpp
 create mode 100644 clang/lib/Sema/JumpDiagnostics.cpp
 create mode 100644 clang/lib/Sema/Makefile
 create mode 100644 clang/lib/Sema/Scope.cpp
 create mode 100644 clang/lib/Sema/Sema.cpp
 create mode 100644 clang/lib/Sema/SemaAccess.cpp
 create mode 100644 clang/lib/Sema/SemaAttr.cpp
 create mode 100644 clang/lib/Sema/SemaCXXScopeSpec.cpp
 create mode 100644 clang/lib/Sema/SemaCast.cpp
 create mode 100644 clang/lib/Sema/SemaChecking.cpp
 create mode 100644 clang/lib/Sema/SemaCodeComplete.cpp
 create mode 100644 clang/lib/Sema/SemaConsumer.cpp
 create mode 100644 clang/lib/Sema/SemaDecl.cpp
 create mode 100644 clang/lib/Sema/SemaDeclAttr.cpp
 create mode 100644 clang/lib/Sema/SemaDeclCXX.cpp
 create mode 100644 clang/lib/Sema/SemaDeclObjC.cpp
 create mode 100644 clang/lib/Sema/SemaExceptionSpec.cpp
 create mode 100644 clang/lib/Sema/SemaExpr.cpp
 create mode 100644 clang/lib/Sema/SemaExprCXX.cpp
 create mode 100644 clang/lib/Sema/SemaExprMember.cpp
 create mode 100644 clang/lib/Sema/SemaExprObjC.cpp
 create mode 100644 clang/lib/Sema/SemaFixItUtils.cpp
 create mode 100644 clang/lib/Sema/SemaInit.cpp
 create mode 100644 clang/lib/Sema/SemaLambda.cpp
 create mode 100644 clang/lib/Sema/SemaLookup.cpp
 create mode 100644 clang/lib/Sema/SemaObjCProperty.cpp
 create mode 100644 clang/lib/Sema/SemaOverload.cpp
 create mode 100644 clang/lib/Sema/SemaPseudoObject.cpp
 create mode 100644 clang/lib/Sema/SemaStmt.cpp
 create mode 100644 clang/lib/Sema/SemaStmtAttr.cpp
 create mode 100644 clang/lib/Sema/SemaTemplate.cpp
 create mode 100644 clang/lib/Sema/SemaTemplateDeduction.cpp
 create mode 100644 clang/lib/Sema/SemaTemplateInstantiate.cpp
 create mode 100644 clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
 create mode 100644 clang/lib/Sema/SemaTemplateVariadic.cpp
 create mode 100644 clang/lib/Sema/SemaType.cpp
 create mode 100644 clang/lib/Sema/TargetAttributesSema.cpp
 create mode 100644 clang/lib/Sema/TargetAttributesSema.h
 create mode 100644 clang/lib/Sema/TreeTransform.h
 create mode 100644 clang/lib/Sema/TypeLocBuilder.h

(limited to 'clang/lib/Sema')

diff --git a/clang/lib/Sema/AnalysisBasedWarnings.cpp b/clang/lib/Sema/AnalysisBasedWarnings.cpp
new file mode 100644
index 0000000..a8e6791
--- /dev/null
+++ b/clang/lib/Sema/AnalysisBasedWarnings.cpp
@@ -0,0 +1,1016 @@
+//=- AnalysisBasedWarnings.cpp - Sema warnings based on libAnalysis -*- 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 analysis_warnings::[Policy,Executor].
+// Together they are used by Sema to issue warnings based on inexpensive
+// static analysis algorithms in libAnalysis.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Sema/AnalysisBasedWarnings.h"
+#include "clang/Sema/SemaInternal.h"
+#include "clang/Sema/ScopeInfo.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Basic/SourceLocation.h"
+#include "clang/Lex/Preprocessor.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/AST/DeclCXX.h"
+#include "clang/AST/ExprObjC.h"
+#include "clang/AST/ExprCXX.h"
+#include "clang/AST/StmtObjC.h"
+#include "clang/AST/StmtCXX.h"
+#include "clang/AST/EvaluatedExprVisitor.h"
+#include "clang/AST/StmtVisitor.h"
+#include "clang/Analysis/AnalysisContext.h"
+#include "clang/Analysis/CFG.h"
+#include "clang/Analysis/Analyses/ReachableCode.h"
+#include "clang/Analysis/Analyses/CFGReachabilityAnalysis.h"
+#include "clang/Analysis/Analyses/ThreadSafety.h"
+#include "clang/Analysis/CFGStmtMap.h"
+#include "clang/Analysis/Analyses/UninitializedValues.h"
+#include "llvm/ADT/BitVector.h"
+#include "llvm/ADT/FoldingSet.h"
+#include "llvm/ADT/ImmutableMap.h"
+#include "llvm/ADT/PostOrderIterator.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Casting.h"
+#include <algorithm>
+#include <vector>
+
+using namespace clang;
+
+//===----------------------------------------------------------------------===//
+// Unreachable code analysis.
+//===----------------------------------------------------------------------===//
+
+namespace {
+  class UnreachableCodeHandler : public reachable_code::Callback {
+    Sema &S;
+  public:
+    UnreachableCodeHandler(Sema &s) : S(s) {}
+
+    void HandleUnreachable(SourceLocation L, SourceRange R1, SourceRange R2) {
+      S.Diag(L, diag::warn_unreachable) << R1 << R2;
+    }
+  };
+}
+
+/// CheckUnreachable - Check for unreachable code.
+static void CheckUnreachable(Sema &S, AnalysisDeclContext &AC) {
+  UnreachableCodeHandler UC(S);
+  reachable_code::FindUnreachableCode(AC, UC);
+}
+
+//===----------------------------------------------------------------------===//
+// Check for missing return value.
+//===----------------------------------------------------------------------===//
+
+enum ControlFlowKind {
+  UnknownFallThrough,
+  NeverFallThrough,
+  MaybeFallThrough,
+  AlwaysFallThrough,
+  NeverFallThroughOrReturn
+};
+
+/// CheckFallThrough - Check that we don't fall off the end of a
+/// Statement that should return a value.
+///
+/// \returns AlwaysFallThrough iff we always fall off the end of the statement,
+/// MaybeFallThrough iff we might or might not fall off the end,
+/// NeverFallThroughOrReturn iff we never fall off the end of the statement or
+/// return.  We assume NeverFallThrough iff we never fall off the end of the
+/// statement but we may return.  We assume that functions not marked noreturn
+/// will return.
+static ControlFlowKind CheckFallThrough(AnalysisDeclContext &AC) {
+  CFG *cfg = AC.getCFG();
+  if (cfg == 0) return UnknownFallThrough;
+
+  // The CFG leaves in dead things, and we don't want the dead code paths to
+  // confuse us, so we mark all live things first.
+  llvm::BitVector live(cfg->getNumBlockIDs());
+  unsigned count = reachable_code::ScanReachableFromBlock(&cfg->getEntry(),
+                                                          live);
+
+  bool AddEHEdges = AC.getAddEHEdges();
+  if (!AddEHEdges && count != cfg->getNumBlockIDs())
+    // When there are things remaining dead, and we didn't add EH edges
+    // from CallExprs to the catch clauses, we have to go back and
+    // mark them as live.
+    for (CFG::iterator I = cfg->begin(), E = cfg->end(); I != E; ++I) {
+      CFGBlock &b = **I;
+      if (!live[b.getBlockID()]) {
+        if (b.pred_begin() == b.pred_end()) {
+          if (b.getTerminator() && isa<CXXTryStmt>(b.getTerminator()))
+            // When not adding EH edges from calls, catch clauses
+            // can otherwise seem dead.  Avoid noting them as dead.
+            count += reachable_code::ScanReachableFromBlock(&b, live);
+          continue;
+        }
+      }
+    }
+
+  // Now we know what is live, we check the live precessors of the exit block
+  // and look for fall through paths, being careful to ignore normal returns,
+  // and exceptional paths.
+  bool HasLiveReturn = false;
+  bool HasFakeEdge = false;
+  bool HasPlainEdge = false;
+  bool HasAbnormalEdge = false;
+
+  // Ignore default cases that aren't likely to be reachable because all
+  // enums in a switch(X) have explicit case statements.
+  CFGBlock::FilterOptions FO;
+  FO.IgnoreDefaultsWithCoveredEnums = 1;
+
+  for (CFGBlock::filtered_pred_iterator
+	 I = cfg->getExit().filtered_pred_start_end(FO); I.hasMore(); ++I) {
+    const CFGBlock& B = **I;
+    if (!live[B.getBlockID()])
+      continue;
+
+    // Skip blocks which contain an element marked as no-return. They don't
+    // represent actually viable edges into the exit block, so mark them as
+    // abnormal.
+    if (B.hasNoReturnElement()) {
+      HasAbnormalEdge = true;
+      continue;
+    }
+
+    // Destructors can appear after the 'return' in the CFG.  This is
+    // normal.  We need to look pass the destructors for the return
+    // statement (if it exists).
+    CFGBlock::const_reverse_iterator ri = B.rbegin(), re = B.rend();
+
+    for ( ; ri != re ; ++ri)
+      if (isa<CFGStmt>(*ri))
+        break;
+
+    // No more CFGElements in the block?
+    if (ri == re) {
+      if (B.getTerminator() && isa<CXXTryStmt>(B.getTerminator())) {
+        HasAbnormalEdge = true;
+        continue;
+      }
+      // A labeled empty statement, or the entry block...
+      HasPlainEdge = true;
+      continue;
+    }
+
+    CFGStmt CS = cast<CFGStmt>(*ri);
+    const Stmt *S = CS.getStmt();
+    if (isa<ReturnStmt>(S)) {
+      HasLiveReturn = true;
+      continue;
+    }
+    if (isa<ObjCAtThrowStmt>(S)) {
+      HasFakeEdge = true;
+      continue;
+    }
+    if (isa<CXXThrowExpr>(S)) {
+      HasFakeEdge = true;
+      continue;
+    }
+    if (const AsmStmt *AS = dyn_cast<AsmStmt>(S)) {
+      if (AS->isMSAsm()) {
+        HasFakeEdge = true;
+        HasLiveReturn = true;
+        continue;
+      }
+    }
+    if (isa<CXXTryStmt>(S)) {
+      HasAbnormalEdge = true;
+      continue;
+    }
+    if (std::find(B.succ_begin(), B.succ_end(), &cfg->getExit())
+        == B.succ_end()) {
+      HasAbnormalEdge = true;
+      continue;
+    }
+
+    HasPlainEdge = true;
+  }
+  if (!HasPlainEdge) {
+    if (HasLiveReturn)
+      return NeverFallThrough;
+    return NeverFallThroughOrReturn;
+  }
+  if (HasAbnormalEdge || HasFakeEdge || HasLiveReturn)
+    return MaybeFallThrough;
+  // This says AlwaysFallThrough for calls to functions that are not marked
+  // noreturn, that don't return.  If people would like this warning to be more
+  // accurate, such functions should be marked as noreturn.
+  return AlwaysFallThrough;
+}
+
+namespace {
+
+struct CheckFallThroughDiagnostics {
+  unsigned diag_MaybeFallThrough_HasNoReturn;
+  unsigned diag_MaybeFallThrough_ReturnsNonVoid;
+  unsigned diag_AlwaysFallThrough_HasNoReturn;
+  unsigned diag_AlwaysFallThrough_ReturnsNonVoid;
+  unsigned diag_NeverFallThroughOrReturn;
+  enum { Function, Block, Lambda } funMode;
+  SourceLocation FuncLoc;
+
+  static CheckFallThroughDiagnostics MakeForFunction(const Decl *Func) {
+    CheckFallThroughDiagnostics D;
+    D.FuncLoc = Func->getLocation();
+    D.diag_MaybeFallThrough_HasNoReturn =
+      diag::warn_falloff_noreturn_function;
+    D.diag_MaybeFallThrough_ReturnsNonVoid =
+      diag::warn_maybe_falloff_nonvoid_function;
+    D.diag_AlwaysFallThrough_HasNoReturn =
+      diag::warn_falloff_noreturn_function;
+    D.diag_AlwaysFallThrough_ReturnsNonVoid =
+      diag::warn_falloff_nonvoid_function;
+
+    // Don't suggest that virtual functions be marked "noreturn", since they
+    // might be overridden by non-noreturn functions.
+    bool isVirtualMethod = false;
+    if (const CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(Func))
+      isVirtualMethod = Method->isVirtual();
+    
+    // Don't suggest that template instantiations be marked "noreturn"
+    bool isTemplateInstantiation = false;
+    if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(Func))
+      isTemplateInstantiation = Function->isTemplateInstantiation();
+        
+    if (!isVirtualMethod && !isTemplateInstantiation)
+      D.diag_NeverFallThroughOrReturn =
+        diag::warn_suggest_noreturn_function;
+    else
+      D.diag_NeverFallThroughOrReturn = 0;
+    
+    D.funMode = Function;
+    return D;
+  }
+
+  static CheckFallThroughDiagnostics MakeForBlock() {
+    CheckFallThroughDiagnostics D;
+    D.diag_MaybeFallThrough_HasNoReturn =
+      diag::err_noreturn_block_has_return_expr;
+    D.diag_MaybeFallThrough_ReturnsNonVoid =
+      diag::err_maybe_falloff_nonvoid_block;
+    D.diag_AlwaysFallThrough_HasNoReturn =
+      diag::err_noreturn_block_has_return_expr;
+    D.diag_AlwaysFallThrough_ReturnsNonVoid =
+      diag::err_falloff_nonvoid_block;
+    D.diag_NeverFallThroughOrReturn =
+      diag::warn_suggest_noreturn_block;
+    D.funMode = Block;
+    return D;
+  }
+
+  static CheckFallThroughDiagnostics MakeForLambda() {
+    CheckFallThroughDiagnostics D;
+    D.diag_MaybeFallThrough_HasNoReturn =
+      diag::err_noreturn_lambda_has_return_expr;
+    D.diag_MaybeFallThrough_ReturnsNonVoid =
+      diag::warn_maybe_falloff_nonvoid_lambda;
+    D.diag_AlwaysFallThrough_HasNoReturn =
+      diag::err_noreturn_lambda_has_return_expr;
+    D.diag_AlwaysFallThrough_ReturnsNonVoid =
+      diag::warn_falloff_nonvoid_lambda;
+    D.diag_NeverFallThroughOrReturn = 0;
+    D.funMode = Lambda;
+    return D;
+  }
+
+  bool checkDiagnostics(DiagnosticsEngine &D, bool ReturnsVoid,
+                        bool HasNoReturn) const {
+    if (funMode == Function) {
+      return (ReturnsVoid ||
+              D.getDiagnosticLevel(diag::warn_maybe_falloff_nonvoid_function,
+                                   FuncLoc) == DiagnosticsEngine::Ignored)
+        && (!HasNoReturn ||
+            D.getDiagnosticLevel(diag::warn_noreturn_function_has_return_expr,
+                                 FuncLoc) == DiagnosticsEngine::Ignored)
+        && (!ReturnsVoid ||
+            D.getDiagnosticLevel(diag::warn_suggest_noreturn_block, FuncLoc)
+              == DiagnosticsEngine::Ignored);
+    }
+
+    // For blocks / lambdas.
+    return ReturnsVoid && !HasNoReturn
+            && ((funMode == Lambda) ||
+                D.getDiagnosticLevel(diag::warn_suggest_noreturn_block, FuncLoc)
+                  == DiagnosticsEngine::Ignored);
+  }
+};
+
+}
+
+/// CheckFallThroughForFunctionDef - Check that we don't fall off the end of a
+/// function that should return a value.  Check that we don't fall off the end
+/// of a noreturn function.  We assume that functions and blocks not marked
+/// noreturn will return.
+static void CheckFallThroughForBody(Sema &S, const Decl *D, const Stmt *Body,
+                                    const BlockExpr *blkExpr,
+                                    const CheckFallThroughDiagnostics& CD,
+                                    AnalysisDeclContext &AC) {
+
+  bool ReturnsVoid = false;
+  bool HasNoReturn = false;
+
+  if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
+    ReturnsVoid = FD->getResultType()->isVoidType();
+    HasNoReturn = FD->hasAttr<NoReturnAttr>() ||
+       FD->getType()->getAs<FunctionType>()->getNoReturnAttr();
+  }
+  else if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) {
+    ReturnsVoid = MD->getResultType()->isVoidType();
+    HasNoReturn = MD->hasAttr<NoReturnAttr>();
+  }
+  else if (isa<BlockDecl>(D)) {
+    QualType BlockTy = blkExpr->getType();
+    if (const FunctionType *FT =
+          BlockTy->getPointeeType()->getAs<FunctionType>()) {
+      if (FT->getResultType()->isVoidType())
+        ReturnsVoid = true;
+      if (FT->getNoReturnAttr())
+        HasNoReturn = true;
+    }
+  }
+
+  DiagnosticsEngine &Diags = S.getDiagnostics();
+
+  // Short circuit for compilation speed.
+  if (CD.checkDiagnostics(Diags, ReturnsVoid, HasNoReturn))
+      return;
+
+  // FIXME: Function try block
+  if (const CompoundStmt *Compound = dyn_cast<CompoundStmt>(Body)) {
+    switch (CheckFallThrough(AC)) {
+      case UnknownFallThrough:
+        break;
+
+      case MaybeFallThrough:
+        if (HasNoReturn)
+          S.Diag(Compound->getRBracLoc(),
+                 CD.diag_MaybeFallThrough_HasNoReturn);
+        else if (!ReturnsVoid)
+          S.Diag(Compound->getRBracLoc(),
+                 CD.diag_MaybeFallThrough_ReturnsNonVoid);
+        break;
+      case AlwaysFallThrough:
+        if (HasNoReturn)
+          S.Diag(Compound->getRBracLoc(),
+                 CD.diag_AlwaysFallThrough_HasNoReturn);
+        else if (!ReturnsVoid)
+          S.Diag(Compound->getRBracLoc(),
+                 CD.diag_AlwaysFallThrough_ReturnsNonVoid);
+        break;
+      case NeverFallThroughOrReturn:
+        if (ReturnsVoid && !HasNoReturn && CD.diag_NeverFallThroughOrReturn) {
+          if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
+            S.Diag(Compound->getLBracLoc(), CD.diag_NeverFallThroughOrReturn)
+              << 0 << FD;
+          } else if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) {
+            S.Diag(Compound->getLBracLoc(), CD.diag_NeverFallThroughOrReturn)
+              << 1 << MD;
+          } else {
+            S.Diag(Compound->getLBracLoc(), CD.diag_NeverFallThroughOrReturn);
+          }
+        }
+        break;
+      case NeverFallThrough:
+        break;
+    }
+  }
+}
+
+//===----------------------------------------------------------------------===//
+// -Wuninitialized
+//===----------------------------------------------------------------------===//
+
+namespace {
+/// ContainsReference - A visitor class to search for references to
+/// a particular declaration (the needle) within any evaluated component of an
+/// expression (recursively).
+class ContainsReference : public EvaluatedExprVisitor<ContainsReference> {
+  bool FoundReference;
+  const DeclRefExpr *Needle;
+
+public:
+  ContainsReference(ASTContext &Context, const DeclRefExpr *Needle)
+    : EvaluatedExprVisitor<ContainsReference>(Context),
+      FoundReference(false), Needle(Needle) {}
+
+  void VisitExpr(Expr *E) {
+    // Stop evaluating if we already have a reference.
+    if (FoundReference)
+      return;
+
+    EvaluatedExprVisitor<ContainsReference>::VisitExpr(E);
+  }
+
+  void VisitDeclRefExpr(DeclRefExpr *E) {
+    if (E == Needle)
+      FoundReference = true;
+    else
+      EvaluatedExprVisitor<ContainsReference>::VisitDeclRefExpr(E);
+  }
+
+  bool doesContainReference() const { return FoundReference; }
+};
+}
+
+static bool SuggestInitializationFixit(Sema &S, const VarDecl *VD) {
+  QualType VariableTy = VD->getType().getCanonicalType();
+  if (VariableTy->isBlockPointerType() &&
+      !VD->hasAttr<BlocksAttr>()) {
+    S.Diag(VD->getLocation(), diag::note_block_var_fixit_add_initialization) << VD->getDeclName()
+    << FixItHint::CreateInsertion(VD->getLocation(), "__block ");
+    return true;
+  }
+  
+  // Don't issue a fixit if there is already an initializer.
+  if (VD->getInit())
+    return false;
+  
+  // Suggest possible initialization (if any).
+  const char *Init = S.getFixItZeroInitializerForType(VariableTy);
+  if (!Init)
+    return false;
+  SourceLocation Loc = S.PP.getLocForEndOfToken(VD->getLocEnd());
+  
+  S.Diag(Loc, diag::note_var_fixit_add_initialization) << VD->getDeclName()
+    << FixItHint::CreateInsertion(Loc, Init);
+  return true;
+}
+
+/// DiagnoseUninitializedUse -- Helper function for diagnosing uses of an
+/// uninitialized variable. This manages the different forms of diagnostic
+/// emitted for particular types of uses. Returns true if the use was diagnosed
+/// as a warning. If a pariticular use is one we omit warnings for, returns
+/// false.
+static bool DiagnoseUninitializedUse(Sema &S, const VarDecl *VD,
+                                     const Expr *E, bool isAlwaysUninit,
+                                     bool alwaysReportSelfInit = false) {
+  bool isSelfInit = false;
+
+  if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) {
+    if (isAlwaysUninit) {
+      // Inspect the initializer of the variable declaration which is
+      // being referenced prior to its initialization. We emit
+      // specialized diagnostics for self-initialization, and we
+      // specifically avoid warning about self references which take the
+      // form of:
+      //
+      //   int x = x;
+      //
+      // This is used to indicate to GCC that 'x' is intentionally left
+      // uninitialized. Proven code paths which access 'x' in
+      // an uninitialized state after this will still warn.
+      //
+      // TODO: Should we suppress maybe-uninitialized warnings for
+      // variables initialized in this way?
+      if (const Expr *Initializer = VD->getInit()) {
+        if (!alwaysReportSelfInit && DRE == Initializer->IgnoreParenImpCasts())
+          return false;
+
+        ContainsReference CR(S.Context, DRE);
+        CR.Visit(const_cast<Expr*>(Initializer));
+        isSelfInit = CR.doesContainReference();
+      }
+      if (isSelfInit) {
+        S.Diag(DRE->getLocStart(),
+               diag::warn_uninit_self_reference_in_init)
+        << VD->getDeclName() << VD->getLocation() << DRE->getSourceRange();
+      } else {
+        S.Diag(DRE->getLocStart(), diag::warn_uninit_var)
+          << VD->getDeclName() << DRE->getSourceRange();
+      }
+    } else {
+      S.Diag(DRE->getLocStart(), diag::warn_maybe_uninit_var)
+        << VD->getDeclName() << DRE->getSourceRange();
+    }
+  } else {
+    const BlockExpr *BE = cast<BlockExpr>(E);
+    if (VD->getType()->isBlockPointerType() &&
+        !VD->hasAttr<BlocksAttr>())
+      S.Diag(BE->getLocStart(), diag::warn_uninit_byref_blockvar_captured_by_block)
+        << VD->getDeclName();
+    else
+      S.Diag(BE->getLocStart(),
+             isAlwaysUninit ? diag::warn_uninit_var_captured_by_block
+                            : diag::warn_maybe_uninit_var_captured_by_block)
+        << VD->getDeclName();
+  }
+
+  // Report where the variable was declared when the use wasn't within
+  // the initializer of that declaration & we didn't already suggest
+  // an initialization fixit.
+  if (!isSelfInit && !SuggestInitializationFixit(S, VD))
+    S.Diag(VD->getLocStart(), diag::note_uninit_var_def)
+      << VD->getDeclName();
+
+  return true;
+}
+
+typedef std::pair<const Expr*, bool> UninitUse;
+
+namespace {
+struct SLocSort {
+  bool operator()(const UninitUse &a, const UninitUse &b) {
+    SourceLocation aLoc = a.first->getLocStart();
+    SourceLocation bLoc = b.first->getLocStart();
+    return aLoc.getRawEncoding() < bLoc.getRawEncoding();
+  }
+};
+
+class UninitValsDiagReporter : public UninitVariablesHandler {
+  Sema &S;
+  typedef SmallVector<UninitUse, 2> UsesVec;
+  typedef llvm::DenseMap<const VarDecl *, std::pair<UsesVec*, bool> > UsesMap;
+  UsesMap *uses;
+  
+public:
+  UninitValsDiagReporter(Sema &S) : S(S), uses(0) {}
+  ~UninitValsDiagReporter() { 
+    flushDiagnostics();
+  }
+
+  std::pair<UsesVec*, bool> &getUses(const VarDecl *vd) {
+    if (!uses)
+      uses = new UsesMap();
+
+    UsesMap::mapped_type &V = (*uses)[vd];
+    UsesVec *&vec = V.first;
+    if (!vec)
+      vec = new UsesVec();
+    
+    return V;
+  }
+  
+  void handleUseOfUninitVariable(const Expr *ex, const VarDecl *vd,
+                                 bool isAlwaysUninit) {
+    getUses(vd).first->push_back(std::make_pair(ex, isAlwaysUninit));
+  }
+  
+  void handleSelfInit(const VarDecl *vd) {
+    getUses(vd).second = true;    
+  }
+  
+  void flushDiagnostics() {
+    if (!uses)
+      return;
+    
+    for (UsesMap::iterator i = uses->begin(), e = uses->end(); i != e; ++i) {
+      const VarDecl *vd = i->first;
+      const UsesMap::mapped_type &V = i->second;
+
+      UsesVec *vec = V.first;
+      bool hasSelfInit = V.second;
+
+      // Specially handle the case where we have uses of an uninitialized 
+      // variable, but the root cause is an idiomatic self-init.  We want
+      // to report the diagnostic at the self-init since that is the root cause.
+      if (!vec->empty() && hasSelfInit && hasAlwaysUninitializedUse(vec))
+        DiagnoseUninitializedUse(S, vd, vd->getInit()->IgnoreParenCasts(),
+                                 /* isAlwaysUninit */ true,
+                                 /* alwaysReportSelfInit */ true);
+      else {
+        // Sort the uses by their SourceLocations.  While not strictly
+        // guaranteed to produce them in line/column order, this will provide
+        // a stable ordering.
+        std::sort(vec->begin(), vec->end(), SLocSort());
+        
+        for (UsesVec::iterator vi = vec->begin(), ve = vec->end(); vi != ve;
+             ++vi) {
+          if (DiagnoseUninitializedUse(S, vd, vi->first,
+                                        /*isAlwaysUninit=*/vi->second))
+            // Skip further diagnostics for this variable. We try to warn only
+            // on the first point at which a variable is used uninitialized.
+            break;
+        }
+      }
+      
+      // Release the uses vector.
+      delete vec;
+    }
+    delete uses;
+  }
+
+private:
+  static bool hasAlwaysUninitializedUse(const UsesVec* vec) {
+  for (UsesVec::const_iterator i = vec->begin(), e = vec->end(); i != e; ++i) {
+    if (i->second) {
+      return true;
+    }
+  }
+  return false;
+}
+};
+}
+
+
+//===----------------------------------------------------------------------===//
+// -Wthread-safety
+//===----------------------------------------------------------------------===//
+namespace clang {
+namespace thread_safety {
+typedef llvm::SmallVector<PartialDiagnosticAt, 1> OptionalNotes;
+typedef std::pair<PartialDiagnosticAt, OptionalNotes> DelayedDiag;
+typedef std::list<DelayedDiag> DiagList;
+
+struct SortDiagBySourceLocation {
+  SourceManager &SM;
+  SortDiagBySourceLocation(SourceManager &SM) : SM(SM) {}
+
+  bool operator()(const DelayedDiag &left, const DelayedDiag &right) {
+    // Although this call will be slow, this is only called when outputting
+    // multiple warnings.
+    return SM.isBeforeInTranslationUnit(left.first.first, right.first.first);
+  }
+};
+
+namespace {
+class ThreadSafetyReporter : public clang::thread_safety::ThreadSafetyHandler {
+  Sema &S;
+  DiagList Warnings;
+  SourceLocation FunLocation, FunEndLocation;
+
+  // Helper functions
+  void warnLockMismatch(unsigned DiagID, Name LockName, SourceLocation Loc) {
+    // Gracefully handle rare cases when the analysis can't get a more
+    // precise source location.
+    if (!Loc.isValid())
+      Loc = FunLocation;
+    PartialDiagnosticAt Warning(Loc, S.PDiag(DiagID) << LockName);
+    Warnings.push_back(DelayedDiag(Warning, OptionalNotes()));
+  }
+
+ public:
+  ThreadSafetyReporter(Sema &S, SourceLocation FL, SourceLocation FEL)
+    : S(S), FunLocation(FL), FunEndLocation(FEL) {}
+
+  /// \brief Emit all buffered diagnostics in order of sourcelocation.
+  /// We need to output diagnostics produced while iterating through
+  /// the lockset in deterministic order, so this function orders diagnostics
+  /// and outputs them.
+  void emitDiagnostics() {
+    Warnings.sort(SortDiagBySourceLocation(S.getSourceManager()));
+    for (DiagList::iterator I = Warnings.begin(), E = Warnings.end();
+         I != E; ++I) {
+      S.Diag(I->first.first, I->first.second);
+      const OptionalNotes &Notes = I->second;
+      for (unsigned NoteI = 0, NoteN = Notes.size(); NoteI != NoteN; ++NoteI)
+        S.Diag(Notes[NoteI].first, Notes[NoteI].second);
+    }
+  }
+
+  void handleInvalidLockExp(SourceLocation Loc) {
+    PartialDiagnosticAt Warning(Loc,
+                                S.PDiag(diag::warn_cannot_resolve_lock) << Loc);
+    Warnings.push_back(DelayedDiag(Warning, OptionalNotes()));
+  }
+  void handleUnmatchedUnlock(Name LockName, SourceLocation Loc) {
+    warnLockMismatch(diag::warn_unlock_but_no_lock, LockName, Loc);
+  }
+
+  void handleDoubleLock(Name LockName, SourceLocation Loc) {
+    warnLockMismatch(diag::warn_double_lock, LockName, Loc);
+  }
+
+  void handleMutexHeldEndOfScope(Name LockName, SourceLocation LocLocked,
+                                 SourceLocation LocEndOfScope,
+                                 LockErrorKind LEK){
+    unsigned DiagID = 0;
+    switch (LEK) {
+      case LEK_LockedSomePredecessors:
+        DiagID = diag::warn_lock_some_predecessors;
+        break;
+      case LEK_LockedSomeLoopIterations:
+        DiagID = diag::warn_expecting_lock_held_on_loop;
+        break;
+      case LEK_LockedAtEndOfFunction:
+        DiagID = diag::warn_no_unlock;
+        break;
+    }
+    if (LocEndOfScope.isInvalid())
+      LocEndOfScope = FunEndLocation;
+
+    PartialDiagnosticAt Warning(LocEndOfScope, S.PDiag(DiagID) << LockName);
+    PartialDiagnosticAt Note(LocLocked, S.PDiag(diag::note_locked_here));
+    Warnings.push_back(DelayedDiag(Warning, OptionalNotes(1, Note)));
+  }
+
+
+  void handleExclusiveAndShared(Name LockName, SourceLocation Loc1,
+                                SourceLocation Loc2) {
+    PartialDiagnosticAt Warning(
+      Loc1, S.PDiag(diag::warn_lock_exclusive_and_shared) << LockName);
+    PartialDiagnosticAt Note(
+      Loc2, S.PDiag(diag::note_lock_exclusive_and_shared) << LockName);
+    Warnings.push_back(DelayedDiag(Warning, OptionalNotes(1, Note)));
+  }
+
+  void handleNoMutexHeld(const NamedDecl *D, ProtectedOperationKind POK,
+                         AccessKind AK, SourceLocation Loc) {
+    assert((POK == POK_VarAccess || POK == POK_VarDereference)
+             && "Only works for variables");
+    unsigned DiagID = POK == POK_VarAccess?
+                        diag::warn_variable_requires_any_lock:
+                        diag::warn_var_deref_requires_any_lock;
+    PartialDiagnosticAt Warning(Loc, S.PDiag(DiagID)
+      << D->getName() << getLockKindFromAccessKind(AK));
+    Warnings.push_back(DelayedDiag(Warning, OptionalNotes()));
+  }
+
+  void handleMutexNotHeld(const NamedDecl *D, ProtectedOperationKind POK,
+                          Name LockName, LockKind LK, SourceLocation Loc) {
+    unsigned DiagID = 0;
+    switch (POK) {
+      case POK_VarAccess:
+        DiagID = diag::warn_variable_requires_lock;
+        break;
+      case POK_VarDereference:
+        DiagID = diag::warn_var_deref_requires_lock;
+        break;
+      case POK_FunctionCall:
+        DiagID = diag::warn_fun_requires_lock;
+        break;
+    }
+    PartialDiagnosticAt Warning(Loc, S.PDiag(DiagID)
+      << D->getName() << LockName << LK);
+    Warnings.push_back(DelayedDiag(Warning, OptionalNotes()));
+  }
+
+  void handleFunExcludesLock(Name FunName, Name LockName, SourceLocation Loc) {
+    PartialDiagnosticAt Warning(Loc,
+      S.PDiag(diag::warn_fun_excludes_mutex) << FunName << LockName);
+    Warnings.push_back(DelayedDiag(Warning, OptionalNotes()));
+  }
+};
+}
+}
+}
+
+//===----------------------------------------------------------------------===//
+// AnalysisBasedWarnings - Worker object used by Sema to execute analysis-based
+//  warnings on a function, method, or block.
+//===----------------------------------------------------------------------===//
+
+clang::sema::AnalysisBasedWarnings::Policy::Policy() {
+  enableCheckFallThrough = 1;
+  enableCheckUnreachable = 0;
+  enableThreadSafetyAnalysis = 0;
+}
+
+clang::sema::AnalysisBasedWarnings::AnalysisBasedWarnings(Sema &s)
+  : S(s),
+    NumFunctionsAnalyzed(0),
+    NumFunctionsWithBadCFGs(0),
+    NumCFGBlocks(0),
+    MaxCFGBlocksPerFunction(0),
+    NumUninitAnalysisFunctions(0),
+    NumUninitAnalysisVariables(0),
+    MaxUninitAnalysisVariablesPerFunction(0),
+    NumUninitAnalysisBlockVisits(0),
+    MaxUninitAnalysisBlockVisitsPerFunction(0) {
+  DiagnosticsEngine &D = S.getDiagnostics();
+  DefaultPolicy.enableCheckUnreachable = (unsigned)
+    (D.getDiagnosticLevel(diag::warn_unreachable, SourceLocation()) !=
+        DiagnosticsEngine::Ignored);
+  DefaultPolicy.enableThreadSafetyAnalysis = (unsigned)
+    (D.getDiagnosticLevel(diag::warn_double_lock, SourceLocation()) !=
+     DiagnosticsEngine::Ignored);
+
+}
+
+static void flushDiagnostics(Sema &S, sema::FunctionScopeInfo *fscope) {
+  for (SmallVectorImpl<sema::PossiblyUnreachableDiag>::iterator
+       i = fscope->PossiblyUnreachableDiags.begin(),
+       e = fscope->PossiblyUnreachableDiags.end();
+       i != e; ++i) {
+    const sema::PossiblyUnreachableDiag &D = *i;
+    S.Diag(D.Loc, D.PD);
+  }
+}
+
+void clang::sema::
+AnalysisBasedWarnings::IssueWarnings(sema::AnalysisBasedWarnings::Policy P,
+                                     sema::FunctionScopeInfo *fscope,
+                                     const Decl *D, const BlockExpr *blkExpr) {
+
+  // We avoid doing analysis-based warnings when there are errors for
+  // two reasons:
+  // (1) The CFGs often can't be constructed (if the body is invalid), so
+  //     don't bother trying.
+  // (2) The code already has problems; running the analysis just takes more
+  //     time.
+  DiagnosticsEngine &Diags = S.getDiagnostics();
+
+  // Do not do any analysis for declarations in system headers if we are
+  // going to just ignore them.
+  if (Diags.getSuppressSystemWarnings() &&
+      S.SourceMgr.isInSystemHeader(D->getLocation()))
+    return;
+
+  // For code in dependent contexts, we'll do this at instantiation time.
+  if (cast<DeclContext>(D)->isDependentContext())
+    return;
+
+  if (Diags.hasErrorOccurred() || Diags.hasFatalErrorOccurred()) {
+    // Flush out any possibly unreachable diagnostics.
+    flushDiagnostics(S, fscope);
+    return;
+  }
+  
+  const Stmt *Body = D->getBody();
+  assert(Body);
+
+  AnalysisDeclContext AC(/* AnalysisDeclContextManager */ 0,  D, 0);
+
+  // Don't generate EH edges for CallExprs as we'd like to avoid the n^2
+  // explosion for destrutors that can result and the compile time hit.
+  AC.getCFGBuildOptions().PruneTriviallyFalseEdges = true;
+  AC.getCFGBuildOptions().AddEHEdges = false;
+  AC.getCFGBuildOptions().AddInitializers = true;
+  AC.getCFGBuildOptions().AddImplicitDtors = true;
+  
+  // Force that certain expressions appear as CFGElements in the CFG.  This
+  // is used to speed up various analyses.
+  // FIXME: This isn't the right factoring.  This is here for initial
+  // prototyping, but we need a way for analyses to say what expressions they
+  // expect to always be CFGElements and then fill in the BuildOptions
+  // appropriately.  This is essentially a layering violation.
+  if (P.enableCheckUnreachable || P.enableThreadSafetyAnalysis) {
+    // Unreachable code analysis and thread safety require a linearized CFG.
+    AC.getCFGBuildOptions().setAllAlwaysAdd();
+  }
+  else {
+    AC.getCFGBuildOptions()
+      .setAlwaysAdd(Stmt::BinaryOperatorClass)
+      .setAlwaysAdd(Stmt::BlockExprClass)
+      .setAlwaysAdd(Stmt::CStyleCastExprClass)
+      .setAlwaysAdd(Stmt::DeclRefExprClass)
+      .setAlwaysAdd(Stmt::ImplicitCastExprClass)
+      .setAlwaysAdd(Stmt::UnaryOperatorClass);
+  }
+
+  // Construct the analysis context with the specified CFG build options.
+  
+  // Emit delayed diagnostics.
+  if (!fscope->PossiblyUnreachableDiags.empty()) {
+    bool analyzed = false;
+
+    // Register the expressions with the CFGBuilder.
+    for (SmallVectorImpl<sema::PossiblyUnreachableDiag>::iterator
+         i = fscope->PossiblyUnreachableDiags.begin(),
+         e = fscope->PossiblyUnreachableDiags.end();
+         i != e; ++i) {
+      if (const Stmt *stmt = i->stmt)
+        AC.registerForcedBlockExpression(stmt);
+    }
+
+    if (AC.getCFG()) {
+      analyzed = true;
+      for (SmallVectorImpl<sema::PossiblyUnreachableDiag>::iterator
+            i = fscope->PossiblyUnreachableDiags.begin(),
+            e = fscope->PossiblyUnreachableDiags.end();
+            i != e; ++i)
+      {
+        const sema::PossiblyUnreachableDiag &D = *i;
+        bool processed = false;
+        if (const Stmt *stmt = i->stmt) {
+          const CFGBlock *block = AC.getBlockForRegisteredExpression(stmt);
+          CFGReverseBlockReachabilityAnalysis *cra =
+              AC.getCFGReachablityAnalysis();
+          // FIXME: We should be able to assert that block is non-null, but
+          // the CFG analysis can skip potentially-evaluated expressions in
+          // edge cases; see test/Sema/vla-2.c.
+          if (block && cra) {
+            // Can this block be reached from the entrance?
+            if (cra->isReachable(&AC.getCFG()->getEntry(), block))
+              S.Diag(D.Loc, D.PD);
+            processed = true;
+          }
+        }
+        if (!processed) {
+          // Emit the warning anyway if we cannot map to a basic block.
+          S.Diag(D.Loc, D.PD);
+        }
+      }
+    }
+
+    if (!analyzed)
+      flushDiagnostics(S, fscope);
+  }
+  
+  
+  // Warning: check missing 'return'
+  if (P.enableCheckFallThrough) {
+    const CheckFallThroughDiagnostics &CD =
+      (isa<BlockDecl>(D) ? CheckFallThroughDiagnostics::MakeForBlock()
+       : (isa<CXXMethodDecl>(D) &&
+          cast<CXXMethodDecl>(D)->getOverloadedOperator() == OO_Call &&
+          cast<CXXMethodDecl>(D)->getParent()->isLambda())
+            ? CheckFallThroughDiagnostics::MakeForLambda()
+            : CheckFallThroughDiagnostics::MakeForFunction(D));
+    CheckFallThroughForBody(S, D, Body, blkExpr, CD, AC);
+  }
+
+  // Warning: check for unreachable code
+  if (P.enableCheckUnreachable) {
+    // Only check for unreachable code on non-template instantiations.
+    // Different template instantiations can effectively change the control-flow
+    // and it is very difficult to prove that a snippet of code in a template
+    // is unreachable for all instantiations.
+    bool isTemplateInstantiation = false;
+    if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(D))
+      isTemplateInstantiation = Function->isTemplateInstantiation();
+    if (!isTemplateInstantiation)
+      CheckUnreachable(S, AC);
+  }
+
+  // Check for thread safety violations
+  if (P.enableThreadSafetyAnalysis) {
+    SourceLocation FL = AC.getDecl()->getLocation();
+    SourceLocation FEL = AC.getDecl()->getLocEnd();
+    thread_safety::ThreadSafetyReporter Reporter(S, FL, FEL);
+    thread_safety::runThreadSafetyAnalysis(AC, Reporter);
+    Reporter.emitDiagnostics();
+  }
+
+  if (Diags.getDiagnosticLevel(diag::warn_uninit_var, D->getLocStart())
+      != DiagnosticsEngine::Ignored ||
+      Diags.getDiagnosticLevel(diag::warn_maybe_uninit_var, D->getLocStart())
+      != DiagnosticsEngine::Ignored) {
+    if (CFG *cfg = AC.getCFG()) {
+      UninitValsDiagReporter reporter(S);
+      UninitVariablesAnalysisStats stats;
+      std::memset(&stats, 0, sizeof(UninitVariablesAnalysisStats));
+      runUninitializedVariablesAnalysis(*cast<DeclContext>(D), *cfg, AC,
+                                        reporter, stats);
+
+      if (S.CollectStats && stats.NumVariablesAnalyzed > 0) {
+        ++NumUninitAnalysisFunctions;
+        NumUninitAnalysisVariables += stats.NumVariablesAnalyzed;
+        NumUninitAnalysisBlockVisits += stats.NumBlockVisits;
+        MaxUninitAnalysisVariablesPerFunction =
+            std::max(MaxUninitAnalysisVariablesPerFunction,
+                     stats.NumVariablesAnalyzed);
+        MaxUninitAnalysisBlockVisitsPerFunction =
+            std::max(MaxUninitAnalysisBlockVisitsPerFunction,
+                     stats.NumBlockVisits);
+      }
+    }
+  }
+
+  // Collect statistics about the CFG if it was built.
+  if (S.CollectStats && AC.isCFGBuilt()) {
+    ++NumFunctionsAnalyzed;
+    if (CFG *cfg = AC.getCFG()) {
+      // If we successfully built a CFG for this context, record some more
+      // detail information about it.
+      NumCFGBlocks += cfg->getNumBlockIDs();
+      MaxCFGBlocksPerFunction = std::max(MaxCFGBlocksPerFunction,
+                                         cfg->getNumBlockIDs());
+    } else {
+      ++NumFunctionsWithBadCFGs;
+    }
+  }
+}
+
+void clang::sema::AnalysisBasedWarnings::PrintStats() const {
+  llvm::errs() << "\n*** Analysis Based Warnings Stats:\n";
+
+  unsigned NumCFGsBuilt = NumFunctionsAnalyzed - NumFunctionsWithBadCFGs;
+  unsigned AvgCFGBlocksPerFunction =
+      !NumCFGsBuilt ? 0 : NumCFGBlocks/NumCFGsBuilt;
+  llvm::errs() << NumFunctionsAnalyzed << " functions analyzed ("
+               << NumFunctionsWithBadCFGs << " w/o CFGs).\n"
+               << "  " << NumCFGBlocks << " CFG blocks built.\n"
+               << "  " << AvgCFGBlocksPerFunction
+               << " average CFG blocks per function.\n"
+               << "  " << MaxCFGBlocksPerFunction
+               << " max CFG blocks per function.\n";
+
+  unsigned AvgUninitVariablesPerFunction = !NumUninitAnalysisFunctions ? 0
+      : NumUninitAnalysisVariables/NumUninitAnalysisFunctions;
+  unsigned AvgUninitBlockVisitsPerFunction = !NumUninitAnalysisFunctions ? 0
+      : NumUninitAnalysisBlockVisits/NumUninitAnalysisFunctions;
+  llvm::errs() << NumUninitAnalysisFunctions
+               << " functions analyzed for uninitialiazed variables\n"
+               << "  " << NumUninitAnalysisVariables << " variables analyzed.\n"
+               << "  " << AvgUninitVariablesPerFunction
+               << " average variables per function.\n"
+               << "  " << MaxUninitAnalysisVariablesPerFunction
+               << " max variables per function.\n"
+               << "  " << NumUninitAnalysisBlockVisits << " block visits.\n"
+               << "  " << AvgUninitBlockVisitsPerFunction
+               << " average block visits per function.\n"
+               << "  " << MaxUninitAnalysisBlockVisitsPerFunction
+               << " max block visits per function.\n";
+}
diff --git a/clang/lib/Sema/AttributeList.cpp b/clang/lib/Sema/AttributeList.cpp
new file mode 100644
index 0000000..f142ab4
--- /dev/null
+++ b/clang/lib/Sema/AttributeList.cpp
@@ -0,0 +1,126 @@
+//===--- AttributeList.cpp --------------------------------------*- 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 AttributeList class implementation
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Sema/AttributeList.h"
+#include "clang/AST/Expr.h"
+#include "clang/Basic/IdentifierTable.h"
+#include "llvm/ADT/StringSwitch.h"
+using namespace clang;
+
+size_t AttributeList::allocated_size() const {
+  if (IsAvailability) return AttributeFactory::AvailabilityAllocSize;
+  return (sizeof(AttributeList) + NumArgs * sizeof(Expr*));
+}
+
+AttributeFactory::AttributeFactory() {
+  // Go ahead and configure all the inline capacity.  This is just a memset.
+  FreeLists.resize(InlineFreeListsCapacity);
+}
+AttributeFactory::~AttributeFactory() {}
+
+static size_t getFreeListIndexForSize(size_t size) {
+  assert(size >= sizeof(AttributeList));
+  assert((size % sizeof(void*)) == 0);
+  return ((size - sizeof(AttributeList)) / sizeof(void*));
+}
+
+void *AttributeFactory::allocate(size_t size) {
+  // Check for a previously reclaimed attribute.
+  size_t index = getFreeListIndexForSize(size);
+  if (index < FreeLists.size()) {
+    if (AttributeList *attr = FreeLists[index]) {
+      FreeLists[index] = attr->NextInPool;
+      return attr;
+    }
+  }
+
+  // Otherwise, allocate something new.
+  return Alloc.Allocate(size, llvm::AlignOf<AttributeFactory>::Alignment);
+}
+
+void AttributeFactory::reclaimPool(AttributeList *cur) {
+  assert(cur && "reclaiming empty pool!");
+  do {
+    // Read this here, because we're going to overwrite NextInPool
+    // when we toss 'cur' into the appropriate queue.
+    AttributeList *next = cur->NextInPool;
+
+    size_t size = cur->allocated_size();
+    size_t freeListIndex = getFreeListIndexForSize(size);
+
+    // Expand FreeLists to the appropriate size, if required.
+    if (freeListIndex >= FreeLists.size())
+      FreeLists.resize(freeListIndex+1);
+
+    // Add 'cur' to the appropriate free-list.
+    cur->NextInPool = FreeLists[freeListIndex];
+    FreeLists[freeListIndex] = cur;
+    
+    cur = next;
+  } while (cur);
+}
+
+void AttributePool::takePool(AttributeList *pool) {
+  assert(pool);
+
+  // Fast path:  this pool is empty.
+  if (!Head) {
+    Head = pool;
+    return;
+  }
+
+  // Reverse the pool onto the current head.  This optimizes for the
+  // pattern of pulling a lot of pools into a single pool.
+  do {
+    AttributeList *next = pool->NextInPool;
+    pool->NextInPool = Head;
+    Head = pool;
+    pool = next;
+  } while (pool);
+}
+
+AttributeList *
+AttributePool::createIntegerAttribute(ASTContext &C, IdentifierInfo *Name,
+                                      SourceLocation TokLoc, int Arg) {
+  Expr *IArg = IntegerLiteral::Create(C, llvm::APInt(32, (uint64_t) Arg),
+                                      C.IntTy, TokLoc);
+  return create(Name, TokLoc, 0, TokLoc, 0, TokLoc, &IArg, 1, 0);
+}
+
+AttributeList::Kind AttributeList::getKind(const IdentifierInfo *Name) {
+  StringRef AttrName = Name->getName();
+
+  // Normalize the attribute name, __foo__ becomes foo.
+  if (AttrName.startswith("__") && AttrName.endswith("__") &&
+      AttrName.size() >= 4)
+    AttrName = AttrName.substr(2, AttrName.size() - 4);
+
+  return llvm::StringSwitch<AttributeList::Kind>(AttrName)
+    #include "clang/Sema/AttrParsedAttrKinds.inc"
+    .Case("address_space", AT_address_space)
+    .Case("align", AT_aligned) // FIXME - should it be "aligned"?
+    .Case("base_check", AT_base_check)
+    .Case("bounded", IgnoredAttribute)       // OpenBSD
+    .Case("__const", AT_const) // some GCC headers do contain this spelling
+    .Case("cf_returns_autoreleased", AT_cf_returns_autoreleased)
+    .Case("mode", AT_mode)
+    .Case("vec_type_hint", IgnoredAttribute)
+    .Case("ext_vector_type", AT_ext_vector_type)
+    .Case("neon_vector_type", AT_neon_vector_type)
+    .Case("neon_polyvector_type", AT_neon_polyvector_type)
+    .Case("opencl_image_access", AT_opencl_image_access)
+    .Case("objc_gc", AT_objc_gc)
+    .Case("objc_ownership", AT_objc_ownership)
+    .Case("vector_size", AT_vector_size)
+    .Default(UnknownAttribute);
+}
diff --git a/clang/lib/Sema/CMakeLists.txt b/clang/lib/Sema/CMakeLists.txt
new file mode 100644
index 0000000..07734c7
--- /dev/null
+++ b/clang/lib/Sema/CMakeLists.txt
@@ -0,0 +1,58 @@
+set(LLVM_USED_LIBS
+  clangAST
+  clangAnalysis
+  clangBasic
+  clangEdit
+  clangLex
+  )
+
+add_clang_library(clangSema
+  AnalysisBasedWarnings.cpp
+  AttributeList.cpp
+  CodeCompleteConsumer.cpp
+  DeclSpec.cpp
+  DelayedDiagnostic.cpp
+  IdentifierResolver.cpp
+  JumpDiagnostics.cpp
+  Scope.cpp
+  Sema.cpp
+  SemaAccess.cpp
+  SemaAttr.cpp
+  SemaCXXScopeSpec.cpp
+  SemaCast.cpp
+  SemaChecking.cpp
+  SemaCodeComplete.cpp
+  SemaConsumer.cpp
+  SemaDecl.cpp
+  SemaDeclAttr.cpp
+  SemaDeclCXX.cpp
+  SemaDeclObjC.cpp
+  SemaExceptionSpec.cpp
+  SemaExpr.cpp
+  SemaExprCXX.cpp
+  SemaExprMember.cpp
+  SemaExprObjC.cpp
+  SemaFixItUtils.cpp
+  SemaInit.cpp
+  SemaLambda.cpp
+  SemaLookup.cpp
+  SemaObjCProperty.cpp
+  SemaOverload.cpp
+  SemaPseudoObject.cpp
+  SemaStmt.cpp
+  SemaStmtAttr.cpp
+  SemaTemplate.cpp
+  SemaTemplateDeduction.cpp
+  SemaTemplateInstantiate.cpp
+  SemaTemplateInstantiateDecl.cpp
+  SemaTemplateVariadic.cpp
+  SemaType.cpp
+  TargetAttributesSema.cpp
+  )
+
+add_dependencies(clangSema ClangARMNeon ClangAttrClasses ClangAttrList 
+                 ClangDiagnosticSema ClangDeclNodes ClangStmtNodes 
+                 ClangAttrTemplateInstantiate ClangAttrParsedAttrList 
+				 ClangAttrParsedAttrKinds)
+
+
diff --git a/clang/lib/Sema/CodeCompleteConsumer.cpp b/clang/lib/Sema/CodeCompleteConsumer.cpp
new file mode 100644
index 0000000..ce9bbb9
--- /dev/null
+++ b/clang/lib/Sema/CodeCompleteConsumer.cpp
@@ -0,0 +1,641 @@
+//===--- CodeCompleteConsumer.cpp - Code Completion Interface ---*- 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 CodeCompleteConsumer class.
+//
+//===----------------------------------------------------------------------===//
+#include "clang/Sema/CodeCompleteConsumer.h"
+#include "clang/Sema/Scope.h"
+#include "clang/Sema/Sema.h"
+#include "clang/AST/DeclCXX.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/AST/DeclTemplate.h"
+#include "clang/Lex/Preprocessor.h"
+#include "clang-c/Index.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/Twine.h"
+#include "llvm/Support/raw_ostream.h"
+#include <algorithm>
+#include <cstring>
+#include <functional>
+
+using namespace clang;
+
+//===----------------------------------------------------------------------===//
+// Code completion context implementation
+//===----------------------------------------------------------------------===//
+
+bool CodeCompletionContext::wantConstructorResults() const {
+  switch (Kind) {
+  case CCC_Recovery:
+  case CCC_Statement:
+  case CCC_Expression:
+  case CCC_ObjCMessageReceiver:
+  case CCC_ParenthesizedExpression:
+    return true;
+    
+  case CCC_TopLevel:
+  case CCC_ObjCInterface:
+  case CCC_ObjCImplementation:
+  case CCC_ObjCIvarList:
+  case CCC_ClassStructUnion:
+  case CCC_DotMemberAccess:
+  case CCC_ArrowMemberAccess:
+  case CCC_ObjCPropertyAccess:
+  case CCC_EnumTag:
+  case CCC_UnionTag:
+  case CCC_ClassOrStructTag:
+  case CCC_ObjCProtocolName:
+  case CCC_Namespace:
+  case CCC_Type:
+  case CCC_Name:
+  case CCC_PotentiallyQualifiedName:
+  case CCC_MacroName:
+  case CCC_MacroNameUse:
+  case CCC_PreprocessorExpression:
+  case CCC_PreprocessorDirective:
+  case CCC_NaturalLanguage:
+  case CCC_SelectorName:
+  case CCC_TypeQualifiers:
+  case CCC_Other:
+  case CCC_OtherWithMacros:
+  case CCC_ObjCInstanceMessage:
+  case CCC_ObjCClassMessage:
+  case CCC_ObjCInterfaceName:
+  case CCC_ObjCCategoryName:
+    return false;
+  }
+
+  llvm_unreachable("Invalid CodeCompletionContext::Kind!");
+}
+
+//===----------------------------------------------------------------------===//
+// Code completion string implementation
+//===----------------------------------------------------------------------===//
+CodeCompletionString::Chunk::Chunk(ChunkKind Kind, const char *Text) 
+  : Kind(Kind), Text("")
+{
+  switch (Kind) {
+  case CK_TypedText:
+  case CK_Text:
+  case CK_Placeholder:
+  case CK_Informative:
+  case CK_ResultType:
+  case CK_CurrentParameter:
+    this->Text = Text;
+    break;
+
+  case CK_Optional:
+    llvm_unreachable("Optional strings cannot be created from text");
+      
+  case CK_LeftParen:
+    this->Text = "(";
+    break;
+
+  case CK_RightParen:
+    this->Text = ")";
+    break;
+
+  case CK_LeftBracket:
+    this->Text = "[";
+    break;
+    
+  case CK_RightBracket:
+    this->Text = "]";
+    break;
+    
+  case CK_LeftBrace:
+    this->Text = "{";
+    break;
+
+  case CK_RightBrace:
+    this->Text = "}";
+    break;
+
+  case CK_LeftAngle:
+    this->Text = "<";
+    break;
+    
+  case CK_RightAngle:
+    this->Text = ">";
+    break;
+      
+  case CK_Comma:
+    this->Text = ", ";
+    break;
+
+  case CK_Colon:
+    this->Text = ":";
+    break;
+
+  case CK_SemiColon:
+    this->Text = ";";
+    break;
+
+  case CK_Equal:
+    this->Text = " = ";
+    break;
+
+  case CK_HorizontalSpace:
+    this->Text = " ";
+    break;
+
+  case CK_VerticalSpace:
+    this->Text = "\n";
+    break;
+  }
+}
+
+CodeCompletionString::Chunk
+CodeCompletionString::Chunk::CreateText(const char *Text) {
+  return Chunk(CK_Text, Text);
+}
+
+CodeCompletionString::Chunk 
+CodeCompletionString::Chunk::CreateOptional(CodeCompletionString *Optional) {
+  Chunk Result;
+  Result.Kind = CK_Optional;
+  Result.Optional = Optional;
+  return Result;
+}
+
+CodeCompletionString::Chunk 
+CodeCompletionString::Chunk::CreatePlaceholder(const char *Placeholder) {
+  return Chunk(CK_Placeholder, Placeholder);
+}
+
+CodeCompletionString::Chunk 
+CodeCompletionString::Chunk::CreateInformative(const char *Informative) {
+  return Chunk(CK_Informative, Informative);
+}
+
+CodeCompletionString::Chunk 
+CodeCompletionString::Chunk::CreateResultType(const char *ResultType) {
+  return Chunk(CK_ResultType, ResultType);
+}
+
+CodeCompletionString::Chunk 
+CodeCompletionString::Chunk::CreateCurrentParameter(
+                                                const char *CurrentParameter) {
+  return Chunk(CK_CurrentParameter, CurrentParameter);
+}
+
+CodeCompletionString::CodeCompletionString(const Chunk *Chunks, 
+                                           unsigned NumChunks,
+                                           unsigned Priority, 
+                                           CXAvailabilityKind Availability,
+                                           const char **Annotations,
+                                           unsigned NumAnnotations,
+                                           CXCursorKind ParentKind,
+                                           StringRef ParentName)
+  : NumChunks(NumChunks), NumAnnotations(NumAnnotations),
+    Priority(Priority), Availability(Availability), ParentKind(ParentKind),
+    ParentName(ParentName)
+{ 
+  assert(NumChunks <= 0xffff);
+  assert(NumAnnotations <= 0xffff);
+
+  Chunk *StoredChunks = reinterpret_cast<Chunk *>(this + 1);
+  for (unsigned I = 0; I != NumChunks; ++I)
+    StoredChunks[I] = Chunks[I];
+
+  const char **StoredAnnotations = reinterpret_cast<const char **>(StoredChunks + NumChunks);
+  for (unsigned I = 0; I != NumAnnotations; ++I)
+    StoredAnnotations[I] = Annotations[I];
+}
+
+unsigned CodeCompletionString::getAnnotationCount() const {
+  return NumAnnotations;
+}
+
+const char *CodeCompletionString::getAnnotation(unsigned AnnotationNr) const {
+  if (AnnotationNr < NumAnnotations)
+    return reinterpret_cast<const char * const*>(end())[AnnotationNr];
+  else
+    return 0;
+}
+
+
+std::string CodeCompletionString::getAsString() const {
+  std::string Result;
+  llvm::raw_string_ostream OS(Result);
+                          
+  for (iterator C = begin(), CEnd = end(); C != CEnd; ++C) {
+    switch (C->Kind) {
+    case CK_Optional: OS << "{#" << C->Optional->getAsString() << "#}"; break;
+    case CK_Placeholder: OS << "<#" << C->Text << "#>"; break;
+        
+    case CK_Informative: 
+    case CK_ResultType:
+      OS << "[#" << C->Text << "#]"; 
+      break;
+        
+    case CK_CurrentParameter: OS << "<#" << C->Text << "#>"; break;
+    default: OS << C->Text; break;
+    }
+  }
+  return OS.str();
+}
+
+const char *CodeCompletionString::getTypedText() const {
+  for (iterator C = begin(), CEnd = end(); C != CEnd; ++C)
+    if (C->Kind == CK_TypedText)
+      return C->Text;
+  
+  return 0;
+}
+
+const char *CodeCompletionAllocator::CopyString(StringRef String) {
+  char *Mem = (char *)Allocate(String.size() + 1, 1);
+  std::copy(String.begin(), String.end(), Mem);
+  Mem[String.size()] = 0;
+  return Mem;
+}
+
+const char *CodeCompletionAllocator::CopyString(Twine String) {
+  // FIXME: It would be more efficient to teach Twine to tell us its size and
+  // then add a routine there to fill in an allocated char* with the contents
+  // of the string.
+  SmallString<128> Data;
+  return CopyString(String.toStringRef(Data));
+}
+
+StringRef CodeCompletionTUInfo::getParentName(DeclContext *DC) {
+  NamedDecl *ND = dyn_cast<NamedDecl>(DC);
+  if (!ND)
+    return StringRef();
+  
+  // Check whether we've already cached the parent name.
+  StringRef &CachedParentName = ParentNames[DC];
+  if (!CachedParentName.empty())
+    return CachedParentName;
+
+  // If we already processed this DeclContext and assigned empty to it, the
+  // data pointer will be non-null.
+  if (CachedParentName.data() != 0)
+    return StringRef();
+
+  // Find the interesting names.
+  llvm::SmallVector<DeclContext *, 2> Contexts;
+  while (DC && !DC->isFunctionOrMethod()) {
+    if (NamedDecl *ND = dyn_cast<NamedDecl>(DC)) {
+      if (ND->getIdentifier())
+        Contexts.push_back(DC);
+    }
+    
+    DC = DC->getParent();
+  }
+
+  {
+    llvm::SmallString<128> S;
+    llvm::raw_svector_ostream OS(S);
+    bool First = true;
+    for (unsigned I = Contexts.size(); I != 0; --I) {
+      if (First)
+        First = false;
+      else {
+        OS << "::";
+      }
+      
+      DeclContext *CurDC = Contexts[I-1];
+      if (ObjCCategoryImplDecl *CatImpl = dyn_cast<ObjCCategoryImplDecl>(CurDC))
+        CurDC = CatImpl->getCategoryDecl();
+      
+      if (ObjCCategoryDecl *Cat = dyn_cast<ObjCCategoryDecl>(CurDC)) {
+        ObjCInterfaceDecl *Interface = Cat->getClassInterface();
+        if (!Interface) {
+          // Assign an empty StringRef but with non-null data to distinguish
+          // between empty because we didn't process the DeclContext yet.
+          CachedParentName = StringRef((const char *)~0U, 0);
+          return StringRef();
+        }
+        
+        OS << Interface->getName() << '(' << Cat->getName() << ')';
+      } else {
+        OS << cast<NamedDecl>(CurDC)->getName();
+      }
+    }
+    
+    CachedParentName = AllocatorRef->CopyString(OS.str());
+  }
+
+  return CachedParentName;
+}
+
+CodeCompletionString *CodeCompletionBuilder::TakeString() {
+  void *Mem = getAllocator().Allocate(
+                  sizeof(CodeCompletionString) + sizeof(Chunk) * Chunks.size()
+                                    + sizeof(const char *) * Annotations.size(),
+                                 llvm::alignOf<CodeCompletionString>());
+  CodeCompletionString *Result 
+    = new (Mem) CodeCompletionString(Chunks.data(), Chunks.size(),
+                                     Priority, Availability,
+                                     Annotations.data(), Annotations.size(),
+                                     ParentKind, ParentName);
+  Chunks.clear();
+  return Result;
+}
+
+void CodeCompletionBuilder::AddTypedTextChunk(const char *Text) {
+  Chunks.push_back(Chunk(CodeCompletionString::CK_TypedText, Text));
+}
+
+void CodeCompletionBuilder::AddTextChunk(const char *Text) {
+  Chunks.push_back(Chunk::CreateText(Text));
+}
+
+void CodeCompletionBuilder::AddOptionalChunk(CodeCompletionString *Optional) {
+  Chunks.push_back(Chunk::CreateOptional(Optional));
+}
+
+void CodeCompletionBuilder::AddPlaceholderChunk(const char *Placeholder) {
+  Chunks.push_back(Chunk::CreatePlaceholder(Placeholder));
+}
+
+void CodeCompletionBuilder::AddInformativeChunk(const char *Text) {
+  Chunks.push_back(Chunk::CreateInformative(Text));
+}
+
+void CodeCompletionBuilder::AddResultTypeChunk(const char *ResultType) {
+  Chunks.push_back(Chunk::CreateResultType(ResultType));
+}
+
+void
+CodeCompletionBuilder::AddCurrentParameterChunk(const char *CurrentParameter) {
+  Chunks.push_back(Chunk::CreateCurrentParameter(CurrentParameter));
+}
+
+void CodeCompletionBuilder::AddChunk(CodeCompletionString::ChunkKind CK,
+                                     const char *Text) {
+  Chunks.push_back(Chunk(CK, Text));
+}
+
+void CodeCompletionBuilder::addParentContext(DeclContext *DC) {
+  if (DC->isTranslationUnit()) {
+    ParentKind = CXCursor_TranslationUnit;
+    return;
+  }
+  
+  if (DC->isFunctionOrMethod())
+    return;
+  
+  NamedDecl *ND = dyn_cast<NamedDecl>(DC);
+  if (!ND)
+    return;
+  
+  ParentKind = getCursorKindForDecl(ND);
+  ParentName = getCodeCompletionTUInfo().getParentName(DC);
+}
+
+unsigned CodeCompletionResult::getPriorityFromDecl(NamedDecl *ND) {
+  if (!ND)
+    return CCP_Unlikely;
+  
+  // Context-based decisions.
+  DeclContext *DC = ND->getDeclContext()->getRedeclContext();
+  if (DC->isFunctionOrMethod() || isa<BlockDecl>(DC)) {
+    // _cmd is relatively rare
+    if (ImplicitParamDecl *ImplicitParam = dyn_cast<ImplicitParamDecl>(ND))
+      if (ImplicitParam->getIdentifier() &&
+          ImplicitParam->getIdentifier()->isStr("_cmd"))
+        return CCP_ObjC_cmd;
+    
+    return CCP_LocalDeclaration;
+  }
+  if (DC->isRecord() || isa<ObjCContainerDecl>(DC))
+    return CCP_MemberDeclaration;
+  
+  // Content-based decisions.
+  if (isa<EnumConstantDecl>(ND))
+    return CCP_Constant;
+  if (isa<TypeDecl>(ND) || isa<ObjCInterfaceDecl>(ND))
+    return CCP_Type;
+  
+  return CCP_Declaration;
+}
+
+//===----------------------------------------------------------------------===//
+// Code completion overload candidate implementation
+//===----------------------------------------------------------------------===//
+FunctionDecl *
+CodeCompleteConsumer::OverloadCandidate::getFunction() const {
+  if (getKind() == CK_Function)
+    return Function;
+  else if (getKind() == CK_FunctionTemplate)
+    return FunctionTemplate->getTemplatedDecl();
+  else
+    return 0;
+}
+
+const FunctionType *
+CodeCompleteConsumer::OverloadCandidate::getFunctionType() const {
+  switch (Kind) {
+  case CK_Function:
+    return Function->getType()->getAs<FunctionType>();
+      
+  case CK_FunctionTemplate:
+    return FunctionTemplate->getTemplatedDecl()->getType()
+             ->getAs<FunctionType>();
+      
+  case CK_FunctionType:
+    return Type;
+  }
+
+  llvm_unreachable("Invalid CandidateKind!");
+}
+
+//===----------------------------------------------------------------------===//
+// Code completion consumer implementation
+//===----------------------------------------------------------------------===//
+
+CodeCompleteConsumer::~CodeCompleteConsumer() { }
+
+void 
+PrintingCodeCompleteConsumer::ProcessCodeCompleteResults(Sema &SemaRef,
+                                                 CodeCompletionContext Context,
+                                                 CodeCompletionResult *Results,
+                                                         unsigned NumResults) {
+  std::stable_sort(Results, Results + NumResults);
+  
+  // Print the results.
+  for (unsigned I = 0; I != NumResults; ++I) {
+    OS << "COMPLETION: ";
+    switch (Results[I].Kind) {
+    case CodeCompletionResult::RK_Declaration:
+      OS << *Results[I].Declaration;
+      if (Results[I].Hidden)
+        OS << " (Hidden)";
+      if (CodeCompletionString *CCS 
+            = Results[I].CreateCodeCompletionString(SemaRef, getAllocator(),
+                                                    CCTUInfo)) {
+        OS << " : " << CCS->getAsString();
+      }
+        
+      OS << '\n';
+      break;
+      
+    case CodeCompletionResult::RK_Keyword:
+      OS << Results[I].Keyword << '\n';
+      break;
+        
+    case CodeCompletionResult::RK_Macro: {
+      OS << Results[I].Macro->getName();
+      if (CodeCompletionString *CCS 
+            = Results[I].CreateCodeCompletionString(SemaRef, getAllocator(),
+                                                    CCTUInfo)) {
+        OS << " : " << CCS->getAsString();
+      }
+      OS << '\n';
+      break;
+    }
+        
+    case CodeCompletionResult::RK_Pattern: {
+      OS << "Pattern : " 
+         << Results[I].Pattern->getAsString() << '\n';
+      break;
+    }
+    }
+  }
+}
+
+void 
+PrintingCodeCompleteConsumer::ProcessOverloadCandidates(Sema &SemaRef,
+                                                        unsigned CurrentArg,
+                                              OverloadCandidate *Candidates,
+                                                     unsigned NumCandidates) {
+  for (unsigned I = 0; I != NumCandidates; ++I) {
+    if (CodeCompletionString *CCS
+          = Candidates[I].CreateSignatureString(CurrentArg, SemaRef,
+                                                getAllocator(), CCTUInfo)) {
+      OS << "OVERLOAD: " << CCS->getAsString() << "\n";
+    }
+  }
+}
+
+/// \brief Retrieve the effective availability of the given declaration.
+static AvailabilityResult getDeclAvailability(Decl *D) {
+  AvailabilityResult AR = D->getAvailability();
+  if (isa<EnumConstantDecl>(D))
+    AR = std::max(AR, cast<Decl>(D->getDeclContext())->getAvailability());
+  return AR;
+}
+
+void CodeCompletionResult::computeCursorKindAndAvailability(bool Accessible) {
+  switch (Kind) {
+  case RK_Pattern:
+    if (!Declaration) {
+      // Do nothing: Patterns can come with cursor kinds!
+      break;
+    }
+    // Fall through
+      
+  case RK_Declaration: {
+    // Set the availability based on attributes.
+    switch (getDeclAvailability(Declaration)) {
+    case AR_Available:
+    case AR_NotYetIntroduced:
+      Availability = CXAvailability_Available;      
+      break;
+      
+    case AR_Deprecated:
+      Availability = CXAvailability_Deprecated;
+      break;
+      
+    case AR_Unavailable:
+      Availability = CXAvailability_NotAvailable;
+      break;
+    }
+
+    if (FunctionDecl *Function = dyn_cast<FunctionDecl>(Declaration))
+      if (Function->isDeleted())
+        Availability = CXAvailability_NotAvailable;
+      
+    CursorKind = getCursorKindForDecl(Declaration);
+    if (CursorKind == CXCursor_UnexposedDecl) {
+      // FIXME: Forward declarations of Objective-C classes and protocols 
+      // are not directly exposed, but we want code completion to treat them 
+      // like a definition.
+      if (isa<ObjCInterfaceDecl>(Declaration))
+        CursorKind = CXCursor_ObjCInterfaceDecl;
+      else if (isa<ObjCProtocolDecl>(Declaration))
+        CursorKind = CXCursor_ObjCProtocolDecl;
+      else
+        CursorKind = CXCursor_NotImplemented;
+    }
+    break;
+  }
+
+  case RK_Macro:
+    Availability = CXAvailability_Available;      
+    CursorKind = CXCursor_MacroDefinition;
+    break;
+      
+  case RK_Keyword:
+    Availability = CXAvailability_Available;      
+    CursorKind = CXCursor_NotImplemented;
+    break;      
+  }
+
+  if (!Accessible)
+    Availability = CXAvailability_NotAccessible;
+}
+
+/// \brief Retrieve the name that should be used to order a result.
+///
+/// If the name needs to be constructed as a string, that string will be
+/// saved into Saved and the returned StringRef will refer to it.
+static StringRef getOrderedName(const CodeCompletionResult &R,
+                                    std::string &Saved) {
+  switch (R.Kind) {
+    case CodeCompletionResult::RK_Keyword:
+      return R.Keyword;
+      
+    case CodeCompletionResult::RK_Pattern:
+      return R.Pattern->getTypedText();
+      
+    case CodeCompletionResult::RK_Macro:
+      return R.Macro->getName();
+      
+    case CodeCompletionResult::RK_Declaration:
+      // Handle declarations below.
+      break;
+  }
+  
+  DeclarationName Name = R.Declaration->getDeclName();
+  
+  // If the name is a simple identifier (by far the common case), or a
+  // zero-argument selector, just return a reference to that identifier.
+  if (IdentifierInfo *Id = Name.getAsIdentifierInfo())
+    return Id->getName();
+  if (Name.isObjCZeroArgSelector())
+    if (IdentifierInfo *Id
+        = Name.getObjCSelector().getIdentifierInfoForSlot(0))
+      return Id->getName();
+  
+  Saved = Name.getAsString();
+  return Saved;
+}
+    
+bool clang::operator<(const CodeCompletionResult &X, 
+                      const CodeCompletionResult &Y) {
+  std::string XSaved, YSaved;
+  StringRef XStr = getOrderedName(X, XSaved);
+  StringRef YStr = getOrderedName(Y, YSaved);
+  int cmp = XStr.compare_lower(YStr);
+  if (cmp)
+    return cmp < 0;
+  
+  // If case-insensitive comparison fails, try case-sensitive comparison.
+  cmp = XStr.compare(YStr);
+  if (cmp)
+    return cmp < 0;
+  
+  return false;
+}
diff --git a/clang/lib/Sema/DeclSpec.cpp b/clang/lib/Sema/DeclSpec.cpp
new file mode 100644
index 0000000..b531acc
--- /dev/null
+++ b/clang/lib/Sema/DeclSpec.cpp
@@ -0,0 +1,986 @@
+//===--- SemaDeclSpec.cpp - Declaration Specifier Semantic Analysis -------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+//  This file implements semantic analysis for declaration specifiers.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Parse/ParseDiagnostic.h" // FIXME: remove this back-dependency!
+#include "clang/Sema/DeclSpec.h"
+#include "clang/Sema/LocInfoType.h"
+#include "clang/Sema/ParsedTemplate.h"
+#include "clang/Sema/SemaDiagnostic.h"
+#include "clang/Sema/Sema.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/NestedNameSpecifier.h"
+#include "clang/AST/TypeLoc.h"
+#include "clang/Lex/Preprocessor.h"
+#include "clang/Basic/LangOptions.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/Support/ErrorHandling.h"
+#include <cstring>
+using namespace clang;
+
+
+static DiagnosticBuilder Diag(DiagnosticsEngine &D, SourceLocation Loc,
+                              unsigned DiagID) {
+  return D.Report(Loc, DiagID);
+}
+
+
+void UnqualifiedId::setTemplateId(TemplateIdAnnotation *TemplateId) {
+  assert(TemplateId && "NULL template-id annotation?");
+  Kind = IK_TemplateId;
+  this->TemplateId = TemplateId;
+  StartLocation = TemplateId->TemplateNameLoc;
+  EndLocation = TemplateId->RAngleLoc;
+}
+
+void UnqualifiedId::setConstructorTemplateId(TemplateIdAnnotation *TemplateId) {
+  assert(TemplateId && "NULL template-id annotation?");
+  Kind = IK_ConstructorTemplateId;
+  this->TemplateId = TemplateId;
+  StartLocation = TemplateId->TemplateNameLoc;
+  EndLocation = TemplateId->RAngleLoc;
+}
+
+void CXXScopeSpec::Extend(ASTContext &Context, SourceLocation TemplateKWLoc, 
+                          TypeLoc TL, SourceLocation ColonColonLoc) {
+  Builder.Extend(Context, TemplateKWLoc, TL, ColonColonLoc);
+  if (Range.getBegin().isInvalid())
+    Range.setBegin(TL.getBeginLoc());
+  Range.setEnd(ColonColonLoc);
+
+  assert(Range == Builder.getSourceRange() &&
+         "NestedNameSpecifierLoc range computation incorrect");
+}
+
+void CXXScopeSpec::Extend(ASTContext &Context, IdentifierInfo *Identifier,
+                          SourceLocation IdentifierLoc, 
+                          SourceLocation ColonColonLoc) {
+  Builder.Extend(Context, Identifier, IdentifierLoc, ColonColonLoc);
+  
+  if (Range.getBegin().isInvalid())
+    Range.setBegin(IdentifierLoc);
+  Range.setEnd(ColonColonLoc);
+  
+  assert(Range == Builder.getSourceRange() &&
+         "NestedNameSpecifierLoc range computation incorrect");
+}
+
+void CXXScopeSpec::Extend(ASTContext &Context, NamespaceDecl *Namespace,
+                          SourceLocation NamespaceLoc, 
+                          SourceLocation ColonColonLoc) {
+  Builder.Extend(Context, Namespace, NamespaceLoc, ColonColonLoc);
+  
+  if (Range.getBegin().isInvalid())
+    Range.setBegin(NamespaceLoc);
+  Range.setEnd(ColonColonLoc);
+
+  assert(Range == Builder.getSourceRange() &&
+         "NestedNameSpecifierLoc range computation incorrect");
+}
+
+void CXXScopeSpec::Extend(ASTContext &Context, NamespaceAliasDecl *Alias,
+                          SourceLocation AliasLoc, 
+                          SourceLocation ColonColonLoc) {
+  Builder.Extend(Context, Alias, AliasLoc, ColonColonLoc);
+  
+  if (Range.getBegin().isInvalid())
+    Range.setBegin(AliasLoc);
+  Range.setEnd(ColonColonLoc);
+
+  assert(Range == Builder.getSourceRange() &&
+         "NestedNameSpecifierLoc range computation incorrect");
+}
+
+void CXXScopeSpec::MakeGlobal(ASTContext &Context, 
+                              SourceLocation ColonColonLoc) {
+  Builder.MakeGlobal(Context, ColonColonLoc);
+  
+  Range = SourceRange(ColonColonLoc);
+  
+  assert(Range == Builder.getSourceRange() &&
+         "NestedNameSpecifierLoc range computation incorrect");
+}
+
+void CXXScopeSpec::MakeTrivial(ASTContext &Context, 
+                               NestedNameSpecifier *Qualifier, SourceRange R) {
+  Builder.MakeTrivial(Context, Qualifier, R);
+  Range = R;
+}
+
+void CXXScopeSpec::Adopt(NestedNameSpecifierLoc Other) {
+  if (!Other) {
+    Range = SourceRange();
+    Builder.Clear();
+    return;
+  }
+
+  Range = Other.getSourceRange();
+  Builder.Adopt(Other);
+}
+
+SourceLocation CXXScopeSpec::getLastQualifierNameLoc() const {
+  if (!Builder.getRepresentation())
+    return SourceLocation();
+  return Builder.getTemporary().getLocalBeginLoc();
+}
+
+NestedNameSpecifierLoc 
+CXXScopeSpec::getWithLocInContext(ASTContext &Context) const {
+  if (!Builder.getRepresentation())
+    return NestedNameSpecifierLoc();
+  
+  return Builder.getWithLocInContext(Context);
+}
+
+/// DeclaratorChunk::getFunction - Return a DeclaratorChunk for a function.
+/// "TheDeclarator" is the declarator that this will be added to.
+DeclaratorChunk DeclaratorChunk::getFunction(bool hasProto, bool isVariadic,
+                                             SourceLocation EllipsisLoc,
+                                             ParamInfo *ArgInfo,
+                                             unsigned NumArgs,
+                                             unsigned TypeQuals,
+                                             bool RefQualifierIsLvalueRef,
+                                             SourceLocation RefQualifierLoc,
+                                             SourceLocation ConstQualifierLoc,
+                                             SourceLocation
+                                                 VolatileQualifierLoc,
+                                             SourceLocation MutableLoc,
+                                             ExceptionSpecificationType
+                                                 ESpecType,
+                                             SourceLocation ESpecLoc,
+                                             ParsedType *Exceptions,
+                                             SourceRange *ExceptionRanges,
+                                             unsigned NumExceptions,
+                                             Expr *NoexceptExpr,
+                                             SourceLocation LocalRangeBegin,
+                                             SourceLocation LocalRangeEnd,
+                                             Declarator &TheDeclarator,
+                                             ParsedType TrailingReturnType) {
+  DeclaratorChunk I;
+  I.Kind                        = Function;
+  I.Loc                         = LocalRangeBegin;
+  I.EndLoc                      = LocalRangeEnd;
+  I.Fun.AttrList                = 0;
+  I.Fun.hasPrototype            = hasProto;
+  I.Fun.isVariadic              = isVariadic;
+  I.Fun.EllipsisLoc             = EllipsisLoc.getRawEncoding();
+  I.Fun.DeleteArgInfo           = false;
+  I.Fun.TypeQuals               = TypeQuals;
+  I.Fun.NumArgs                 = NumArgs;
+  I.Fun.ArgInfo                 = 0;
+  I.Fun.RefQualifierIsLValueRef = RefQualifierIsLvalueRef;
+  I.Fun.RefQualifierLoc         = RefQualifierLoc.getRawEncoding();
+  I.Fun.ConstQualifierLoc       = ConstQualifierLoc.getRawEncoding();
+  I.Fun.VolatileQualifierLoc    = VolatileQualifierLoc.getRawEncoding();
+  I.Fun.MutableLoc              = MutableLoc.getRawEncoding();
+  I.Fun.ExceptionSpecType       = ESpecType;
+  I.Fun.ExceptionSpecLoc        = ESpecLoc.getRawEncoding();
+  I.Fun.NumExceptions           = 0;
+  I.Fun.Exceptions              = 0;
+  I.Fun.NoexceptExpr            = 0;
+  I.Fun.TrailingReturnType   = TrailingReturnType.getAsOpaquePtr();
+
+  // new[] an argument array if needed.
+  if (NumArgs) {
+    // If the 'InlineParams' in Declarator is unused and big enough, put our
+    // parameter list there (in an effort to avoid new/delete traffic).  If it
+    // is already used (consider a function returning a function pointer) or too
+    // small (function taking too many arguments), go to the heap.
+    if (!TheDeclarator.InlineParamsUsed &&
+        NumArgs <= llvm::array_lengthof(TheDeclarator.InlineParams)) {
+      I.Fun.ArgInfo = TheDeclarator.InlineParams;
+      I.Fun.DeleteArgInfo = false;
+      TheDeclarator.InlineParamsUsed = true;
+    } else {
+      I.Fun.ArgInfo = new DeclaratorChunk::ParamInfo[NumArgs];
+      I.Fun.DeleteArgInfo = true;
+    }
+    memcpy(I.Fun.ArgInfo, ArgInfo, sizeof(ArgInfo[0])*NumArgs);
+  }
+
+  // Check what exception specification information we should actually store.
+  switch (ESpecType) {
+  default: break; // By default, save nothing.
+  case EST_Dynamic:
+    // new[] an exception array if needed
+    if (NumExceptions) {
+      I.Fun.NumExceptions = NumExceptions;
+      I.Fun.Exceptions = new DeclaratorChunk::TypeAndRange[NumExceptions];
+      for (unsigned i = 0; i != NumExceptions; ++i) {
+        I.Fun.Exceptions[i].Ty = Exceptions[i];
+        I.Fun.Exceptions[i].Range = ExceptionRanges[i];
+      }
+    }
+    break;
+
+  case EST_ComputedNoexcept:
+    I.Fun.NoexceptExpr = NoexceptExpr;
+    break;
+  }
+  return I;
+}
+
+bool Declarator::isDeclarationOfFunction() const {
+  for (unsigned i = 0, i_end = DeclTypeInfo.size(); i < i_end; ++i) {
+    switch (DeclTypeInfo[i].Kind) {
+    case DeclaratorChunk::Function:
+      return true;
+    case DeclaratorChunk::Paren:
+      continue;
+    case DeclaratorChunk::Pointer:
+    case DeclaratorChunk::Reference:
+    case DeclaratorChunk::Array:
+    case DeclaratorChunk::BlockPointer:
+    case DeclaratorChunk::MemberPointer:
+      return false;
+    }
+    llvm_unreachable("Invalid type chunk");
+  }
+  
+  switch (DS.getTypeSpecType()) {
+    case TST_atomic:
+    case TST_auto:
+    case TST_bool:
+    case TST_char:
+    case TST_char16:
+    case TST_char32:
+    case TST_class:
+    case TST_decimal128:
+    case TST_decimal32:
+    case TST_decimal64:
+    case TST_double:
+    case TST_enum:
+    case TST_error:
+    case TST_float:
+    case TST_half:
+    case TST_int:
+    case TST_int128:
+    case TST_struct:
+    case TST_union:
+    case TST_unknown_anytype:
+    case TST_unspecified:
+    case TST_void:
+    case TST_wchar:
+      return false;
+
+    case TST_decltype:
+    case TST_typeofExpr:
+      if (Expr *E = DS.getRepAsExpr())
+        return E->getType()->isFunctionType();
+      return false;
+     
+    case TST_underlyingType:
+    case TST_typename:
+    case TST_typeofType: {
+      QualType QT = DS.getRepAsType().get();
+      if (QT.isNull())
+        return false;
+      
+      if (const LocInfoType *LIT = dyn_cast<LocInfoType>(QT))
+        QT = LIT->getType();
+
+      if (QT.isNull())
+        return false;
+        
+      return QT->isFunctionType();
+    }
+  }
+
+  llvm_unreachable("Invalid TypeSpecType!");
+}
+
+/// getParsedSpecifiers - Return a bitmask of which flavors of specifiers this
+/// declaration specifier includes.
+///
+unsigned DeclSpec::getParsedSpecifiers() const {
+  unsigned Res = 0;
+  if (StorageClassSpec != SCS_unspecified ||
+      SCS_thread_specified)
+    Res |= PQ_StorageClassSpecifier;
+
+  if (TypeQualifiers != TQ_unspecified)
+    Res |= PQ_TypeQualifier;
+
+  if (hasTypeSpecifier())
+    Res |= PQ_TypeSpecifier;
+
+  if (FS_inline_specified || FS_virtual_specified || FS_explicit_specified)
+    Res |= PQ_FunctionSpecifier;
+  return Res;
+}
+
+template <class T> static bool BadSpecifier(T TNew, T TPrev,
+                                            const char *&PrevSpec,
+                                            unsigned &DiagID) {
+  PrevSpec = DeclSpec::getSpecifierName(TPrev);
+  DiagID = (TNew == TPrev ? diag::ext_duplicate_declspec
+            : diag::err_invalid_decl_spec_combination);
+  return true;
+}
+
+const char *DeclSpec::getSpecifierName(DeclSpec::SCS S) {
+  switch (S) {
+  case DeclSpec::SCS_unspecified: return "unspecified";
+  case DeclSpec::SCS_typedef:     return "typedef";
+  case DeclSpec::SCS_extern:      return "extern";
+  case DeclSpec::SCS_static:      return "static";
+  case DeclSpec::SCS_auto:        return "auto";
+  case DeclSpec::SCS_register:    return "register";
+  case DeclSpec::SCS_private_extern: return "__private_extern__";
+  case DeclSpec::SCS_mutable:     return "mutable";
+  }
+  llvm_unreachable("Unknown typespec!");
+}
+
+const char *DeclSpec::getSpecifierName(TSW W) {
+  switch (W) {
+  case TSW_unspecified: return "unspecified";
+  case TSW_short:       return "short";
+  case TSW_long:        return "long";
+  case TSW_longlong:    return "long long";
+  }
+  llvm_unreachable("Unknown typespec!");
+}
+
+const char *DeclSpec::getSpecifierName(TSC C) {
+  switch (C) {
+  case TSC_unspecified: return "unspecified";
+  case TSC_imaginary:   return "imaginary";
+  case TSC_complex:     return "complex";
+  }
+  llvm_unreachable("Unknown typespec!");
+}
+
+
+const char *DeclSpec::getSpecifierName(TSS S) {
+  switch (S) {
+  case TSS_unspecified: return "unspecified";
+  case TSS_signed:      return "signed";
+  case TSS_unsigned:    return "unsigned";
+  }
+  llvm_unreachable("Unknown typespec!");
+}
+
+const char *DeclSpec::getSpecifierName(DeclSpec::TST T) {
+  switch (T) {
+  case DeclSpec::TST_unspecified: return "unspecified";
+  case DeclSpec::TST_void:        return "void";
+  case DeclSpec::TST_char:        return "char";
+  case DeclSpec::TST_wchar:       return "wchar_t";
+  case DeclSpec::TST_char16:      return "char16_t";
+  case DeclSpec::TST_char32:      return "char32_t";
+  case DeclSpec::TST_int:         return "int";
+  case DeclSpec::TST_int128:      return "__int128";
+  case DeclSpec::TST_half:        return "half";
+  case DeclSpec::TST_float:       return "float";
+  case DeclSpec::TST_double:      return "double";
+  case DeclSpec::TST_bool:        return "_Bool";
+  case DeclSpec::TST_decimal32:   return "_Decimal32";
+  case DeclSpec::TST_decimal64:   return "_Decimal64";
+  case DeclSpec::TST_decimal128:  return "_Decimal128";
+  case DeclSpec::TST_enum:        return "enum";
+  case DeclSpec::TST_class:       return "class";
+  case DeclSpec::TST_union:       return "union";
+  case DeclSpec::TST_struct:      return "struct";
+  case DeclSpec::TST_typename:    return "type-name";
+  case DeclSpec::TST_typeofType:
+  case DeclSpec::TST_typeofExpr:  return "typeof";
+  case DeclSpec::TST_auto:        return "auto";
+  case DeclSpec::TST_decltype:    return "(decltype)";
+  case DeclSpec::TST_underlyingType: return "__underlying_type";
+  case DeclSpec::TST_unknown_anytype: return "__unknown_anytype";
+  case DeclSpec::TST_atomic: return "_Atomic";
+  case DeclSpec::TST_error:       return "(error)";
+  }
+  llvm_unreachable("Unknown typespec!");
+}
+
+const char *DeclSpec::getSpecifierName(TQ T) {
+  switch (T) {
+  case DeclSpec::TQ_unspecified: return "unspecified";
+  case DeclSpec::TQ_const:       return "const";
+  case DeclSpec::TQ_restrict:    return "restrict";
+  case DeclSpec::TQ_volatile:    return "volatile";
+  }
+  llvm_unreachable("Unknown typespec!");
+}
+
+bool DeclSpec::SetStorageClassSpec(Sema &S, SCS SC, SourceLocation Loc,
+                                   const char *&PrevSpec,
+                                   unsigned &DiagID) {
+  // OpenCL 1.1 6.8g: "The extern, static, auto and register storage-class
+  // specifiers are not supported."
+  // It seems sensible to prohibit private_extern too
+  // The cl_clang_storage_class_specifiers extension enables support for
+  // these storage-class specifiers.
+  if (S.getLangOpts().OpenCL &&
+      !S.getOpenCLOptions().cl_clang_storage_class_specifiers) {
+    switch (SC) {
+    case SCS_extern:
+    case SCS_private_extern:
+    case SCS_auto:
+    case SCS_register:
+    case SCS_static:
+      DiagID   = diag::err_not_opencl_storage_class_specifier;
+      PrevSpec = getSpecifierName(SC);
+      return true;
+    default:
+      break;
+    }
+  }
+
+  if (StorageClassSpec != SCS_unspecified) {
+    // Maybe this is an attempt to use C++0x 'auto' outside of C++0x mode.
+    bool isInvalid = true;
+    if (TypeSpecType == TST_unspecified && S.getLangOpts().CPlusPlus) {
+      if (SC == SCS_auto)
+        return SetTypeSpecType(TST_auto, Loc, PrevSpec, DiagID);
+      if (StorageClassSpec == SCS_auto) {
+        isInvalid = SetTypeSpecType(TST_auto, StorageClassSpecLoc,
+                                    PrevSpec, DiagID);
+        assert(!isInvalid && "auto SCS -> TST recovery failed");
+      }
+    }
+
+    // Changing storage class is allowed only if the previous one
+    // was the 'extern' that is part of a linkage specification and
+    // the new storage class is 'typedef'.
+    if (isInvalid &&
+        !(SCS_extern_in_linkage_spec &&
+          StorageClassSpec == SCS_extern &&
+          SC == SCS_typedef))
+      return BadSpecifier(SC, (SCS)StorageClassSpec, PrevSpec, DiagID);
+  }
+  StorageClassSpec = SC;
+  StorageClassSpecLoc = Loc;
+  assert((unsigned)SC == StorageClassSpec && "SCS constants overflow bitfield");
+  return false;
+}
+
+bool DeclSpec::SetStorageClassSpecThread(SourceLocation Loc,
+                                         const char *&PrevSpec,
+                                         unsigned &DiagID) {
+  if (SCS_thread_specified) {
+    PrevSpec = "__thread";
+    DiagID = diag::ext_duplicate_declspec;
+    return true;
+  }
+  SCS_thread_specified = true;
+  SCS_threadLoc = Loc;
+  return false;
+}
+
+/// These methods set the specified attribute of the DeclSpec, but return true
+/// and ignore the request if invalid (e.g. "extern" then "auto" is
+/// specified).
+bool DeclSpec::SetTypeSpecWidth(TSW W, SourceLocation Loc,
+                                const char *&PrevSpec,
+                                unsigned &DiagID) {
+  // Overwrite TSWLoc only if TypeSpecWidth was unspecified, so that
+  // for 'long long' we will keep the source location of the first 'long'.
+  if (TypeSpecWidth == TSW_unspecified)
+    TSWLoc = Loc;
+  // Allow turning long -> long long.
+  else if (W != TSW_longlong || TypeSpecWidth != TSW_long)
+    return BadSpecifier(W, (TSW)TypeSpecWidth, PrevSpec, DiagID);
+  TypeSpecWidth = W;
+  if (TypeAltiVecVector && !TypeAltiVecBool &&
+      ((TypeSpecWidth == TSW_long) || (TypeSpecWidth == TSW_longlong))) {
+    PrevSpec = DeclSpec::getSpecifierName((TST) TypeSpecType);
+    DiagID = diag::warn_vector_long_decl_spec_combination;
+    return true;
+  }
+  return false;
+}
+
+bool DeclSpec::SetTypeSpecComplex(TSC C, SourceLocation Loc,
+                                  const char *&PrevSpec,
+                                  unsigned &DiagID) {
+  if (TypeSpecComplex != TSC_unspecified)
+    return BadSpecifier(C, (TSC)TypeSpecComplex, PrevSpec, DiagID);
+  TypeSpecComplex = C;
+  TSCLoc = Loc;
+  return false;
+}
+
+bool DeclSpec::SetTypeSpecSign(TSS S, SourceLocation Loc,
+                               const char *&PrevSpec,
+                               unsigned &DiagID) {
+  if (TypeSpecSign != TSS_unspecified)
+    return BadSpecifier(S, (TSS)TypeSpecSign, PrevSpec, DiagID);
+  TypeSpecSign = S;
+  TSSLoc = Loc;
+  return false;
+}
+
+bool DeclSpec::SetTypeSpecType(TST T, SourceLocation Loc,
+                               const char *&PrevSpec,
+                               unsigned &DiagID,
+                               ParsedType Rep) {
+  return SetTypeSpecType(T, Loc, Loc, PrevSpec, DiagID, Rep);
+}
+
+bool DeclSpec::SetTypeSpecType(TST T, SourceLocation TagKwLoc,
+                               SourceLocation TagNameLoc,
+                               const char *&PrevSpec,
+                               unsigned &DiagID,
+                               ParsedType Rep) {
+  assert(isTypeRep(T) && "T does not store a type");
+  assert(Rep && "no type provided!");
+  if (TypeSpecType != TST_unspecified) {
+    PrevSpec = DeclSpec::getSpecifierName((TST) TypeSpecType);
+    DiagID = diag::err_invalid_decl_spec_combination;
+    return true;
+  }
+  TypeSpecType = T;
+  TypeRep = Rep;
+  TSTLoc = TagKwLoc;
+  TSTNameLoc = TagNameLoc;
+  TypeSpecOwned = false;
+  return false;
+}
+
+bool DeclSpec::SetTypeSpecType(TST T, SourceLocation Loc,
+                               const char *&PrevSpec,
+                               unsigned &DiagID,
+                               Expr *Rep) {
+  assert(isExprRep(T) && "T does not store an expr");
+  assert(Rep && "no expression provided!");
+  if (TypeSpecType != TST_unspecified) {
+    PrevSpec = DeclSpec::getSpecifierName((TST) TypeSpecType);
+    DiagID = diag::err_invalid_decl_spec_combination;
+    return true;
+  }
+  TypeSpecType = T;
+  ExprRep = Rep;
+  TSTLoc = Loc;
+  TSTNameLoc = Loc;
+  TypeSpecOwned = false;
+  return false;
+}
+
+bool DeclSpec::SetTypeSpecType(TST T, SourceLocation Loc,
+                               const char *&PrevSpec,
+                               unsigned &DiagID,
+                               Decl *Rep, bool Owned) {
+  return SetTypeSpecType(T, Loc, Loc, PrevSpec, DiagID, Rep, Owned);
+}
+
+bool DeclSpec::SetTypeSpecType(TST T, SourceLocation TagKwLoc,
+                               SourceLocation TagNameLoc,
+                               const char *&PrevSpec,
+                               unsigned &DiagID,
+                               Decl *Rep, bool Owned) {
+  assert(isDeclRep(T) && "T does not store a decl");
+  // Unlike the other cases, we don't assert that we actually get a decl.
+
+  if (TypeSpecType != TST_unspecified) {
+    PrevSpec = DeclSpec::getSpecifierName((TST) TypeSpecType);
+    DiagID = diag::err_invalid_decl_spec_combination;
+    return true;
+  }
+  TypeSpecType = T;
+  DeclRep = Rep;
+  TSTLoc = TagKwLoc;
+  TSTNameLoc = TagNameLoc;
+  TypeSpecOwned = Owned;
+  return false;
+}
+
+bool DeclSpec::SetTypeSpecType(TST T, SourceLocation Loc,
+                               const char *&PrevSpec,
+                               unsigned &DiagID) {
+  assert(!isDeclRep(T) && !isTypeRep(T) && !isExprRep(T) &&
+         "rep required for these type-spec kinds!");
+  if (TypeSpecType != TST_unspecified) {
+    PrevSpec = DeclSpec::getSpecifierName((TST) TypeSpecType);
+    DiagID = diag::err_invalid_decl_spec_combination;
+    return true;
+  }
+  TSTLoc = Loc;
+  TSTNameLoc = Loc;
+  if (TypeAltiVecVector && (T == TST_bool) && !TypeAltiVecBool) {
+    TypeAltiVecBool = true;
+    return false;
+  }
+  TypeSpecType = T;
+  TypeSpecOwned = false;
+  if (TypeAltiVecVector && !TypeAltiVecBool && (TypeSpecType == TST_double)) {
+    PrevSpec = DeclSpec::getSpecifierName((TST) TypeSpecType);
+    DiagID = diag::err_invalid_vector_decl_spec;
+    return true;
+  }
+  return false;
+}
+
+bool DeclSpec::SetTypeAltiVecVector(bool isAltiVecVector, SourceLocation Loc,
+                          const char *&PrevSpec, unsigned &DiagID) {
+  if (TypeSpecType != TST_unspecified) {
+    PrevSpec = DeclSpec::getSpecifierName((TST) TypeSpecType);
+    DiagID = diag::err_invalid_vector_decl_spec_combination;
+    return true;
+  }
+  TypeAltiVecVector = isAltiVecVector;
+  AltiVecLoc = Loc;
+  return false;
+}
+
+bool DeclSpec::SetTypeAltiVecPixel(bool isAltiVecPixel, SourceLocation Loc,
+                          const char *&PrevSpec, unsigned &DiagID) {
+  if (!TypeAltiVecVector || TypeAltiVecPixel ||
+      (TypeSpecType != TST_unspecified)) {
+    PrevSpec = DeclSpec::getSpecifierName((TST) TypeSpecType);
+    DiagID = diag::err_invalid_pixel_decl_spec_combination;
+    return true;
+  }
+  TypeAltiVecPixel = isAltiVecPixel;
+  TSTLoc = Loc;
+  TSTNameLoc = Loc;
+  return false;
+}
+
+bool DeclSpec::SetTypeSpecError() {
+  TypeSpecType = TST_error;
+  TypeSpecOwned = false;
+  TSTLoc = SourceLocation();
+  TSTNameLoc = SourceLocation();
+  return false;
+}
+
+bool DeclSpec::SetTypeQual(TQ T, SourceLocation Loc, const char *&PrevSpec,
+                           unsigned &DiagID, const LangOptions &Lang) {
+  // Duplicates turn into warnings pre-C99.
+  if ((TypeQualifiers & T) && !Lang.C99)
+    return BadSpecifier(T, T, PrevSpec, DiagID);
+  TypeQualifiers |= T;
+
+  switch (T) {
+  default: llvm_unreachable("Unknown type qualifier!");
+  case TQ_const:    TQ_constLoc = Loc; break;
+  case TQ_restrict: TQ_restrictLoc = Loc; break;
+  case TQ_volatile: TQ_volatileLoc = Loc; break;
+  }
+  return false;
+}
+
+bool DeclSpec::SetFunctionSpecInline(SourceLocation Loc, const char *&PrevSpec,
+                                     unsigned &DiagID) {
+  // 'inline inline' is ok.
+  FS_inline_specified = true;
+  FS_inlineLoc = Loc;
+  return false;
+}
+
+bool DeclSpec::SetFunctionSpecVirtual(SourceLocation Loc, const char *&PrevSpec,
+                                      unsigned &DiagID) {
+  // 'virtual virtual' is ok.
+  FS_virtual_specified = true;
+  FS_virtualLoc = Loc;
+  return false;
+}
+
+bool DeclSpec::SetFunctionSpecExplicit(SourceLocation Loc, const char *&PrevSpec,
+                                       unsigned &DiagID) {
+  // 'explicit explicit' is ok.
+  FS_explicit_specified = true;
+  FS_explicitLoc = Loc;
+  return false;
+}
+
+bool DeclSpec::SetFriendSpec(SourceLocation Loc, const char *&PrevSpec,
+                             unsigned &DiagID) {
+  if (Friend_specified) {
+    PrevSpec = "friend";
+    DiagID = diag::ext_duplicate_declspec;
+    return true;
+  }
+
+  Friend_specified = true;
+  FriendLoc = Loc;
+  return false;
+}
+
+bool DeclSpec::setModulePrivateSpec(SourceLocation Loc, const char *&PrevSpec,
+                                    unsigned &DiagID) {
+  if (isModulePrivateSpecified()) {
+    PrevSpec = "__module_private__";
+    DiagID = diag::ext_duplicate_declspec;
+    return true;
+  }
+  
+  ModulePrivateLoc = Loc;
+  return false;
+}
+
+bool DeclSpec::SetConstexprSpec(SourceLocation Loc, const char *&PrevSpec,
+                                unsigned &DiagID) {
+  // 'constexpr constexpr' is ok.
+  Constexpr_specified = true;
+  ConstexprLoc = Loc;
+  return false;
+}
+
+void DeclSpec::setProtocolQualifiers(Decl * const *Protos,
+                                     unsigned NP,
+                                     SourceLocation *ProtoLocs,
+                                     SourceLocation LAngleLoc) {
+  if (NP == 0) return;
+  ProtocolQualifiers = new Decl*[NP];
+  ProtocolLocs = new SourceLocation[NP];
+  memcpy((void*)ProtocolQualifiers, Protos, sizeof(Decl*)*NP);
+  memcpy(ProtocolLocs, ProtoLocs, sizeof(SourceLocation)*NP);
+  NumProtocolQualifiers = NP;
+  ProtocolLAngleLoc = LAngleLoc;
+}
+
+void DeclSpec::SaveWrittenBuiltinSpecs() {
+  writtenBS.Sign = getTypeSpecSign();
+  writtenBS.Width = getTypeSpecWidth();
+  writtenBS.Type = getTypeSpecType();
+  // Search the list of attributes for the presence of a mode attribute.
+  writtenBS.ModeAttr = false;
+  AttributeList* attrs = getAttributes().getList();
+  while (attrs) {
+    if (attrs->getKind() == AttributeList::AT_mode) {
+      writtenBS.ModeAttr = true;
+      break;
+    }
+    attrs = attrs->getNext();
+  }
+}
+
+void DeclSpec::SaveStorageSpecifierAsWritten() {
+  if (SCS_extern_in_linkage_spec && StorageClassSpec == SCS_extern)
+    // If 'extern' is part of a linkage specification,
+    // then it is not a storage class "as written".
+    StorageClassSpecAsWritten = SCS_unspecified;
+  else
+    StorageClassSpecAsWritten = StorageClassSpec;
+}
+
+/// Finish - This does final analysis of the declspec, rejecting things like
+/// "_Imaginary" (lacking an FP type).  This returns a diagnostic to issue or
+/// diag::NUM_DIAGNOSTICS if there is no error.  After calling this method,
+/// DeclSpec is guaranteed self-consistent, even if an error occurred.
+void DeclSpec::Finish(DiagnosticsEngine &D, Preprocessor &PP) {
+  // Before possibly changing their values, save specs as written.
+  SaveWrittenBuiltinSpecs();
+  SaveStorageSpecifierAsWritten();
+
+  // Check the type specifier components first.
+
+  // Validate and finalize AltiVec vector declspec.
+  if (TypeAltiVecVector) {
+    if (TypeAltiVecBool) {
+      // Sign specifiers are not allowed with vector bool. (PIM 2.1)
+      if (TypeSpecSign != TSS_unspecified) {
+        Diag(D, TSSLoc, diag::err_invalid_vector_bool_decl_spec)
+          << getSpecifierName((TSS)TypeSpecSign);
+      }
+
+      // Only char/int are valid with vector bool. (PIM 2.1)
+      if (((TypeSpecType != TST_unspecified) && (TypeSpecType != TST_char) &&
+           (TypeSpecType != TST_int)) || TypeAltiVecPixel) {
+        Diag(D, TSTLoc, diag::err_invalid_vector_bool_decl_spec)
+          << (TypeAltiVecPixel ? "__pixel" :
+                                 getSpecifierName((TST)TypeSpecType));
+      }
+
+      // Only 'short' is valid with vector bool. (PIM 2.1)
+      if ((TypeSpecWidth != TSW_unspecified) && (TypeSpecWidth != TSW_short))
+        Diag(D, TSWLoc, diag::err_invalid_vector_bool_decl_spec)
+          << getSpecifierName((TSW)TypeSpecWidth);
+
+      // Elements of vector bool are interpreted as unsigned. (PIM 2.1)
+      if ((TypeSpecType == TST_char) || (TypeSpecType == TST_int) ||
+          (TypeSpecWidth != TSW_unspecified))
+        TypeSpecSign = TSS_unsigned;
+    }
+
+    if (TypeAltiVecPixel) {
+      //TODO: perform validation
+      TypeSpecType = TST_int;
+      TypeSpecSign = TSS_unsigned;
+      TypeSpecWidth = TSW_short;
+      TypeSpecOwned = false;
+    }
+  }
+
+  // signed/unsigned are only valid with int/char/wchar_t.
+  if (TypeSpecSign != TSS_unspecified) {
+    if (TypeSpecType == TST_unspecified)
+      TypeSpecType = TST_int; // unsigned -> unsigned int, signed -> signed int.
+    else if (TypeSpecType != TST_int  && TypeSpecType != TST_int128 &&
+             TypeSpecType != TST_char && TypeSpecType != TST_wchar) {
+      Diag(D, TSSLoc, diag::err_invalid_sign_spec)
+        << getSpecifierName((TST)TypeSpecType);
+      // signed double -> double.
+      TypeSpecSign = TSS_unspecified;
+    }
+  }
+
+  // Validate the width of the type.
+  switch (TypeSpecWidth) {
+  case TSW_unspecified: break;
+  case TSW_short:    // short int
+  case TSW_longlong: // long long int
+    if (TypeSpecType == TST_unspecified)
+      TypeSpecType = TST_int; // short -> short int, long long -> long long int.
+    else if (TypeSpecType != TST_int) {
+      Diag(D, TSWLoc,
+           TypeSpecWidth == TSW_short ? diag::err_invalid_short_spec
+                                      : diag::err_invalid_longlong_spec)
+        <<  getSpecifierName((TST)TypeSpecType);
+      TypeSpecType = TST_int;
+      TypeSpecOwned = false;
+    }
+    break;
+  case TSW_long:  // long double, long int
+    if (TypeSpecType == TST_unspecified)
+      TypeSpecType = TST_int;  // long -> long int.
+    else if (TypeSpecType != TST_int && TypeSpecType != TST_double) {
+      Diag(D, TSWLoc, diag::err_invalid_long_spec)
+        << getSpecifierName((TST)TypeSpecType);
+      TypeSpecType = TST_int;
+      TypeSpecOwned = false;
+    }
+    break;
+  }
+
+  // TODO: if the implementation does not implement _Complex or _Imaginary,
+  // disallow their use.  Need information about the backend.
+  if (TypeSpecComplex != TSC_unspecified) {
+    if (TypeSpecType == TST_unspecified) {
+      Diag(D, TSCLoc, diag::ext_plain_complex)
+        << FixItHint::CreateInsertion(
+                              PP.getLocForEndOfToken(getTypeSpecComplexLoc()),
+                                                 " double");
+      TypeSpecType = TST_double;   // _Complex -> _Complex double.
+    } else if (TypeSpecType == TST_int || TypeSpecType == TST_char) {
+      // Note that this intentionally doesn't include _Complex _Bool.
+      if (!PP.getLangOpts().CPlusPlus)
+        Diag(D, TSTLoc, diag::ext_integer_complex);
+    } else if (TypeSpecType != TST_float && TypeSpecType != TST_double) {
+      Diag(D, TSCLoc, diag::err_invalid_complex_spec)
+        << getSpecifierName((TST)TypeSpecType);
+      TypeSpecComplex = TSC_unspecified;
+    }
+  }
+
+  // If no type specifier was provided and we're parsing a language where
+  // the type specifier is not optional, but we got 'auto' as a storage
+  // class specifier, then assume this is an attempt to use C++0x's 'auto'
+  // type specifier.
+  // FIXME: Does Microsoft really support implicit int in C++?
+  if (PP.getLangOpts().CPlusPlus && !PP.getLangOpts().MicrosoftExt &&
+      TypeSpecType == TST_unspecified && StorageClassSpec == SCS_auto) {
+    TypeSpecType = TST_auto;
+    StorageClassSpec = StorageClassSpecAsWritten = SCS_unspecified;
+    TSTLoc = TSTNameLoc = StorageClassSpecLoc;
+    StorageClassSpecLoc = SourceLocation();
+  }
+  // Diagnose if we've recovered from an ill-formed 'auto' storage class
+  // specifier in a pre-C++0x dialect of C++.
+  if (!PP.getLangOpts().CPlusPlus0x && TypeSpecType == TST_auto)
+    Diag(D, TSTLoc, diag::ext_auto_type_specifier);
+  if (PP.getLangOpts().CPlusPlus && !PP.getLangOpts().CPlusPlus0x &&
+      StorageClassSpec == SCS_auto)
+    Diag(D, StorageClassSpecLoc, diag::warn_auto_storage_class)
+      << FixItHint::CreateRemoval(StorageClassSpecLoc);
+  if (TypeSpecType == TST_char16 || TypeSpecType == TST_char32)
+    Diag(D, TSTLoc, diag::warn_cxx98_compat_unicode_type)
+      << (TypeSpecType == TST_char16 ? "char16_t" : "char32_t");
+  if (Constexpr_specified)
+    Diag(D, ConstexprLoc, diag::warn_cxx98_compat_constexpr);
+
+  // C++ [class.friend]p6:
+  //   No storage-class-specifier shall appear in the decl-specifier-seq
+  //   of a friend declaration.
+  if (isFriendSpecified() && getStorageClassSpec()) {
+    DeclSpec::SCS SC = getStorageClassSpec();
+    const char *SpecName = getSpecifierName(SC);
+
+    SourceLocation SCLoc = getStorageClassSpecLoc();
+    SourceLocation SCEndLoc = SCLoc.getLocWithOffset(strlen(SpecName));
+
+    Diag(D, SCLoc, diag::err_friend_storage_spec)
+      << SpecName
+      << FixItHint::CreateRemoval(SourceRange(SCLoc, SCEndLoc));
+
+    ClearStorageClassSpecs();
+  }
+
+  assert(!TypeSpecOwned || isDeclRep((TST) TypeSpecType));
+ 
+  // Okay, now we can infer the real type.
+
+  // TODO: return "auto function" and other bad things based on the real type.
+
+  // 'data definition has no type or storage class'?
+}
+
+bool DeclSpec::isMissingDeclaratorOk() {
+  TST tst = getTypeSpecType();
+  return isDeclRep(tst) && getRepAsDecl() != 0 &&
+    StorageClassSpec != DeclSpec::SCS_typedef;
+}
+
+void UnqualifiedId::clear() {
+  Kind = IK_Identifier;
+  Identifier = 0;
+  StartLocation = SourceLocation();
+  EndLocation = SourceLocation();
+}
+
+void UnqualifiedId::setOperatorFunctionId(SourceLocation OperatorLoc, 
+                                          OverloadedOperatorKind Op,
+                                          SourceLocation SymbolLocations[3]) {
+  Kind = IK_OperatorFunctionId;
+  StartLocation = OperatorLoc;
+  EndLocation = OperatorLoc;
+  OperatorFunctionId.Operator = Op;
+  for (unsigned I = 0; I != 3; ++I) {
+    OperatorFunctionId.SymbolLocations[I] = SymbolLocations[I].getRawEncoding();
+    
+    if (SymbolLocations[I].isValid())
+      EndLocation = SymbolLocations[I];
+  }
+}
+
+bool VirtSpecifiers::SetSpecifier(Specifier VS, SourceLocation Loc,
+                                  const char *&PrevSpec) {
+  LastLocation = Loc;
+  
+  if (Specifiers & VS) {
+    PrevSpec = getSpecifierName(VS);
+    return true;
+  }
+
+  Specifiers |= VS;
+
+  switch (VS) {
+  default: llvm_unreachable("Unknown specifier!");
+  case VS_Override: VS_overrideLoc = Loc; break;
+  case VS_Final:    VS_finalLoc = Loc; break;
+  }
+
+  return false;
+}
+
+const char *VirtSpecifiers::getSpecifierName(Specifier VS) {
+  switch (VS) {
+  default: llvm_unreachable("Unknown specifier");
+  case VS_Override: return "override";
+  case VS_Final: return "final";
+  }
+}
diff --git a/clang/lib/Sema/DelayedDiagnostic.cpp b/clang/lib/Sema/DelayedDiagnostic.cpp
new file mode 100644
index 0000000..876f9d7
--- /dev/null
+++ b/clang/lib/Sema/DelayedDiagnostic.cpp
@@ -0,0 +1,56 @@
+//===--- DelayedDiagnostic.cpp - Delayed declarator diagnostics -*- 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 DelayedDiagnostic class implementation, which
+// is used to record diagnostics that are being conditionally produced
+// during declarator parsing.
+//
+// This file also defines AccessedEntity.
+//
+//===----------------------------------------------------------------------===//
+#include "clang/Sema/DelayedDiagnostic.h"
+#include <string.h>
+using namespace clang;
+using namespace sema;
+
+DelayedDiagnostic DelayedDiagnostic::makeDeprecation(SourceLocation Loc,
+                                    const NamedDecl *D,
+                                    const ObjCInterfaceDecl *UnknownObjCClass,
+                                    StringRef Msg) {
+  DelayedDiagnostic DD;
+  DD.Kind = Deprecation;
+  DD.Triggered = false;
+  DD.Loc = Loc;
+  DD.DeprecationData.Decl = D;
+  DD.DeprecationData.UnknownObjCClass = UnknownObjCClass;
+  char *MessageData = 0;
+  if (Msg.size()) {
+    MessageData = new char [Msg.size()];
+    memcpy(MessageData, Msg.data(), Msg.size());
+  }
+
+  DD.DeprecationData.Message = MessageData;
+  DD.DeprecationData.MessageLen = Msg.size();
+  return DD;
+}
+
+void DelayedDiagnostic::Destroy() {
+  switch (Kind) {
+  case Access: 
+    getAccessData().~AccessedEntity(); 
+    break;
+
+  case Deprecation: 
+    delete [] DeprecationData.Message;
+    break;
+
+  case ForbiddenType:
+    break;
+  }
+}
diff --git a/clang/lib/Sema/IdentifierResolver.cpp b/clang/lib/Sema/IdentifierResolver.cpp
new file mode 100644
index 0000000..4d62cab
--- /dev/null
+++ b/clang/lib/Sema/IdentifierResolver.cpp
@@ -0,0 +1,444 @@
+//===- IdentifierResolver.cpp - Lexical Scope Name lookup -------*- 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 IdentifierResolver class, which is used for lexical
+// scoped lookup, based on declaration names.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Sema/IdentifierResolver.h"
+#include "clang/Sema/Scope.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/Basic/LangOptions.h"
+#include "clang/Lex/ExternalPreprocessorSource.h"
+#include "clang/Lex/Preprocessor.h"
+
+using namespace clang;
+
+//===----------------------------------------------------------------------===//
+// IdDeclInfoMap class
+//===----------------------------------------------------------------------===//
+
+/// IdDeclInfoMap - Associates IdDeclInfos with declaration names.
+/// Allocates 'pools' (vectors of IdDeclInfos) to avoid allocating each
+/// individual IdDeclInfo to heap.
+class IdentifierResolver::IdDeclInfoMap {
+  static const unsigned int POOL_SIZE = 512;
+
+  /// We use our own linked-list implementation because it is sadly
+  /// impossible to add something to a pre-C++0x STL container without
+  /// a completely unnecessary copy.
+  struct IdDeclInfoPool {
+    IdDeclInfoPool(IdDeclInfoPool *Next) : Next(Next) {}
+    
+    IdDeclInfoPool *Next;
+    IdDeclInfo Pool[POOL_SIZE];
+  };
+  
+  IdDeclInfoPool *CurPool;
+  unsigned int CurIndex;
+
+public:
+  IdDeclInfoMap() : CurPool(0), CurIndex(POOL_SIZE) {}
+
+  ~IdDeclInfoMap() {
+    IdDeclInfoPool *Cur = CurPool;
+    while (IdDeclInfoPool *P = Cur) {
+      Cur = Cur->Next;
+      delete P;
+    }
+  }
+
+  /// Returns the IdDeclInfo associated to the DeclarationName.
+  /// It creates a new IdDeclInfo if one was not created before for this id.
+  IdDeclInfo &operator[](DeclarationName Name);
+};
+
+
+//===----------------------------------------------------------------------===//
+// IdDeclInfo Implementation
+//===----------------------------------------------------------------------===//
+
+/// RemoveDecl - Remove the decl from the scope chain.
+/// The decl must already be part of the decl chain.
+void IdentifierResolver::IdDeclInfo::RemoveDecl(NamedDecl *D) {
+  for (DeclsTy::iterator I = Decls.end(); I != Decls.begin(); --I) {
+    if (D == *(I-1)) {
+      Decls.erase(I-1);
+      return;
+    }
+  }
+
+  llvm_unreachable("Didn't find this decl on its identifier's chain!");
+}
+
+bool
+IdentifierResolver::IdDeclInfo::ReplaceDecl(NamedDecl *Old, NamedDecl *New) {
+  for (DeclsTy::iterator I = Decls.end(); I != Decls.begin(); --I) {
+    if (Old == *(I-1)) {
+      *(I - 1) = New;
+      return true;
+    }
+  }
+
+  return false;
+}
+
+
+//===----------------------------------------------------------------------===//
+// IdentifierResolver Implementation
+//===----------------------------------------------------------------------===//
+
+IdentifierResolver::IdentifierResolver(Preprocessor &PP)
+  : LangOpt(PP.getLangOpts()), PP(PP),
+    IdDeclInfos(new IdDeclInfoMap) {
+}
+
+IdentifierResolver::~IdentifierResolver() {
+  delete IdDeclInfos;
+}
+
+/// isDeclInScope - If 'Ctx' is a function/method, isDeclInScope returns true
+/// if 'D' is in Scope 'S', otherwise 'S' is ignored and isDeclInScope returns
+/// true if 'D' belongs to the given declaration context.
+bool IdentifierResolver::isDeclInScope(Decl *D, DeclContext *Ctx,
+                                       ASTContext &Context, Scope *S,
+                             bool ExplicitInstantiationOrSpecialization) const {
+  Ctx = Ctx->getRedeclContext();
+
+  if (Ctx->isFunctionOrMethod() || S->isFunctionPrototypeScope()) {
+    // Ignore the scopes associated within transparent declaration contexts.
+    while (S->getEntity() &&
+           ((DeclContext *)S->getEntity())->isTransparentContext())
+      S = S->getParent();
+
+    if (S->isDeclScope(D))
+      return true;
+    if (LangOpt.CPlusPlus) {
+      // C++ 3.3.2p3:
+      // The name declared in a catch exception-declaration is local to the
+      // handler and shall not be redeclared in the outermost block of the
+      // handler.
+      // C++ 3.3.2p4:
+      // Names declared in the for-init-statement, and in the condition of if,
+      // while, for, and switch statements are local to the if, while, for, or
+      // switch statement (including the controlled statement), and shall not be
+      // redeclared in a subsequent condition of that statement nor in the
+      // outermost block (or, for the if statement, any of the outermost blocks)
+      // of the controlled statement.
+      //
+      assert(S->getParent() && "No TUScope?");
+      if (S->getParent()->getFlags() & Scope::ControlScope)
+        return S->getParent()->isDeclScope(D);
+    }
+    return false;
+  }
+
+  DeclContext *DCtx = D->getDeclContext()->getRedeclContext();
+  return ExplicitInstantiationOrSpecialization
+           ? Ctx->InEnclosingNamespaceSetOf(DCtx)
+           : Ctx->Equals(DCtx);
+}
+
+/// AddDecl - Link the decl to its shadowed decl chain.
+void IdentifierResolver::AddDecl(NamedDecl *D) {
+  DeclarationName Name = D->getDeclName();
+  if (IdentifierInfo *II = Name.getAsIdentifierInfo())
+    updatingIdentifier(*II);
+
+  void *Ptr = Name.getFETokenInfo<void>();
+
+  if (!Ptr) {
+    Name.setFETokenInfo(D);
+    return;
+  }
+
+  IdDeclInfo *IDI;
+
+  if (isDeclPtr(Ptr)) {
+    Name.setFETokenInfo(NULL);
+    IDI = &(*IdDeclInfos)[Name];
+    NamedDecl *PrevD = static_cast<NamedDecl*>(Ptr);
+    IDI->AddDecl(PrevD);
+  } else
+    IDI = toIdDeclInfo(Ptr);
+
+  IDI->AddDecl(D);
+}
+
+void IdentifierResolver::InsertDeclAfter(iterator Pos, NamedDecl *D) {
+  DeclarationName Name = D->getDeclName();
+  if (IdentifierInfo *II = Name.getAsIdentifierInfo())
+    updatingIdentifier(*II);
+  
+  void *Ptr = Name.getFETokenInfo<void>();
+  
+  if (!Ptr) {
+    AddDecl(D);
+    return;
+  }
+
+  if (isDeclPtr(Ptr)) {
+    // We only have a single declaration: insert before or after it,
+    // as appropriate.
+    if (Pos == iterator()) {
+      // Add the new declaration before the existing declaration.
+      NamedDecl *PrevD = static_cast<NamedDecl*>(Ptr);
+      RemoveDecl(PrevD);
+      AddDecl(D);
+      AddDecl(PrevD);
+    } else {
+      // Add new declaration after the existing declaration.
+      AddDecl(D);
+    }
+
+    return;
+  }
+
+  // General case: insert the declaration at the appropriate point in the 
+  // list, which already has at least two elements.
+  IdDeclInfo *IDI = toIdDeclInfo(Ptr);
+  if (Pos.isIterator()) {
+    IDI->InsertDecl(Pos.getIterator() + 1, D);
+  } else
+    IDI->InsertDecl(IDI->decls_begin(), D);
+}
+
+/// RemoveDecl - Unlink the decl from its shadowed decl chain.
+/// The decl must already be part of the decl chain.
+void IdentifierResolver::RemoveDecl(NamedDecl *D) {
+  assert(D && "null param passed");
+  DeclarationName Name = D->getDeclName();
+  if (IdentifierInfo *II = Name.getAsIdentifierInfo())
+    updatingIdentifier(*II);
+
+  void *Ptr = Name.getFETokenInfo<void>();
+
+  assert(Ptr && "Didn't find this decl on its identifier's chain!");
+
+  if (isDeclPtr(Ptr)) {
+    assert(D == Ptr && "Didn't find this decl on its identifier's chain!");
+    Name.setFETokenInfo(NULL);
+    return;
+  }
+
+  return toIdDeclInfo(Ptr)->RemoveDecl(D);
+}
+
+bool IdentifierResolver::ReplaceDecl(NamedDecl *Old, NamedDecl *New) {
+  assert(Old->getDeclName() == New->getDeclName() &&
+         "Cannot replace a decl with another decl of a different name");
+
+  DeclarationName Name = Old->getDeclName();
+  if (IdentifierInfo *II = Name.getAsIdentifierInfo())
+    updatingIdentifier(*II);
+
+  void *Ptr = Name.getFETokenInfo<void>();
+
+  if (!Ptr)
+    return false;
+
+  if (isDeclPtr(Ptr)) {
+    if (Ptr == Old) {
+      Name.setFETokenInfo(New);
+      return true;
+    }
+    return false;
+  }
+
+  return toIdDeclInfo(Ptr)->ReplaceDecl(Old, New);
+}
+
+/// begin - Returns an iterator for decls with name 'Name'.
+IdentifierResolver::iterator
+IdentifierResolver::begin(DeclarationName Name) {
+  if (IdentifierInfo *II = Name.getAsIdentifierInfo())
+    readingIdentifier(*II);
+    
+  void *Ptr = Name.getFETokenInfo<void>();
+  if (!Ptr) return end();
+
+  if (isDeclPtr(Ptr))
+    return iterator(static_cast<NamedDecl*>(Ptr));
+
+  IdDeclInfo *IDI = toIdDeclInfo(Ptr);
+
+  IdDeclInfo::DeclsTy::iterator I = IDI->decls_end();
+  if (I != IDI->decls_begin())
+    return iterator(I-1);
+  // No decls found.
+  return end();
+}
+
+namespace {
+  enum DeclMatchKind {
+    DMK_Different,
+    DMK_Replace,
+    DMK_Ignore
+  };
+}
+
+/// \brief Compare two declarations to see whether they are different or,
+/// if they are the same, whether the new declaration should replace the 
+/// existing declaration.
+static DeclMatchKind compareDeclarations(NamedDecl *Existing, NamedDecl *New) {
+  // If the declarations are identical, ignore the new one.
+  if (Existing == New)
+    return DMK_Ignore;
+
+  // If the declarations have different kinds, they're obviously different.
+  if (Existing->getKind() != New->getKind())
+    return DMK_Different;
+
+  // If the declarations are redeclarations of each other, keep the newest one.
+  if (Existing->getCanonicalDecl() == New->getCanonicalDecl()) {
+    // If the existing declaration is somewhere in the previous declaration
+    // chain of the new declaration, then prefer the new declaration.
+    for (Decl::redecl_iterator RD = New->redecls_begin(), 
+                            RDEnd = New->redecls_end();
+         RD != RDEnd; ++RD) {
+      if (*RD == Existing)
+        return DMK_Replace;
+        
+      if (RD->isCanonicalDecl())
+        break;
+    }
+    
+    return DMK_Ignore;
+  }
+  
+  return DMK_Different;
+}
+
+bool IdentifierResolver::tryAddTopLevelDecl(NamedDecl *D, DeclarationName Name){
+  if (IdentifierInfo *II = Name.getAsIdentifierInfo())
+    readingIdentifier(*II);
+  
+  void *Ptr = Name.getFETokenInfo<void>();
+    
+  if (!Ptr) {
+    Name.setFETokenInfo(D);
+    return true;
+  }
+  
+  IdDeclInfo *IDI;
+  
+  if (isDeclPtr(Ptr)) {
+    NamedDecl *PrevD = static_cast<NamedDecl*>(Ptr);
+    
+    switch (compareDeclarations(PrevD, D)) {
+    case DMK_Different:
+      break;
+      
+    case DMK_Ignore:
+      return false;
+      
+    case DMK_Replace:
+      Name.setFETokenInfo(D);
+      return true;
+    }
+    
+    Name.setFETokenInfo(NULL);
+    IDI = &(*IdDeclInfos)[Name];
+    
+    // If the existing declaration is not visible in translation unit scope,
+    // then add the new top-level declaration first.
+    if (!PrevD->getDeclContext()->getRedeclContext()->isTranslationUnit()) {
+      IDI->AddDecl(D);
+      IDI->AddDecl(PrevD);
+    } else {
+      IDI->AddDecl(PrevD);
+      IDI->AddDecl(D);
+    }
+    return true;
+  } 
+  
+  IDI = toIdDeclInfo(Ptr);
+
+  // See whether this declaration is identical to any existing declarations.
+  // If not, find the right place to insert it.
+  for (IdDeclInfo::DeclsTy::iterator I = IDI->decls_begin(), 
+                                  IEnd = IDI->decls_end();
+       I != IEnd; ++I) {
+    
+    switch (compareDeclarations(*I, D)) {
+    case DMK_Different:
+      break;
+      
+    case DMK_Ignore:
+      return false;
+      
+    case DMK_Replace:
+      *I = D;
+      return true;
+    }
+    
+    if (!(*I)->getDeclContext()->getRedeclContext()->isTranslationUnit()) {
+      // We've found a declaration that is not visible from the translation
+      // unit (it's in an inner scope). Insert our declaration here.
+      IDI->InsertDecl(I, D);
+      return true;
+    }
+  }
+  
+  // Add the declaration to the end.
+  IDI->AddDecl(D);
+  return true;
+}
+
+void IdentifierResolver::readingIdentifier(IdentifierInfo &II) {
+  if (II.isOutOfDate())
+    PP.getExternalSource()->updateOutOfDateIdentifier(II);  
+}
+
+void IdentifierResolver::updatingIdentifier(IdentifierInfo &II) {
+  if (II.isOutOfDate())
+    PP.getExternalSource()->updateOutOfDateIdentifier(II);
+  
+  if (II.isFromAST())
+    II.setChangedSinceDeserialization();
+}
+
+//===----------------------------------------------------------------------===//
+// IdDeclInfoMap Implementation
+//===----------------------------------------------------------------------===//
+
+/// Returns the IdDeclInfo associated to the DeclarationName.
+/// It creates a new IdDeclInfo if one was not created before for this id.
+IdentifierResolver::IdDeclInfo &
+IdentifierResolver::IdDeclInfoMap::operator[](DeclarationName Name) {
+  void *Ptr = Name.getFETokenInfo<void>();
+
+  if (Ptr) return *toIdDeclInfo(Ptr);
+
+  if (CurIndex == POOL_SIZE) {
+    CurPool = new IdDeclInfoPool(CurPool);
+    CurIndex = 0;
+  }
+  IdDeclInfo *IDI = &CurPool->Pool[CurIndex];
+  Name.setFETokenInfo(reinterpret_cast<void*>(
+                              reinterpret_cast<uintptr_t>(IDI) | 0x1)
+                                                                     );
+  ++CurIndex;
+  return *IDI;
+}
+
+void IdentifierResolver::iterator::incrementSlowCase() {
+  NamedDecl *D = **this;
+  void *InfoPtr = D->getDeclName().getFETokenInfo<void>();
+  assert(!isDeclPtr(InfoPtr) && "Decl with wrong id ?");
+  IdDeclInfo *Info = toIdDeclInfo(InfoPtr);
+
+  BaseIter I = getIterator();
+  if (I != Info->decls_begin())
+    *this = iterator(I-1);
+  else // No more decls.
+    *this = iterator();
+}
diff --git a/clang/lib/Sema/JumpDiagnostics.cpp b/clang/lib/Sema/JumpDiagnostics.cpp
new file mode 100644
index 0000000..ab786c6
--- /dev/null
+++ b/clang/lib/Sema/JumpDiagnostics.cpp
@@ -0,0 +1,770 @@
+//===--- JumpDiagnostics.cpp - Protected scope jump analysis ------*- 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 JumpScopeChecker class, which is used to diagnose
+// jumps that enter a protected scope in an invalid way.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Sema/SemaInternal.h"
+#include "clang/AST/DeclCXX.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/ExprCXX.h"
+#include "clang/AST/StmtObjC.h"
+#include "clang/AST/StmtCXX.h"
+#include "llvm/ADT/BitVector.h"
+using namespace clang;
+
+namespace {
+
+/// JumpScopeChecker - This object is used by Sema to diagnose invalid jumps
+/// into VLA and other protected scopes.  For example, this rejects:
+///    goto L;
+///    int a[n];
+///  L:
+///
+class JumpScopeChecker {
+  Sema &S;
+
+  /// GotoScope - This is a record that we use to keep track of all of the
+  /// scopes that are introduced by VLAs and other things that scope jumps like
+  /// gotos.  This scope tree has nothing to do with the source scope tree,
+  /// because you can have multiple VLA scopes per compound statement, and most
+  /// compound statements don't introduce any scopes.
+  struct GotoScope {
+    /// ParentScope - The index in ScopeMap of the parent scope.  This is 0 for
+    /// the parent scope is the function body.
+    unsigned ParentScope;
+
+    /// InDiag - The note to emit if there is a jump into this scope.
+    unsigned InDiag;
+
+    /// OutDiag - The note to emit if there is an indirect jump out
+    /// of this scope.  Direct jumps always clean up their current scope
+    /// in an orderly way.
+    unsigned OutDiag;
+
+    /// Loc - Location to emit the diagnostic.
+    SourceLocation Loc;
+
+    GotoScope(unsigned parentScope, unsigned InDiag, unsigned OutDiag,
+              SourceLocation L)
+      : ParentScope(parentScope), InDiag(InDiag), OutDiag(OutDiag), Loc(L) {}
+  };
+
+  SmallVector<GotoScope, 48> Scopes;
+  llvm::DenseMap<Stmt*, unsigned> LabelAndGotoScopes;
+  SmallVector<Stmt*, 16> Jumps;
+
+  SmallVector<IndirectGotoStmt*, 4> IndirectJumps;
+  SmallVector<LabelDecl*, 4> IndirectJumpTargets;
+public:
+  JumpScopeChecker(Stmt *Body, Sema &S);
+private:
+  void BuildScopeInformation(Decl *D, unsigned &ParentScope);
+  void BuildScopeInformation(VarDecl *D, const BlockDecl *BDecl, 
+                             unsigned &ParentScope);
+  void BuildScopeInformation(Stmt *S, unsigned &origParentScope);
+  
+  void VerifyJumps();
+  void VerifyIndirectJumps();
+  void NoteJumpIntoScopes(ArrayRef<unsigned> ToScopes);
+  void DiagnoseIndirectJump(IndirectGotoStmt *IG, unsigned IGScope,
+                            LabelDecl *Target, unsigned TargetScope);
+  void CheckJump(Stmt *From, Stmt *To, SourceLocation DiagLoc,
+                 unsigned JumpDiag, unsigned JumpDiagWarning,
+                 unsigned JumpDiagCXX98Compat);
+
+  unsigned GetDeepestCommonScope(unsigned A, unsigned B);
+};
+} // end anonymous namespace
+
+
+JumpScopeChecker::JumpScopeChecker(Stmt *Body, Sema &s) : S(s) {
+  // Add a scope entry for function scope.
+  Scopes.push_back(GotoScope(~0U, ~0U, ~0U, SourceLocation()));
+
+  // Build information for the top level compound statement, so that we have a
+  // defined scope record for every "goto" and label.
+  unsigned BodyParentScope = 0;
+  BuildScopeInformation(Body, BodyParentScope);
+
+  // Check that all jumps we saw are kosher.
+  VerifyJumps();
+  VerifyIndirectJumps();
+}
+
+/// GetDeepestCommonScope - Finds the innermost scope enclosing the
+/// two scopes.
+unsigned JumpScopeChecker::GetDeepestCommonScope(unsigned A, unsigned B) {
+  while (A != B) {
+    // Inner scopes are created after outer scopes and therefore have
+    // higher indices.
+    if (A < B) {
+      assert(Scopes[B].ParentScope < B);
+      B = Scopes[B].ParentScope;
+    } else {
+      assert(Scopes[A].ParentScope < A);
+      A = Scopes[A].ParentScope;
+    }
+  }
+  return A;
+}
+
+typedef std::pair<unsigned,unsigned> ScopePair;
+
+/// GetDiagForGotoScopeDecl - If this decl induces a new goto scope, return a
+/// diagnostic that should be emitted if control goes over it. If not, return 0.
+static ScopePair GetDiagForGotoScopeDecl(ASTContext &Context, const Decl *D) {
+  if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
+    unsigned InDiag = 0, OutDiag = 0;
+    if (VD->getType()->isVariablyModifiedType())
+      InDiag = diag::note_protected_by_vla;
+
+    if (VD->hasAttr<BlocksAttr>())
+      return ScopePair(diag::note_protected_by___block,
+                       diag::note_exits___block);
+
+    if (VD->hasAttr<CleanupAttr>())
+      return ScopePair(diag::note_protected_by_cleanup,
+                       diag::note_exits_cleanup);
+
+    if (Context.getLangOpts().ObjCAutoRefCount && VD->hasLocalStorage()) {
+      switch (VD->getType().getObjCLifetime()) {
+      case Qualifiers::OCL_None:
+      case Qualifiers::OCL_ExplicitNone:
+      case Qualifiers::OCL_Autoreleasing:
+        break;
+
+      case Qualifiers::OCL_Strong:
+      case Qualifiers::OCL_Weak:
+        return ScopePair(diag::note_protected_by_objc_ownership,
+                         diag::note_exits_objc_ownership);
+      }
+    }
+
+    if (Context.getLangOpts().CPlusPlus && VD->hasLocalStorage()) {
+      // C++11 [stmt.dcl]p3:
+      //   A program that jumps from a point where a variable with automatic
+      //   storage duration is not in scope to a point where it is in scope
+      //   is ill-formed unless the variable has scalar type, class type with
+      //   a trivial default constructor and a trivial destructor, a 
+      //   cv-qualified version of one of these types, or an array of one of
+      //   the preceding types and is declared without an initializer.
+
+      // C++03 [stmt.dcl.p3:
+      //   A program that jumps from a point where a local variable
+      //   with automatic storage duration is not in scope to a point
+      //   where it is in scope is ill-formed unless the variable has
+      //   POD type and is declared without an initializer.
+
+      if (const Expr *init = VD->getInit()) {
+        // We actually give variables of record type (or array thereof)
+        // an initializer even if that initializer only calls a trivial
+        // ctor.  Detect that case.
+        // FIXME: With generalized initializer lists, this may
+        // classify "X x{};" as having no initializer.
+        unsigned inDiagToUse = diag::note_protected_by_variable_init;
+
+        const CXXRecordDecl *record = 0;
+
+        if (const CXXConstructExpr *cce = dyn_cast<CXXConstructExpr>(init)) {
+          const CXXConstructorDecl *ctor = cce->getConstructor();
+          record = ctor->getParent();
+
+          if (ctor->isTrivial() && ctor->isDefaultConstructor()) {
+            if (!record->hasTrivialDestructor())
+              inDiagToUse = diag::note_protected_by_variable_nontriv_destructor;
+            else if (!record->isPOD())
+              inDiagToUse = diag::note_protected_by_variable_non_pod;
+            else
+              inDiagToUse = 0;
+          }
+        } else if (VD->getType()->isArrayType()) {
+          record = VD->getType()->getBaseElementTypeUnsafe()
+                                ->getAsCXXRecordDecl();
+        }
+
+        if (inDiagToUse)
+          InDiag = inDiagToUse;
+
+        // Also object to indirect jumps which leave scopes with dtors.
+        if (record && !record->hasTrivialDestructor())
+          OutDiag = diag::note_exits_dtor;
+      }
+    }
+    
+    return ScopePair(InDiag, OutDiag);    
+  }
+
+  if (const TypedefDecl *TD = dyn_cast<TypedefDecl>(D)) {
+    if (TD->getUnderlyingType()->isVariablyModifiedType())
+      return ScopePair(diag::note_protected_by_vla_typedef, 0);
+  }
+
+  if (const TypeAliasDecl *TD = dyn_cast<TypeAliasDecl>(D)) {
+    if (TD->getUnderlyingType()->isVariablyModifiedType())
+      return ScopePair(diag::note_protected_by_vla_type_alias, 0);
+  }
+
+  return ScopePair(0U, 0U);
+}
+
+/// \brief Build scope information for a declaration that is part of a DeclStmt.
+void JumpScopeChecker::BuildScopeInformation(Decl *D, unsigned &ParentScope) {
+  // If this decl causes a new scope, push and switch to it.
+  std::pair<unsigned,unsigned> Diags = GetDiagForGotoScopeDecl(S.Context, D);
+  if (Diags.first || Diags.second) {
+    Scopes.push_back(GotoScope(ParentScope, Diags.first, Diags.second,
+                               D->getLocation()));
+    ParentScope = Scopes.size()-1;
+  }
+  
+  // If the decl has an initializer, walk it with the potentially new
+  // scope we just installed.
+  if (VarDecl *VD = dyn_cast<VarDecl>(D))
+    if (Expr *Init = VD->getInit())
+      BuildScopeInformation(Init, ParentScope);
+}
+
+/// \brief Build scope information for a captured block literal variables.
+void JumpScopeChecker::BuildScopeInformation(VarDecl *D, 
+                                             const BlockDecl *BDecl, 
+                                             unsigned &ParentScope) {
+  // exclude captured __block variables; there's no destructor
+  // associated with the block literal for them.
+  if (D->hasAttr<BlocksAttr>())
+    return;
+  QualType T = D->getType();
+  QualType::DestructionKind destructKind = T.isDestructedType();
+  if (destructKind != QualType::DK_none) {
+    std::pair<unsigned,unsigned> Diags;
+    switch (destructKind) {
+      case QualType::DK_cxx_destructor:
+        Diags = ScopePair(diag::note_enters_block_captures_cxx_obj,
+                          diag::note_exits_block_captures_cxx_obj);
+        break;
+      case QualType::DK_objc_strong_lifetime:
+        Diags = ScopePair(diag::note_enters_block_captures_strong,
+                          diag::note_exits_block_captures_strong);
+        break;
+      case QualType::DK_objc_weak_lifetime:
+        Diags = ScopePair(diag::note_enters_block_captures_weak,
+                          diag::note_exits_block_captures_weak);
+        break;
+      case QualType::DK_none:
+        llvm_unreachable("non-lifetime captured variable");
+    }
+    SourceLocation Loc = D->getLocation();
+    if (Loc.isInvalid())
+      Loc = BDecl->getLocation();
+    Scopes.push_back(GotoScope(ParentScope, 
+                               Diags.first, Diags.second, Loc));
+    ParentScope = Scopes.size()-1;
+  }
+}
+
+/// BuildScopeInformation - The statements from CI to CE are known to form a
+/// coherent VLA scope with a specified parent node.  Walk through the
+/// statements, adding any labels or gotos to LabelAndGotoScopes and recursively
+/// walking the AST as needed.
+void JumpScopeChecker::BuildScopeInformation(Stmt *S, unsigned &origParentScope) {
+  // If this is a statement, rather than an expression, scopes within it don't
+  // propagate out into the enclosing scope.  Otherwise we have to worry
+  // about block literals, which have the lifetime of their enclosing statement.
+  unsigned independentParentScope = origParentScope;
+  unsigned &ParentScope = ((isa<Expr>(S) && !isa<StmtExpr>(S)) 
+                            ? origParentScope : independentParentScope);
+
+  bool SkipFirstSubStmt = false;
+  
+  // If we found a label, remember that it is in ParentScope scope.
+  switch (S->getStmtClass()) {
+  case Stmt::AddrLabelExprClass:
+    IndirectJumpTargets.push_back(cast<AddrLabelExpr>(S)->getLabel());
+    break;
+
+  case Stmt::IndirectGotoStmtClass:
+    // "goto *&&lbl;" is a special case which we treat as equivalent
+    // to a normal goto.  In addition, we don't calculate scope in the
+    // operand (to avoid recording the address-of-label use), which
+    // works only because of the restricted set of expressions which
+    // we detect as constant targets.
+    if (cast<IndirectGotoStmt>(S)->getConstantTarget()) {
+      LabelAndGotoScopes[S] = ParentScope;
+      Jumps.push_back(S);
+      return;
+    }
+
+    LabelAndGotoScopes[S] = ParentScope;
+    IndirectJumps.push_back(cast<IndirectGotoStmt>(S));
+    break;
+
+  case Stmt::SwitchStmtClass:
+    // Evaluate the condition variable before entering the scope of the switch
+    // statement.
+    if (VarDecl *Var = cast<SwitchStmt>(S)->getConditionVariable()) {
+      BuildScopeInformation(Var, ParentScope);
+      SkipFirstSubStmt = true;
+    }
+    // Fall through
+      
+  case Stmt::GotoStmtClass:
+    // Remember both what scope a goto is in as well as the fact that we have
+    // it.  This makes the second scan not have to walk the AST again.
+    LabelAndGotoScopes[S] = ParentScope;
+    Jumps.push_back(S);
+    break;
+
+  default:
+    break;
+  }
+
+  for (Stmt::child_range CI = S->children(); CI; ++CI) {
+    if (SkipFirstSubStmt) {
+      SkipFirstSubStmt = false;
+      continue;
+    }
+    
+    Stmt *SubStmt = *CI;
+    if (SubStmt == 0) continue;
+
+    // Cases, labels, and defaults aren't "scope parents".  It's also
+    // important to handle these iteratively instead of recursively in
+    // order to avoid blowing out the stack.
+    while (true) {
+      Stmt *Next;
+      if (CaseStmt *CS = dyn_cast<CaseStmt>(SubStmt))
+        Next = CS->getSubStmt();
+      else if (DefaultStmt *DS = dyn_cast<DefaultStmt>(SubStmt))
+        Next = DS->getSubStmt();
+      else if (LabelStmt *LS = dyn_cast<LabelStmt>(SubStmt))
+        Next = LS->getSubStmt();
+      else
+        break;
+
+      LabelAndGotoScopes[SubStmt] = ParentScope;
+      SubStmt = Next;
+    }
+
+    // If this is a declstmt with a VLA definition, it defines a scope from here
+    // to the end of the containing context.
+    if (DeclStmt *DS = dyn_cast<DeclStmt>(SubStmt)) {
+      // The decl statement creates a scope if any of the decls in it are VLAs
+      // or have the cleanup attribute.
+      for (DeclStmt::decl_iterator I = DS->decl_begin(), E = DS->decl_end();
+           I != E; ++I)
+        BuildScopeInformation(*I, ParentScope);
+      continue;
+    }
+    // Disallow jumps into any part of an @try statement by pushing a scope and
+    // walking all sub-stmts in that scope.
+    if (ObjCAtTryStmt *AT = dyn_cast<ObjCAtTryStmt>(SubStmt)) {
+      unsigned newParentScope;
+      // Recursively walk the AST for the @try part.
+      Scopes.push_back(GotoScope(ParentScope,
+                                 diag::note_protected_by_objc_try,
+                                 diag::note_exits_objc_try,
+                                 AT->getAtTryLoc()));
+      if (Stmt *TryPart = AT->getTryBody())
+        BuildScopeInformation(TryPart, (newParentScope = Scopes.size()-1));
+
+      // Jump from the catch to the finally or try is not valid.
+      for (unsigned I = 0, N = AT->getNumCatchStmts(); I != N; ++I) {
+        ObjCAtCatchStmt *AC = AT->getCatchStmt(I);
+        Scopes.push_back(GotoScope(ParentScope,
+                                   diag::note_protected_by_objc_catch,
+                                   diag::note_exits_objc_catch,
+                                   AC->getAtCatchLoc()));
+        // @catches are nested and it isn't
+        BuildScopeInformation(AC->getCatchBody(), 
+                              (newParentScope = Scopes.size()-1));
+      }
+
+      // Jump from the finally to the try or catch is not valid.
+      if (ObjCAtFinallyStmt *AF = AT->getFinallyStmt()) {
+        Scopes.push_back(GotoScope(ParentScope,
+                                   diag::note_protected_by_objc_finally,
+                                   diag::note_exits_objc_finally,
+                                   AF->getAtFinallyLoc()));
+        BuildScopeInformation(AF, (newParentScope = Scopes.size()-1));
+      }
+
+      continue;
+    }
+    
+    unsigned newParentScope;
+    // Disallow jumps into the protected statement of an @synchronized, but
+    // allow jumps into the object expression it protects.
+    if (ObjCAtSynchronizedStmt *AS = dyn_cast<ObjCAtSynchronizedStmt>(SubStmt)){
+      // Recursively walk the AST for the @synchronized object expr, it is
+      // evaluated in the normal scope.
+      BuildScopeInformation(AS->getSynchExpr(), ParentScope);
+
+      // Recursively walk the AST for the @synchronized part, protected by a new
+      // scope.
+      Scopes.push_back(GotoScope(ParentScope,
+                                 diag::note_protected_by_objc_synchronized,
+                                 diag::note_exits_objc_synchronized,
+                                 AS->getAtSynchronizedLoc()));
+      BuildScopeInformation(AS->getSynchBody(), 
+                            (newParentScope = Scopes.size()-1));
+      continue;
+    }
+
+    // Disallow jumps into any part of a C++ try statement. This is pretty
+    // much the same as for Obj-C.
+    if (CXXTryStmt *TS = dyn_cast<CXXTryStmt>(SubStmt)) {
+      Scopes.push_back(GotoScope(ParentScope,
+                                 diag::note_protected_by_cxx_try,
+                                 diag::note_exits_cxx_try,
+                                 TS->getSourceRange().getBegin()));
+      if (Stmt *TryBlock = TS->getTryBlock())
+        BuildScopeInformation(TryBlock, (newParentScope = Scopes.size()-1));
+
+      // Jump from the catch into the try is not allowed either.
+      for (unsigned I = 0, E = TS->getNumHandlers(); I != E; ++I) {
+        CXXCatchStmt *CS = TS->getHandler(I);
+        Scopes.push_back(GotoScope(ParentScope,
+                                   diag::note_protected_by_cxx_catch,
+                                   diag::note_exits_cxx_catch,
+                                   CS->getSourceRange().getBegin()));
+        BuildScopeInformation(CS->getHandlerBlock(), 
+                              (newParentScope = Scopes.size()-1));
+      }
+
+      continue;
+    }
+
+    // Disallow jumps into the protected statement of an @autoreleasepool.
+    if (ObjCAutoreleasePoolStmt *AS = dyn_cast<ObjCAutoreleasePoolStmt>(SubStmt)){
+      // Recursively walk the AST for the @autoreleasepool part, protected by a new
+      // scope.
+      Scopes.push_back(GotoScope(ParentScope,
+                                 diag::note_protected_by_objc_autoreleasepool,
+                                 diag::note_exits_objc_autoreleasepool,
+                                 AS->getAtLoc()));
+      BuildScopeInformation(AS->getSubStmt(), (newParentScope = Scopes.size()-1));
+      continue;
+    }
+    
+    if (const BlockExpr *BE = dyn_cast<BlockExpr>(SubStmt)) {
+        const BlockDecl *BDecl = BE->getBlockDecl();
+        for (BlockDecl::capture_const_iterator ci = BDecl->capture_begin(),
+             ce = BDecl->capture_end(); ci != ce; ++ci) {
+          VarDecl *variable = ci->getVariable();
+          BuildScopeInformation(variable, BDecl, ParentScope);
+        }
+    }
+    
+    // Recursively walk the AST.
+    BuildScopeInformation(SubStmt, ParentScope);
+  }
+}
+
+/// VerifyJumps - Verify each element of the Jumps array to see if they are
+/// valid, emitting diagnostics if not.
+void JumpScopeChecker::VerifyJumps() {
+  while (!Jumps.empty()) {
+    Stmt *Jump = Jumps.pop_back_val();
+
+    // With a goto,
+    if (GotoStmt *GS = dyn_cast<GotoStmt>(Jump)) {
+      CheckJump(GS, GS->getLabel()->getStmt(), GS->getGotoLoc(),
+                diag::err_goto_into_protected_scope,
+                diag::warn_goto_into_protected_scope,
+                diag::warn_cxx98_compat_goto_into_protected_scope);
+      continue;
+    }
+
+    // We only get indirect gotos here when they have a constant target.
+    if (IndirectGotoStmt *IGS = dyn_cast<IndirectGotoStmt>(Jump)) {
+      LabelDecl *Target = IGS->getConstantTarget();
+      CheckJump(IGS, Target->getStmt(), IGS->getGotoLoc(),
+                diag::err_goto_into_protected_scope,
+                diag::warn_goto_into_protected_scope,
+                diag::warn_cxx98_compat_goto_into_protected_scope);
+      continue;
+    }
+
+    SwitchStmt *SS = cast<SwitchStmt>(Jump);
+    for (SwitchCase *SC = SS->getSwitchCaseList(); SC;
+         SC = SC->getNextSwitchCase()) {
+      assert(LabelAndGotoScopes.count(SC) && "Case not visited?");
+      CheckJump(SS, SC, SC->getLocStart(),
+                diag::err_switch_into_protected_scope, 0,
+                diag::warn_cxx98_compat_switch_into_protected_scope);
+    }
+  }
+}
+
+/// VerifyIndirectJumps - Verify whether any possible indirect jump
+/// might cross a protection boundary.  Unlike direct jumps, indirect
+/// jumps count cleanups as protection boundaries:  since there's no
+/// way to know where the jump is going, we can't implicitly run the
+/// right cleanups the way we can with direct jumps.
+///
+/// Thus, an indirect jump is "trivial" if it bypasses no
+/// initializations and no teardowns.  More formally, an indirect jump
+/// from A to B is trivial if the path out from A to DCA(A,B) is
+/// trivial and the path in from DCA(A,B) to B is trivial, where
+/// DCA(A,B) is the deepest common ancestor of A and B.
+/// Jump-triviality is transitive but asymmetric.
+///
+/// A path in is trivial if none of the entered scopes have an InDiag.
+/// A path out is trivial is none of the exited scopes have an OutDiag.
+///
+/// Under these definitions, this function checks that the indirect
+/// jump between A and B is trivial for every indirect goto statement A
+/// and every label B whose address was taken in the function.
+void JumpScopeChecker::VerifyIndirectJumps() {
+  if (IndirectJumps.empty()) return;
+
+  // If there aren't any address-of-label expressions in this function,
+  // complain about the first indirect goto.
+  if (IndirectJumpTargets.empty()) {
+    S.Diag(IndirectJumps[0]->getGotoLoc(),
+           diag::err_indirect_goto_without_addrlabel);
+    return;
+  }
+
+  // Collect a single representative of every scope containing an
+  // indirect goto.  For most code bases, this substantially cuts
+  // down on the number of jump sites we'll have to consider later.
+  typedef std::pair<unsigned, IndirectGotoStmt*> JumpScope;
+  SmallVector<JumpScope, 32> JumpScopes;
+  {
+    llvm::DenseMap<unsigned, IndirectGotoStmt*> JumpScopesMap;
+    for (SmallVectorImpl<IndirectGotoStmt*>::iterator
+           I = IndirectJumps.begin(), E = IndirectJumps.end(); I != E; ++I) {
+      IndirectGotoStmt *IG = *I;
+      assert(LabelAndGotoScopes.count(IG) &&
+             "indirect jump didn't get added to scopes?");
+      unsigned IGScope = LabelAndGotoScopes[IG];
+      IndirectGotoStmt *&Entry = JumpScopesMap[IGScope];
+      if (!Entry) Entry = IG;
+    }
+    JumpScopes.reserve(JumpScopesMap.size());
+    for (llvm::DenseMap<unsigned, IndirectGotoStmt*>::iterator
+           I = JumpScopesMap.begin(), E = JumpScopesMap.end(); I != E; ++I)
+      JumpScopes.push_back(*I);
+  }
+
+  // Collect a single representative of every scope containing a
+  // label whose address was taken somewhere in the function.
+  // For most code bases, there will be only one such scope.
+  llvm::DenseMap<unsigned, LabelDecl*> TargetScopes;
+  for (SmallVectorImpl<LabelDecl*>::iterator
+         I = IndirectJumpTargets.begin(), E = IndirectJumpTargets.end();
+       I != E; ++I) {
+    LabelDecl *TheLabel = *I;
+    assert(LabelAndGotoScopes.count(TheLabel->getStmt()) &&
+           "Referenced label didn't get added to scopes?");
+    unsigned LabelScope = LabelAndGotoScopes[TheLabel->getStmt()];
+    LabelDecl *&Target = TargetScopes[LabelScope];
+    if (!Target) Target = TheLabel;
+  }
+
+  // For each target scope, make sure it's trivially reachable from
+  // every scope containing a jump site.
+  //
+  // A path between scopes always consists of exitting zero or more
+  // scopes, then entering zero or more scopes.  We build a set of
+  // of scopes S from which the target scope can be trivially
+  // entered, then verify that every jump scope can be trivially
+  // exitted to reach a scope in S.
+  llvm::BitVector Reachable(Scopes.size(), false);
+  for (llvm::DenseMap<unsigned,LabelDecl*>::iterator
+         TI = TargetScopes.begin(), TE = TargetScopes.end(); TI != TE; ++TI) {
+    unsigned TargetScope = TI->first;
+    LabelDecl *TargetLabel = TI->second;
+
+    Reachable.reset();
+
+    // Mark all the enclosing scopes from which you can safely jump
+    // into the target scope.  'Min' will end up being the index of
+    // the shallowest such scope.
+    unsigned Min = TargetScope;
+    while (true) {
+      Reachable.set(Min);
+
+      // Don't go beyond the outermost scope.
+      if (Min == 0) break;
+
+      // Stop if we can't trivially enter the current scope.
+      if (Scopes[Min].InDiag) break;
+
+      Min = Scopes[Min].ParentScope;
+    }
+
+    // Walk through all the jump sites, checking that they can trivially
+    // reach this label scope.
+    for (SmallVectorImpl<JumpScope>::iterator
+           I = JumpScopes.begin(), E = JumpScopes.end(); I != E; ++I) {
+      unsigned Scope = I->first;
+
+      // Walk out the "scope chain" for this scope, looking for a scope
+      // we've marked reachable.  For well-formed code this amortizes
+      // to O(JumpScopes.size() / Scopes.size()):  we only iterate
+      // when we see something unmarked, and in well-formed code we
+      // mark everything we iterate past.
+      bool IsReachable = false;
+      while (true) {
+        if (Reachable.test(Scope)) {
+          // If we find something reachable, mark all the scopes we just
+          // walked through as reachable.
+          for (unsigned S = I->first; S != Scope; S = Scopes[S].ParentScope)
+            Reachable.set(S);
+          IsReachable = true;
+          break;
+        }
+
+        // Don't walk out if we've reached the top-level scope or we've
+        // gotten shallower than the shallowest reachable scope.
+        if (Scope == 0 || Scope < Min) break;
+
+        // Don't walk out through an out-diagnostic.
+        if (Scopes[Scope].OutDiag) break;
+
+        Scope = Scopes[Scope].ParentScope;
+      }
+
+      // Only diagnose if we didn't find something.
+      if (IsReachable) continue;
+
+      DiagnoseIndirectJump(I->second, I->first, TargetLabel, TargetScope);
+    }
+  }
+}
+
+/// Return true if a particular error+note combination must be downgraded to a
+/// warning in Microsoft mode.
+static bool IsMicrosoftJumpWarning(unsigned JumpDiag, unsigned InDiagNote) {
+  return (JumpDiag == diag::err_goto_into_protected_scope &&
+         (InDiagNote == diag::note_protected_by_variable_init ||
+          InDiagNote == diag::note_protected_by_variable_nontriv_destructor));
+}
+
+/// Return true if a particular note should be downgraded to a compatibility
+/// warning in C++11 mode.
+static bool IsCXX98CompatWarning(Sema &S, unsigned InDiagNote) {
+  return S.getLangOpts().CPlusPlus0x &&
+         InDiagNote == diag::note_protected_by_variable_non_pod;
+}
+
+/// Produce primary diagnostic for an indirect jump statement.
+static void DiagnoseIndirectJumpStmt(Sema &S, IndirectGotoStmt *Jump,
+                                     LabelDecl *Target, bool &Diagnosed) {
+  if (Diagnosed)
+    return;
+  S.Diag(Jump->getGotoLoc(), diag::err_indirect_goto_in_protected_scope);
+  S.Diag(Target->getStmt()->getIdentLoc(), diag::note_indirect_goto_target);
+  Diagnosed = true;
+}
+
+/// Produce note diagnostics for a jump into a protected scope.
+void JumpScopeChecker::NoteJumpIntoScopes(ArrayRef<unsigned> ToScopes) {
+  assert(!ToScopes.empty());
+  for (unsigned I = 0, E = ToScopes.size(); I != E; ++I)
+    if (Scopes[ToScopes[I]].InDiag)
+      S.Diag(Scopes[ToScopes[I]].Loc, Scopes[ToScopes[I]].InDiag);
+}
+
+/// Diagnose an indirect jump which is known to cross scopes.
+void JumpScopeChecker::DiagnoseIndirectJump(IndirectGotoStmt *Jump,
+                                            unsigned JumpScope,
+                                            LabelDecl *Target,
+                                            unsigned TargetScope) {
+  assert(JumpScope != TargetScope);
+
+  unsigned Common = GetDeepestCommonScope(JumpScope, TargetScope);
+  bool Diagnosed = false;
+
+  // Walk out the scope chain until we reach the common ancestor.
+  for (unsigned I = JumpScope; I != Common; I = Scopes[I].ParentScope)
+    if (Scopes[I].OutDiag) {
+      DiagnoseIndirectJumpStmt(S, Jump, Target, Diagnosed);
+      S.Diag(Scopes[I].Loc, Scopes[I].OutDiag);
+    }
+
+  SmallVector<unsigned, 10> ToScopesCXX98Compat;
+
+  // Now walk into the scopes containing the label whose address was taken.
+  for (unsigned I = TargetScope; I != Common; I = Scopes[I].ParentScope)
+    if (IsCXX98CompatWarning(S, Scopes[I].InDiag))
+      ToScopesCXX98Compat.push_back(I);
+    else if (Scopes[I].InDiag) {
+      DiagnoseIndirectJumpStmt(S, Jump, Target, Diagnosed);
+      S.Diag(Scopes[I].Loc, Scopes[I].InDiag);
+    }
+
+  // Diagnose this jump if it would be ill-formed in C++98.
+  if (!Diagnosed && !ToScopesCXX98Compat.empty()) {
+    S.Diag(Jump->getGotoLoc(),
+           diag::warn_cxx98_compat_indirect_goto_in_protected_scope);
+    S.Diag(Target->getStmt()->getIdentLoc(), diag::note_indirect_goto_target);
+    NoteJumpIntoScopes(ToScopesCXX98Compat);
+  }
+}
+
+/// CheckJump - Validate that the specified jump statement is valid: that it is
+/// jumping within or out of its current scope, not into a deeper one.
+void JumpScopeChecker::CheckJump(Stmt *From, Stmt *To, SourceLocation DiagLoc,
+                               unsigned JumpDiagError, unsigned JumpDiagWarning,
+                                 unsigned JumpDiagCXX98Compat) {
+  assert(LabelAndGotoScopes.count(From) && "Jump didn't get added to scopes?");
+  unsigned FromScope = LabelAndGotoScopes[From];
+
+  assert(LabelAndGotoScopes.count(To) && "Jump didn't get added to scopes?");
+  unsigned ToScope = LabelAndGotoScopes[To];
+
+  // Common case: exactly the same scope, which is fine.
+  if (FromScope == ToScope) return;
+
+  unsigned CommonScope = GetDeepestCommonScope(FromScope, ToScope);
+
+  // It's okay to jump out from a nested scope.
+  if (CommonScope == ToScope) return;
+
+  // Pull out (and reverse) any scopes we might need to diagnose skipping.
+  SmallVector<unsigned, 10> ToScopesCXX98Compat;
+  SmallVector<unsigned, 10> ToScopesError;
+  SmallVector<unsigned, 10> ToScopesWarning;
+  for (unsigned I = ToScope; I != CommonScope; I = Scopes[I].ParentScope) {
+    if (S.getLangOpts().MicrosoftMode && JumpDiagWarning != 0 &&
+        IsMicrosoftJumpWarning(JumpDiagError, Scopes[I].InDiag))
+      ToScopesWarning.push_back(I);
+    else if (IsCXX98CompatWarning(S, Scopes[I].InDiag))
+      ToScopesCXX98Compat.push_back(I);
+    else if (Scopes[I].InDiag)
+      ToScopesError.push_back(I);
+  }
+
+  // Handle warnings.
+  if (!ToScopesWarning.empty()) {
+    S.Diag(DiagLoc, JumpDiagWarning);
+    NoteJumpIntoScopes(ToScopesWarning);
+  }
+
+  // Handle errors.
+  if (!ToScopesError.empty()) {
+    S.Diag(DiagLoc, JumpDiagError);
+    NoteJumpIntoScopes(ToScopesError);
+  }
+
+  // Handle -Wc++98-compat warnings if the jump is well-formed.
+  if (ToScopesError.empty() && !ToScopesCXX98Compat.empty()) {
+    S.Diag(DiagLoc, JumpDiagCXX98Compat);
+    NoteJumpIntoScopes(ToScopesCXX98Compat);
+  }
+}
+
+void Sema::DiagnoseInvalidJumps(Stmt *Body) {
+  (void)JumpScopeChecker(Body, *this);
+}
diff --git a/clang/lib/Sema/Makefile b/clang/lib/Sema/Makefile
new file mode 100644
index 0000000..2c02739
--- /dev/null
+++ b/clang/lib/Sema/Makefile
@@ -0,0 +1,19 @@
+##===- clang/lib/Sema/Makefile -----------------------------*- Makefile -*-===##
+# 
+#                     The LLVM Compiler Infrastructure
+#
+# This file is distributed under the University of Illinois Open Source
+# License. See LICENSE.TXT for details.
+# 
+##===----------------------------------------------------------------------===##
+#
+#  This implements the semantic analyzer and AST builder library for the 
+#  C-Language front-end.
+#
+##===----------------------------------------------------------------------===##
+
+CLANG_LEVEL := ../..
+LIBRARYNAME := clangSema
+
+include $(CLANG_LEVEL)/Makefile
+
diff --git a/clang/lib/Sema/Scope.cpp b/clang/lib/Sema/Scope.cpp
new file mode 100644
index 0000000..10f12ce
--- /dev/null
+++ b/clang/lib/Sema/Scope.cpp
@@ -0,0 +1,71 @@
+//===- Scope.cpp - Lexical scope information --------------------*- 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 Scope class, which is used for recording
+// information about a lexical scope.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Sema/Scope.h"
+
+using namespace clang;
+
+void Scope::Init(Scope *parent, unsigned flags) {
+  AnyParent = parent;
+  Flags = flags;
+
+  if (parent && !(flags & FnScope)) {
+    BreakParent    = parent->BreakParent;
+    ContinueParent = parent->ContinueParent;
+  } else {
+    // Control scopes do not contain the contents of nested function scopes for
+    // control flow purposes.
+    BreakParent = ContinueParent = 0;
+  }
+
+  if (parent) {
+    Depth = parent->Depth + 1;
+    PrototypeDepth = parent->PrototypeDepth;
+    PrototypeIndex = 0;
+    FnParent       = parent->FnParent;
+    BlockParent    = parent->BlockParent;
+    TemplateParamParent = parent->TemplateParamParent;
+  } else {
+    Depth = 0;
+    PrototypeDepth = 0;
+    PrototypeIndex = 0;
+    FnParent = BlockParent = 0;
+    TemplateParamParent = 0;
+  }
+
+  // If this scope is a function or contains breaks/continues, remember it.
+  if (flags & FnScope)            FnParent = this;
+  if (flags & BreakScope)         BreakParent = this;
+  if (flags & ContinueScope)      ContinueParent = this;
+  if (flags & BlockScope)         BlockParent = this;
+  if (flags & TemplateParamScope) TemplateParamParent = this;
+
+  // If this is a prototype scope, record that.
+  if (flags & FunctionPrototypeScope) PrototypeDepth++;
+
+  DeclsInScope.clear();
+  UsingDirectives.clear();
+  Entity = 0;
+  ErrorTrap.reset();
+}
+
+bool Scope::containedInPrototypeScope() const {
+  const Scope *S = this;
+  while (S) {
+    if (S->isFunctionPrototypeScope())
+      return true;
+    S = S->getParent();
+  }
+  return false;
+}
diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp
new file mode 100644
index 0000000..30a9cd7
--- /dev/null
+++ b/clang/lib/Sema/Sema.cpp
@@ -0,0 +1,1102 @@
+//===--- Sema.cpp - AST Builder and Semantic Analysis Implementation ------===//
+//
+//                     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 actions class which performs semantic analysis and
+// builds an AST out of a parse stream.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Sema/SemaInternal.h"
+#include "clang/Sema/DelayedDiagnostic.h"
+#include "TargetAttributesSema.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/SmallSet.h"
+#include "llvm/ADT/APFloat.h"
+#include "clang/Sema/CXXFieldCollector.h"
+#include "clang/Sema/TemplateDeduction.h"
+#include "clang/Sema/ExternalSemaSource.h"
+#include "clang/Sema/ObjCMethodList.h"
+#include "clang/Sema/PrettyDeclStackTrace.h"
+#include "clang/Sema/Scope.h"
+#include "clang/Sema/ScopeInfo.h"
+#include "clang/Sema/SemaConsumer.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/ASTDiagnostic.h"
+#include "clang/AST/DeclCXX.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/ExprCXX.h"
+#include "clang/AST/StmtCXX.h"
+#include "clang/Lex/HeaderSearch.h"
+#include "clang/Lex/Preprocessor.h"
+#include "clang/Basic/FileManager.h"
+#include "clang/Basic/PartialDiagnostic.h"
+#include "clang/Basic/TargetInfo.h"
+using namespace clang;
+using namespace sema;
+
+FunctionScopeInfo::~FunctionScopeInfo() { }
+
+void FunctionScopeInfo::Clear() {
+  HasBranchProtectedScope = false;
+  HasBranchIntoScope = false;
+  HasIndirectGoto = false;
+  
+  SwitchStack.clear();
+  Returns.clear();
+  ErrorTrap.reset();
+  PossiblyUnreachableDiags.clear();
+}
+
+BlockScopeInfo::~BlockScopeInfo() { }
+LambdaScopeInfo::~LambdaScopeInfo() { }
+
+PrintingPolicy Sema::getPrintingPolicy(const ASTContext &Context,
+                                       const Preprocessor &PP) {
+  PrintingPolicy Policy = Context.getPrintingPolicy();
+  Policy.Bool = Context.getLangOpts().Bool;
+  if (!Policy.Bool) {
+    if (MacroInfo *BoolMacro = PP.getMacroInfo(&Context.Idents.get("bool"))) {
+      Policy.Bool = BoolMacro->isObjectLike() && 
+        BoolMacro->getNumTokens() == 1 &&
+        BoolMacro->getReplacementToken(0).is(tok::kw__Bool);
+    }
+  }
+  
+  return Policy;
+}
+
+void Sema::ActOnTranslationUnitScope(Scope *S) {
+  TUScope = S;
+  PushDeclContext(S, Context.getTranslationUnitDecl());
+
+  VAListTagName = PP.getIdentifierInfo("__va_list_tag");
+}
+
+Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer,
+           TranslationUnitKind TUKind,
+           CodeCompleteConsumer *CodeCompleter)
+  : TheTargetAttributesSema(0), FPFeatures(pp.getLangOpts()),
+    LangOpts(pp.getLangOpts()), PP(pp), Context(ctxt), Consumer(consumer),
+    Diags(PP.getDiagnostics()), SourceMgr(PP.getSourceManager()),
+    CollectStats(false), ExternalSource(0), CodeCompleter(CodeCompleter),
+    CurContext(0), OriginalLexicalContext(0),
+    PackContext(0), MSStructPragmaOn(false), VisContext(0),
+    ExprNeedsCleanups(false), LateTemplateParser(0), OpaqueParser(0),
+    IdResolver(pp), StdInitializerList(0), CXXTypeInfoDecl(0), MSVCGuidDecl(0),
+    NSNumberDecl(0), NSArrayDecl(0), ArrayWithObjectsMethod(0), 
+    NSDictionaryDecl(0), DictionaryWithObjectsMethod(0),
+    GlobalNewDeleteDeclared(false), 
+    ObjCShouldCallSuperDealloc(false),
+    ObjCShouldCallSuperFinalize(false),
+    TUKind(TUKind),
+    NumSFINAEErrors(0), InFunctionDeclarator(0), SuppressAccessChecking(false), 
+    AccessCheckingSFINAE(false), InNonInstantiationSFINAEContext(false),
+    NonInstantiationEntries(0), ArgumentPackSubstitutionIndex(-1),
+    CurrentInstantiationScope(0), TyposCorrected(0),
+    AnalysisWarnings(*this)
+{
+  TUScope = 0;
+  
+  LoadedExternalKnownNamespaces = false;
+  for (unsigned I = 0; I != NSAPI::NumNSNumberLiteralMethods; ++I)
+    NSNumberLiteralMethods[I] = 0;
+
+  if (getLangOpts().ObjC1)
+    NSAPIObj.reset(new NSAPI(Context));
+
+  if (getLangOpts().CPlusPlus)
+    FieldCollector.reset(new CXXFieldCollector());
+
+  // Tell diagnostics how to render things from the AST library.
+  PP.getDiagnostics().SetArgToStringFn(&FormatASTNodeDiagnosticArgument, 
+                                       &Context);
+
+  ExprEvalContexts.push_back(
+        ExpressionEvaluationContextRecord(PotentiallyEvaluated, 0,
+                                          false, 0, false));
+
+  FunctionScopes.push_back(new FunctionScopeInfo(Diags));
+}
+
+void Sema::Initialize() {
+  // Tell the AST consumer about this Sema object.
+  Consumer.Initialize(Context);
+  
+  // FIXME: Isn't this redundant with the initialization above?
+  if (SemaConsumer *SC = dyn_cast<SemaConsumer>(&Consumer))
+    SC->InitializeSema(*this);
+  
+  // Tell the external Sema source about this Sema object.
+  if (ExternalSemaSource *ExternalSema
+      = dyn_cast_or_null<ExternalSemaSource>(Context.getExternalSource()))
+    ExternalSema->InitializeSema(*this);
+
+  // Initialize predefined 128-bit integer types, if needed.
+  if (PP.getTargetInfo().getPointerWidth(0) >= 64) {
+    // If either of the 128-bit integer types are unavailable to name lookup,
+    // define them now.
+    DeclarationName Int128 = &Context.Idents.get("__int128_t");
+    if (IdResolver.begin(Int128) == IdResolver.end())
+      PushOnScopeChains(Context.getInt128Decl(), TUScope);
+
+    DeclarationName UInt128 = &Context.Idents.get("__uint128_t");
+    if (IdResolver.begin(UInt128) == IdResolver.end())
+      PushOnScopeChains(Context.getUInt128Decl(), TUScope);
+  }
+  
+
+  // Initialize predefined Objective-C types:
+  if (PP.getLangOpts().ObjC1) {
+    // If 'SEL' does not yet refer to any declarations, make it refer to the
+    // predefined 'SEL'.
+    DeclarationName SEL = &Context.Idents.get("SEL");
+    if (IdResolver.begin(SEL) == IdResolver.end())
+      PushOnScopeChains(Context.getObjCSelDecl(), TUScope);
+
+    // If 'id' does not yet refer to any declarations, make it refer to the
+    // predefined 'id'.
+    DeclarationName Id = &Context.Idents.get("id");
+    if (IdResolver.begin(Id) == IdResolver.end())
+      PushOnScopeChains(Context.getObjCIdDecl(), TUScope);
+    
+    // Create the built-in typedef for 'Class'.
+    DeclarationName Class = &Context.Idents.get("Class");
+    if (IdResolver.begin(Class) == IdResolver.end())
+      PushOnScopeChains(Context.getObjCClassDecl(), TUScope);
+
+    // Create the built-in forward declaratino for 'Protocol'.
+    DeclarationName Protocol = &Context.Idents.get("Protocol");
+    if (IdResolver.begin(Protocol) == IdResolver.end())
+      PushOnScopeChains(Context.getObjCProtocolDecl(), TUScope);
+  }
+}
+
+Sema::~Sema() {
+  if (PackContext) FreePackedContext();
+  if (VisContext) FreeVisContext();
+  delete TheTargetAttributesSema;
+  MSStructPragmaOn = false;
+  // Kill all the active scopes.
+  for (unsigned I = 1, E = FunctionScopes.size(); I != E; ++I)
+    delete FunctionScopes[I];
+  if (FunctionScopes.size() == 1)
+    delete FunctionScopes[0];
+  
+  // Tell the SemaConsumer to forget about us; we're going out of scope.
+  if (SemaConsumer *SC = dyn_cast<SemaConsumer>(&Consumer))
+    SC->ForgetSema();
+
+  // Detach from the external Sema source.
+  if (ExternalSemaSource *ExternalSema
+        = dyn_cast_or_null<ExternalSemaSource>(Context.getExternalSource()))
+    ExternalSema->ForgetSema();
+}
+
+
+/// makeUnavailableInSystemHeader - There is an error in the current
+/// context.  If we're still in a system header, and we can plausibly
+/// make the relevant declaration unavailable instead of erroring, do
+/// so and return true.
+bool Sema::makeUnavailableInSystemHeader(SourceLocation loc,
+                                         StringRef msg) {
+  // If we're not in a function, it's an error.
+  FunctionDecl *fn = dyn_cast<FunctionDecl>(CurContext);
+  if (!fn) return false;
+
+  // If we're in template instantiation, it's an error.
+  if (!ActiveTemplateInstantiations.empty())
+    return false;
+  
+  // If that function's not in a system header, it's an error.
+  if (!Context.getSourceManager().isInSystemHeader(loc))
+    return false;
+
+  // If the function is already unavailable, it's not an error.
+  if (fn->hasAttr<UnavailableAttr>()) return true;
+
+  fn->addAttr(new (Context) UnavailableAttr(loc, Context, msg));
+  return true;
+}
+
+ASTMutationListener *Sema::getASTMutationListener() const {
+  return getASTConsumer().GetASTMutationListener();
+}
+
+/// \brief Print out statistics about the semantic analysis.
+void Sema::PrintStats() const {
+  llvm::errs() << "\n*** Semantic Analysis Stats:\n";
+  llvm::errs() << NumSFINAEErrors << " SFINAE diagnostics trapped.\n";
+
+  BumpAlloc.PrintStats();
+  AnalysisWarnings.PrintStats();
+}
+
+/// ImpCastExprToType - If Expr is not of type 'Type', insert an implicit cast.
+/// If there is already an implicit cast, merge into the existing one.
+/// The result is of the given category.
+ExprResult Sema::ImpCastExprToType(Expr *E, QualType Ty,
+                                   CastKind Kind, ExprValueKind VK,
+                                   const CXXCastPath *BasePath,
+                                   CheckedConversionKind CCK) {
+#ifndef NDEBUG
+  if (VK == VK_RValue && !E->isRValue()) {
+    switch (Kind) {
+    default:
+      assert(0 && "can't implicitly cast lvalue to rvalue with this cast kind");
+    case CK_LValueToRValue:
+    case CK_ArrayToPointerDecay:
+    case CK_FunctionToPointerDecay:
+    case CK_ToVoid:
+      break;
+    }
+  }
+  assert((VK == VK_RValue || !E->isRValue()) && "can't cast rvalue to lvalue");
+#endif
+
+  QualType ExprTy = Context.getCanonicalType(E->getType());
+  QualType TypeTy = Context.getCanonicalType(Ty);
+
+  if (ExprTy == TypeTy)
+    return Owned(E);
+
+  if (getLangOpts().ObjCAutoRefCount)
+    CheckObjCARCConversion(SourceRange(), Ty, E, CCK);
+
+  // If this is a derived-to-base cast to a through a virtual base, we
+  // need a vtable.
+  if (Kind == CK_DerivedToBase && 
+      BasePathInvolvesVirtualBase(*BasePath)) {
+    QualType T = E->getType();
+    if (const PointerType *Pointer = T->getAs<PointerType>())
+      T = Pointer->getPointeeType();
+    if (const RecordType *RecordTy = T->getAs<RecordType>())
+      MarkVTableUsed(E->getLocStart(), 
+                     cast<CXXRecordDecl>(RecordTy->getDecl()));
+  }
+
+  if (ImplicitCastExpr *ImpCast = dyn_cast<ImplicitCastExpr>(E)) {
+    if (ImpCast->getCastKind() == Kind && (!BasePath || BasePath->empty())) {
+      ImpCast->setType(Ty);
+      ImpCast->setValueKind(VK);
+      return Owned(E);
+    }
+  }
+
+  return Owned(ImplicitCastExpr::Create(Context, Ty, Kind, E, BasePath, VK));
+}
+
+/// ScalarTypeToBooleanCastKind - Returns the cast kind corresponding
+/// to the conversion from scalar type ScalarTy to the Boolean type.
+CastKind Sema::ScalarTypeToBooleanCastKind(QualType ScalarTy) {
+  switch (ScalarTy->getScalarTypeKind()) {
+  case Type::STK_Bool: return CK_NoOp;
+  case Type::STK_CPointer: return CK_PointerToBoolean;
+  case Type::STK_BlockPointer: return CK_PointerToBoolean;
+  case Type::STK_ObjCObjectPointer: return CK_PointerToBoolean;
+  case Type::STK_MemberPointer: return CK_MemberPointerToBoolean;
+  case Type::STK_Integral: return CK_IntegralToBoolean;
+  case Type::STK_Floating: return CK_FloatingToBoolean;
+  case Type::STK_IntegralComplex: return CK_IntegralComplexToBoolean;
+  case Type::STK_FloatingComplex: return CK_FloatingComplexToBoolean;
+  }
+  return CK_Invalid;
+}
+
+/// \brief Used to prune the decls of Sema's UnusedFileScopedDecls vector.
+static bool ShouldRemoveFromUnused(Sema *SemaRef, const DeclaratorDecl *D) {
+  if (D->isUsed())
+    return true;
+
+  if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
+    // UnusedFileScopedDecls stores the first declaration.
+    // The declaration may have become definition so check again.
+    const FunctionDecl *DeclToCheck;
+    if (FD->hasBody(DeclToCheck))
+      return !SemaRef->ShouldWarnIfUnusedFileScopedDecl(DeclToCheck);
+
+    // Later redecls may add new information resulting in not having to warn,
+    // so check again.
+    DeclToCheck = FD->getMostRecentDecl();
+    if (DeclToCheck != FD)
+      return !SemaRef->ShouldWarnIfUnusedFileScopedDecl(DeclToCheck);
+  }
+
+  if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
+    // UnusedFileScopedDecls stores the first declaration.
+    // The declaration may have become definition so check again.
+    const VarDecl *DeclToCheck = VD->getDefinition(); 
+    if (DeclToCheck)
+      return !SemaRef->ShouldWarnIfUnusedFileScopedDecl(DeclToCheck);
+
+    // Later redecls may add new information resulting in not having to warn,
+    // so check again.
+    DeclToCheck = VD->getMostRecentDecl();
+    if (DeclToCheck != VD)
+      return !SemaRef->ShouldWarnIfUnusedFileScopedDecl(DeclToCheck);
+  }
+
+  return false;
+}
+
+namespace {
+  struct UndefinedInternal {
+    NamedDecl *decl;
+    FullSourceLoc useLoc;
+
+    UndefinedInternal(NamedDecl *decl, FullSourceLoc useLoc)
+      : decl(decl), useLoc(useLoc) {}
+  };
+
+  bool operator<(const UndefinedInternal &l, const UndefinedInternal &r) {
+    return l.useLoc.isBeforeInTranslationUnitThan(r.useLoc);
+  }
+}
+
+/// checkUndefinedInternals - Check for undefined objects with internal linkage.
+static void checkUndefinedInternals(Sema &S) {
+  if (S.UndefinedInternals.empty()) return;
+
+  // Collect all the still-undefined entities with internal linkage.
+  SmallVector<UndefinedInternal, 16> undefined;
+  for (llvm::DenseMap<NamedDecl*,SourceLocation>::iterator
+         i = S.UndefinedInternals.begin(), e = S.UndefinedInternals.end();
+       i != e; ++i) {
+    NamedDecl *decl = i->first;
+
+    // Ignore attributes that have become invalid.
+    if (decl->isInvalidDecl()) continue;
+
+    // __attribute__((weakref)) is basically a definition.
+    if (decl->hasAttr<WeakRefAttr>()) continue;
+
+    if (FunctionDecl *fn = dyn_cast<FunctionDecl>(decl)) {
+      if (fn->isPure() || fn->hasBody())
+        continue;
+    } else {
+      if (cast<VarDecl>(decl)->hasDefinition() != VarDecl::DeclarationOnly)
+        continue;
+    }
+
+    // We build a FullSourceLoc so that we can sort with array_pod_sort.
+    FullSourceLoc loc(i->second, S.Context.getSourceManager());
+    undefined.push_back(UndefinedInternal(decl, loc));
+  }
+
+  if (undefined.empty()) return;
+
+  // Sort (in order of use site) so that we're not (as) dependent on
+  // the iteration order through an llvm::DenseMap.
+  llvm::array_pod_sort(undefined.begin(), undefined.end());
+
+  for (SmallVectorImpl<UndefinedInternal>::iterator
+         i = undefined.begin(), e = undefined.end(); i != e; ++i) {
+    NamedDecl *decl = i->decl;
+    S.Diag(decl->getLocation(), diag::warn_undefined_internal)
+      << isa<VarDecl>(decl) << decl;
+    S.Diag(i->useLoc, diag::note_used_here);
+  }
+}
+
+void Sema::LoadExternalWeakUndeclaredIdentifiers() {
+  if (!ExternalSource)
+    return;
+  
+  SmallVector<std::pair<IdentifierInfo *, WeakInfo>, 4> WeakIDs;
+  ExternalSource->ReadWeakUndeclaredIdentifiers(WeakIDs);
+  for (unsigned I = 0, N = WeakIDs.size(); I != N; ++I) {
+    llvm::DenseMap<IdentifierInfo*,WeakInfo>::iterator Pos
+      = WeakUndeclaredIdentifiers.find(WeakIDs[I].first);
+    if (Pos != WeakUndeclaredIdentifiers.end())
+      continue;
+    
+    WeakUndeclaredIdentifiers.insert(WeakIDs[I]);
+  }
+}
+
+/// ActOnEndOfTranslationUnit - This is called at the very end of the
+/// translation unit when EOF is reached and all but the top-level scope is
+/// popped.
+void Sema::ActOnEndOfTranslationUnit() {
+  // Only complete translation units define vtables and perform implicit
+  // instantiations.
+  if (TUKind == TU_Complete) {
+    DiagnoseUseOfUnimplementedSelectors();
+
+    // If any dynamic classes have their key function defined within
+    // this translation unit, then those vtables are considered "used" and must
+    // be emitted.
+    for (DynamicClassesType::iterator I = DynamicClasses.begin(ExternalSource),
+                                      E = DynamicClasses.end();
+         I != E; ++I) {
+      assert(!(*I)->isDependentType() &&
+             "Should not see dependent types here!");
+      if (const CXXMethodDecl *KeyFunction = Context.getKeyFunction(*I)) {
+        const FunctionDecl *Definition = 0;
+        if (KeyFunction->hasBody(Definition))
+          MarkVTableUsed(Definition->getLocation(), *I, true);
+      }
+    }
+
+    // If DefinedUsedVTables ends up marking any virtual member functions it
+    // might lead to more pending template instantiations, which we then need
+    // to instantiate.
+    DefineUsedVTables();
+
+    // C++: Perform implicit template instantiations.
+    //
+    // FIXME: When we perform these implicit instantiations, we do not
+    // carefully keep track of the point of instantiation (C++ [temp.point]).
+    // This means that name lookup that occurs within the template
+    // instantiation will always happen at the end of the translation unit,
+    // so it will find some names that should not be found. Although this is
+    // common behavior for C++ compilers, it is technically wrong. In the
+    // future, we either need to be able to filter the results of name lookup
+    // or we need to perform template instantiations earlier.
+    PerformPendingInstantiations();
+  }
+  
+  // Remove file scoped decls that turned out to be used.
+  UnusedFileScopedDecls.erase(std::remove_if(UnusedFileScopedDecls.begin(0, 
+                                                                         true),
+                                             UnusedFileScopedDecls.end(),
+                              std::bind1st(std::ptr_fun(ShouldRemoveFromUnused),
+                                           this)),
+                              UnusedFileScopedDecls.end());
+
+  if (TUKind == TU_Prefix) {
+    // Translation unit prefixes don't need any of the checking below.
+    TUScope = 0;
+    return;
+  }
+
+  // Check for #pragma weak identifiers that were never declared
+  // FIXME: This will cause diagnostics to be emitted in a non-determinstic
+  // order!  Iterating over a densemap like this is bad.
+  LoadExternalWeakUndeclaredIdentifiers();
+  for (llvm::DenseMap<IdentifierInfo*,WeakInfo>::iterator
+       I = WeakUndeclaredIdentifiers.begin(),
+       E = WeakUndeclaredIdentifiers.end(); I != E; ++I) {
+    if (I->second.getUsed()) continue;
+
+    Diag(I->second.getLocation(), diag::warn_weak_identifier_undeclared)
+      << I->first;
+  }
+
+  if (TUKind == TU_Module) {
+    // If we are building a module, resolve all of the exported declarations
+    // now.
+    if (Module *CurrentModule = PP.getCurrentModule()) {
+      ModuleMap &ModMap = PP.getHeaderSearchInfo().getModuleMap();
+      
+      llvm::SmallVector<Module *, 2> Stack;
+      Stack.push_back(CurrentModule);
+      while (!Stack.empty()) {
+        Module *Mod = Stack.back();
+        Stack.pop_back();
+        
+        // Resolve the exported declarations.
+        // FIXME: Actually complain, once we figure out how to teach the
+        // diagnostic client to deal with complains in the module map at this
+        // point.
+        ModMap.resolveExports(Mod, /*Complain=*/false);
+        
+        // Queue the submodules, so their exports will also be resolved.
+        for (Module::submodule_iterator Sub = Mod->submodule_begin(),
+                                     SubEnd = Mod->submodule_end();
+             Sub != SubEnd; ++Sub) {
+          Stack.push_back(*Sub);
+        }
+      }
+    }
+    
+    // Modules don't need any of the checking below.
+    TUScope = 0;
+    return;
+  }
+  
+  // C99 6.9.2p2:
+  //   A declaration of an identifier for an object that has file
+  //   scope without an initializer, and without a storage-class
+  //   specifier or with the storage-class specifier static,
+  //   constitutes a tentative definition. If a translation unit
+  //   contains one or more tentative definitions for an identifier,
+  //   and the translation unit contains no external definition for
+  //   that identifier, then the behavior is exactly as if the
+  //   translation unit contains a file scope declaration of that
+  //   identifier, with the composite type as of the end of the
+  //   translation unit, with an initializer equal to 0.
+  llvm::SmallSet<VarDecl *, 32> Seen;
+  for (TentativeDefinitionsType::iterator 
+            T = TentativeDefinitions.begin(ExternalSource),
+         TEnd = TentativeDefinitions.end();
+       T != TEnd; ++T) 
+  {
+    VarDecl *VD = (*T)->getActingDefinition();
+
+    // If the tentative definition was completed, getActingDefinition() returns
+    // null. If we've already seen this variable before, insert()'s second
+    // return value is false.
+    if (VD == 0 || VD->isInvalidDecl() || !Seen.insert(VD))
+      continue;
+
+    if (const IncompleteArrayType *ArrayT
+        = Context.getAsIncompleteArrayType(VD->getType())) {
+      if (RequireCompleteType(VD->getLocation(),
+                              ArrayT->getElementType(),
+                              diag::err_tentative_def_incomplete_type_arr)) {
+        VD->setInvalidDecl();
+        continue;
+      }
+
+      // Set the length of the array to 1 (C99 6.9.2p5).
+      Diag(VD->getLocation(), diag::warn_tentative_incomplete_array);
+      llvm::APInt One(Context.getTypeSize(Context.getSizeType()), true);
+      QualType T = Context.getConstantArrayType(ArrayT->getElementType(),
+                                                One, ArrayType::Normal, 0);
+      VD->setType(T);
+    } else if (RequireCompleteType(VD->getLocation(), VD->getType(),
+                                   diag::err_tentative_def_incomplete_type))
+      VD->setInvalidDecl();
+
+    // Notify the consumer that we've completed a tentative definition.
+    if (!VD->isInvalidDecl())
+      Consumer.CompleteTentativeDefinition(VD);
+
+  }
+
+  if (LangOpts.CPlusPlus0x &&
+      Diags.getDiagnosticLevel(diag::warn_delegating_ctor_cycle,
+                               SourceLocation())
+        != DiagnosticsEngine::Ignored)
+    CheckDelegatingCtorCycles();
+
+  // If there were errors, disable 'unused' warnings since they will mostly be
+  // noise.
+  if (!Diags.hasErrorOccurred()) {
+    // Output warning for unused file scoped decls.
+    for (UnusedFileScopedDeclsType::iterator
+           I = UnusedFileScopedDecls.begin(ExternalSource),
+           E = UnusedFileScopedDecls.end(); I != E; ++I) {
+      if (ShouldRemoveFromUnused(this, *I))
+        continue;
+      
+      if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(*I)) {
+        const FunctionDecl *DiagD;
+        if (!FD->hasBody(DiagD))
+          DiagD = FD;
+        if (DiagD->isDeleted())
+          continue; // Deleted functions are supposed to be unused.
+        if (DiagD->isReferenced()) {
+          if (isa<CXXMethodDecl>(DiagD))
+            Diag(DiagD->getLocation(), diag::warn_unneeded_member_function)
+                  << DiagD->getDeclName();
+          else
+            Diag(DiagD->getLocation(), diag::warn_unneeded_internal_decl)
+                  << /*function*/0 << DiagD->getDeclName();
+        } else {
+          Diag(DiagD->getLocation(),
+               isa<CXXMethodDecl>(DiagD) ? diag::warn_unused_member_function
+                                         : diag::warn_unused_function)
+                << DiagD->getDeclName();
+        }
+      } else {
+        const VarDecl *DiagD = cast<VarDecl>(*I)->getDefinition();
+        if (!DiagD)
+          DiagD = cast<VarDecl>(*I);
+        if (DiagD->isReferenced()) {
+          Diag(DiagD->getLocation(), diag::warn_unneeded_internal_decl)
+                << /*variable*/1 << DiagD->getDeclName();
+        } else {
+          Diag(DiagD->getLocation(), diag::warn_unused_variable)
+                << DiagD->getDeclName();
+        }
+      }
+    }
+
+    checkUndefinedInternals(*this);
+  }
+
+  // Check we've noticed that we're no longer parsing the initializer for every
+  // variable. If we miss cases, then at best we have a performance issue and
+  // at worst a rejects-valid bug.
+  assert(ParsingInitForAutoVars.empty() &&
+         "Didn't unmark var as having its initializer parsed");
+
+  TUScope = 0;
+}
+
+
+//===----------------------------------------------------------------------===//
+// Helper functions.
+//===----------------------------------------------------------------------===//
+
+DeclContext *Sema::getFunctionLevelDeclContext() {
+  DeclContext *DC = CurContext;
+
+  while (true) {
+    if (isa<BlockDecl>(DC) || isa<EnumDecl>(DC)) {
+      DC = DC->getParent();
+    } else if (isa<CXXMethodDecl>(DC) &&
+               cast<CXXMethodDecl>(DC)->getOverloadedOperator() == OO_Call &&
+               cast<CXXRecordDecl>(DC->getParent())->isLambda()) {
+      DC = DC->getParent()->getParent();
+    }
+    else break;
+  }
+
+  return DC;
+}
+
+/// getCurFunctionDecl - If inside of a function body, this returns a pointer
+/// to the function decl for the function being parsed.  If we're currently
+/// in a 'block', this returns the containing context.
+FunctionDecl *Sema::getCurFunctionDecl() {
+  DeclContext *DC = getFunctionLevelDeclContext();
+  return dyn_cast<FunctionDecl>(DC);
+}
+
+ObjCMethodDecl *Sema::getCurMethodDecl() {
+  DeclContext *DC = getFunctionLevelDeclContext();
+  return dyn_cast<ObjCMethodDecl>(DC);
+}
+
+NamedDecl *Sema::getCurFunctionOrMethodDecl() {
+  DeclContext *DC = getFunctionLevelDeclContext();
+  if (isa<ObjCMethodDecl>(DC) || isa<FunctionDecl>(DC))
+    return cast<NamedDecl>(DC);
+  return 0;
+}
+
+void Sema::EmitCurrentDiagnostic(unsigned DiagID) {
+  // FIXME: It doesn't make sense to me that DiagID is an incoming argument here
+  // and yet we also use the current diag ID on the DiagnosticsEngine. This has
+  // been made more painfully obvious by the refactor that introduced this
+  // function, but it is possible that the incoming argument can be
+  // eliminnated. If it truly cannot be (for example, there is some reentrancy
+  // issue I am not seeing yet), then there should at least be a clarifying
+  // comment somewhere.
+  if (llvm::Optional<TemplateDeductionInfo*> Info = isSFINAEContext()) {
+    switch (DiagnosticIDs::getDiagnosticSFINAEResponse(
+              Diags.getCurrentDiagID())) {
+    case DiagnosticIDs::SFINAE_Report:
+      // We'll report the diagnostic below.
+      break;
+      
+    case DiagnosticIDs::SFINAE_SubstitutionFailure:
+      // Count this failure so that we know that template argument deduction
+      // has failed.
+      ++NumSFINAEErrors;
+      Diags.setLastDiagnosticIgnored();
+      Diags.Clear();
+      return;
+      
+    case DiagnosticIDs::SFINAE_AccessControl: {
+      // Per C++ Core Issue 1170, access control is part of SFINAE.
+      // Additionally, the AccessCheckingSFINAE flag can be used to temporarily
+      // make access control a part of SFINAE for the purposes of checking
+      // type traits.
+      if (!AccessCheckingSFINAE && !getLangOpts().CPlusPlus0x)
+        break;
+
+      SourceLocation Loc = Diags.getCurrentDiagLoc();
+
+      // Suppress this diagnostic.
+      ++NumSFINAEErrors;
+      Diags.setLastDiagnosticIgnored();
+      Diags.Clear();
+
+      // Now the diagnostic state is clear, produce a C++98 compatibility
+      // warning.
+      Diag(Loc, diag::warn_cxx98_compat_sfinae_access_control);
+
+      // The last diagnostic which Sema produced was ignored. Suppress any
+      // notes attached to it.
+      Diags.setLastDiagnosticIgnored();
+      return;
+    }
+
+    case DiagnosticIDs::SFINAE_Suppress:
+      // Make a copy of this suppressed diagnostic and store it with the
+      // template-deduction information;
+      Diagnostic DiagInfo(&Diags);
+        
+      if (*Info)
+        (*Info)->addSuppressedDiagnostic(DiagInfo.getLocation(),
+                        PartialDiagnostic(DiagInfo,Context.getDiagAllocator()));
+        
+      // Suppress this diagnostic.        
+      Diags.setLastDiagnosticIgnored();
+      Diags.Clear();
+      return;
+    }
+  }
+  
+  // Set up the context's printing policy based on our current state.
+  Context.setPrintingPolicy(getPrintingPolicy());
+  
+  // Emit the diagnostic.
+  if (!Diags.EmitCurrentDiagnostic())
+    return;
+
+  // If this is not a note, and we're in a template instantiation
+  // that is different from the last template instantiation where
+  // we emitted an error, print a template instantiation
+  // backtrace.
+  if (!DiagnosticIDs::isBuiltinNote(DiagID) &&
+      !ActiveTemplateInstantiations.empty() &&
+      ActiveTemplateInstantiations.back()
+        != LastTemplateInstantiationErrorContext) {
+    PrintInstantiationStack();
+    LastTemplateInstantiationErrorContext = ActiveTemplateInstantiations.back();
+  }
+}
+
+Sema::SemaDiagnosticBuilder
+Sema::Diag(SourceLocation Loc, const PartialDiagnostic& PD) {
+  SemaDiagnosticBuilder Builder(Diag(Loc, PD.getDiagID()));
+  PD.Emit(Builder);
+
+  return Builder;
+}
+
+/// \brief Looks through the macro-expansion chain for the given
+/// location, looking for a macro expansion with the given name.
+/// If one is found, returns true and sets the location to that
+/// expansion loc.
+bool Sema::findMacroSpelling(SourceLocation &locref, StringRef name) {
+  SourceLocation loc = locref;
+  if (!loc.isMacroID()) return false;
+
+  // There's no good way right now to look at the intermediate
+  // expansions, so just jump to the expansion location.
+  loc = getSourceManager().getExpansionLoc(loc);
+
+  // If that's written with the name, stop here.
+  SmallVector<char, 16> buffer;
+  if (getPreprocessor().getSpelling(loc, buffer) == name) {
+    locref = loc;
+    return true;
+  }
+  return false;
+}
+
+/// \brief Determines the active Scope associated with the given declaration
+/// context.
+///
+/// This routine maps a declaration context to the active Scope object that
+/// represents that declaration context in the parser. It is typically used
+/// from "scope-less" code (e.g., template instantiation, lazy creation of
+/// declarations) that injects a name for name-lookup purposes and, therefore,
+/// must update the Scope.
+///
+/// \returns The scope corresponding to the given declaraion context, or NULL
+/// if no such scope is open.
+Scope *Sema::getScopeForContext(DeclContext *Ctx) {
+  
+  if (!Ctx)
+    return 0;
+  
+  Ctx = Ctx->getPrimaryContext();
+  for (Scope *S = getCurScope(); S; S = S->getParent()) {
+    // Ignore scopes that cannot have declarations. This is important for
+    // out-of-line definitions of static class members.
+    if (S->getFlags() & (Scope::DeclScope | Scope::TemplateParamScope))
+      if (DeclContext *Entity = static_cast<DeclContext *> (S->getEntity()))
+        if (Ctx == Entity->getPrimaryContext())
+          return S;
+  }
+  
+  return 0;
+}
+
+/// \brief Enter a new function scope
+void Sema::PushFunctionScope() {
+  if (FunctionScopes.size() == 1) {
+    // Use the "top" function scope rather than having to allocate
+    // memory for a new scope.
+    FunctionScopes.back()->Clear();
+    FunctionScopes.push_back(FunctionScopes.back());
+    return;
+  }
+  
+  FunctionScopes.push_back(new FunctionScopeInfo(getDiagnostics()));
+}
+
+void Sema::PushBlockScope(Scope *BlockScope, BlockDecl *Block) {
+  FunctionScopes.push_back(new BlockScopeInfo(getDiagnostics(),
+                                              BlockScope, Block));
+}
+
+void Sema::PushLambdaScope(CXXRecordDecl *Lambda, 
+                           CXXMethodDecl *CallOperator) {
+  FunctionScopes.push_back(new LambdaScopeInfo(getDiagnostics(), Lambda,
+                                               CallOperator));
+}
+
+void Sema::PopFunctionScopeInfo(const AnalysisBasedWarnings::Policy *WP,
+                                const Decl *D, const BlockExpr *blkExpr) {
+  FunctionScopeInfo *Scope = FunctionScopes.pop_back_val();  
+  assert(!FunctionScopes.empty() && "mismatched push/pop!");
+  
+  // Issue any analysis-based warnings.
+  if (WP && D)
+    AnalysisWarnings.IssueWarnings(*WP, Scope, D, blkExpr);
+  else {
+    for (SmallVectorImpl<sema::PossiblyUnreachableDiag>::iterator
+         i = Scope->PossiblyUnreachableDiags.begin(),
+         e = Scope->PossiblyUnreachableDiags.end();
+         i != e; ++i) {
+      const sema::PossiblyUnreachableDiag &D = *i;
+      Diag(D.Loc, D.PD);
+    }
+  }
+
+  if (FunctionScopes.back() != Scope) {
+    delete Scope;
+  }
+}
+
+void Sema::PushCompoundScope() {
+  getCurFunction()->CompoundScopes.push_back(CompoundScopeInfo());
+}
+
+void Sema::PopCompoundScope() {
+  FunctionScopeInfo *CurFunction = getCurFunction();
+  assert(!CurFunction->CompoundScopes.empty() && "mismatched push/pop");
+
+  CurFunction->CompoundScopes.pop_back();
+}
+
+/// \brief Determine whether any errors occurred within this function/method/
+/// block.
+bool Sema::hasAnyUnrecoverableErrorsInThisFunction() const {
+  return getCurFunction()->ErrorTrap.hasUnrecoverableErrorOccurred();
+}
+
+BlockScopeInfo *Sema::getCurBlock() {
+  if (FunctionScopes.empty())
+    return 0;
+  
+  return dyn_cast<BlockScopeInfo>(FunctionScopes.back());  
+}
+
+LambdaScopeInfo *Sema::getCurLambda() {
+  if (FunctionScopes.empty())
+    return 0;
+  
+  return dyn_cast<LambdaScopeInfo>(FunctionScopes.back());  
+}
+
+// Pin this vtable to this file.
+ExternalSemaSource::~ExternalSemaSource() {}
+
+void ExternalSemaSource::ReadMethodPool(Selector Sel) { }
+
+void ExternalSemaSource::ReadKnownNamespaces(
+                           SmallVectorImpl<NamespaceDecl *> &Namespaces) {  
+}
+
+void PrettyDeclStackTraceEntry::print(raw_ostream &OS) const {
+  SourceLocation Loc = this->Loc;
+  if (!Loc.isValid() && TheDecl) Loc = TheDecl->getLocation();
+  if (Loc.isValid()) {
+    Loc.print(OS, S.getSourceManager());
+    OS << ": ";
+  }
+  OS << Message;
+
+  if (TheDecl && isa<NamedDecl>(TheDecl)) {
+    std::string Name = cast<NamedDecl>(TheDecl)->getNameAsString();
+    if (!Name.empty())
+      OS << " '" << Name << '\'';
+  }
+
+  OS << '\n';
+}
+
+/// \brief Figure out if an expression could be turned into a call.
+///
+/// Use this when trying to recover from an error where the programmer may have
+/// written just the name of a function instead of actually calling it.
+///
+/// \param E - The expression to examine.
+/// \param ZeroArgCallReturnTy - If the expression can be turned into a call
+///  with no arguments, this parameter is set to the type returned by such a
+///  call; otherwise, it is set to an empty QualType.
+/// \param OverloadSet - If the expression is an overloaded function
+///  name, this parameter is populated with the decls of the various overloads.
+bool Sema::isExprCallable(const Expr &E, QualType &ZeroArgCallReturnTy,
+                          UnresolvedSetImpl &OverloadSet) {
+  ZeroArgCallReturnTy = QualType();
+  OverloadSet.clear();
+
+  if (E.getType() == Context.OverloadTy) {
+    OverloadExpr::FindResult FR = OverloadExpr::find(const_cast<Expr*>(&E));
+    const OverloadExpr *Overloads = FR.Expression;
+
+    for (OverloadExpr::decls_iterator it = Overloads->decls_begin(),
+         DeclsEnd = Overloads->decls_end(); it != DeclsEnd; ++it) {
+      OverloadSet.addDecl(*it);
+
+      // Check whether the function is a non-template which takes no
+      // arguments.
+      if (const FunctionDecl *OverloadDecl
+            = dyn_cast<FunctionDecl>((*it)->getUnderlyingDecl())) {
+        if (OverloadDecl->getMinRequiredArguments() == 0)
+          ZeroArgCallReturnTy = OverloadDecl->getResultType();
+      }
+    }
+
+    // Ignore overloads that are pointer-to-member constants.
+    if (FR.HasFormOfMemberPointer)
+      return false;
+
+    return true;
+  }
+
+  if (const DeclRefExpr *DeclRef = dyn_cast<DeclRefExpr>(E.IgnoreParens())) {
+    if (const FunctionDecl *Fun = dyn_cast<FunctionDecl>(DeclRef->getDecl())) {
+      if (Fun->getMinRequiredArguments() == 0)
+        ZeroArgCallReturnTy = Fun->getResultType();
+      return true;
+    }
+  }
+
+  // We don't have an expression that's convenient to get a FunctionDecl from,
+  // but we can at least check if the type is "function of 0 arguments".
+  QualType ExprTy = E.getType();
+  const FunctionType *FunTy = NULL;
+  QualType PointeeTy = ExprTy->getPointeeType();
+  if (!PointeeTy.isNull())
+    FunTy = PointeeTy->getAs<FunctionType>();
+  if (!FunTy)
+    FunTy = ExprTy->getAs<FunctionType>();
+  if (!FunTy && ExprTy == Context.BoundMemberTy) {
+    // Look for the bound-member type.  If it's still overloaded, give up,
+    // although we probably should have fallen into the OverloadExpr case above
+    // if we actually have an overloaded bound member.
+    QualType BoundMemberTy = Expr::findBoundMemberType(&E);
+    if (!BoundMemberTy.isNull())
+      FunTy = BoundMemberTy->castAs<FunctionType>();
+  }
+
+  if (const FunctionProtoType *FPT =
+      dyn_cast_or_null<FunctionProtoType>(FunTy)) {
+    if (FPT->getNumArgs() == 0)
+      ZeroArgCallReturnTy = FunTy->getResultType();
+    return true;
+  }
+  return false;
+}
+
+/// \brief Give notes for a set of overloads.
+///
+/// A companion to isExprCallable. In cases when the name that the programmer
+/// wrote was an overloaded function, we may be able to make some guesses about
+/// plausible overloads based on their return types; such guesses can be handed
+/// off to this method to be emitted as notes.
+///
+/// \param Overloads - The overloads to note.
+/// \param FinalNoteLoc - If we've suppressed printing some overloads due to
+///  -fshow-overloads=best, this is the location to attach to the note about too
+///  many candidates. Typically this will be the location of the original
+///  ill-formed expression.
+static void noteOverloads(Sema &S, const UnresolvedSetImpl &Overloads,
+                          const SourceLocation FinalNoteLoc) {
+  int ShownOverloads = 0;
+  int SuppressedOverloads = 0;
+  for (UnresolvedSetImpl::iterator It = Overloads.begin(),
+       DeclsEnd = Overloads.end(); It != DeclsEnd; ++It) {
+    // FIXME: Magic number for max shown overloads stolen from
+    // OverloadCandidateSet::NoteCandidates.
+    if (ShownOverloads >= 4 &&
+        S.Diags.getShowOverloads() == DiagnosticsEngine::Ovl_Best) {
+      ++SuppressedOverloads;
+      continue;
+    }
+
+    NamedDecl *Fn = (*It)->getUnderlyingDecl();
+    S.Diag(Fn->getLocation(), diag::note_possible_target_of_call);
+    ++ShownOverloads;
+  }
+
+  if (SuppressedOverloads)
+    S.Diag(FinalNoteLoc, diag::note_ovl_too_many_candidates)
+      << SuppressedOverloads;
+}
+
+static void notePlausibleOverloads(Sema &S, SourceLocation Loc,
+                                   const UnresolvedSetImpl &Overloads,
+                                   bool (*IsPlausibleResult)(QualType)) {
+  if (!IsPlausibleResult)
+    return noteOverloads(S, Overloads, Loc);
+
+  UnresolvedSet<2> PlausibleOverloads;
+  for (OverloadExpr::decls_iterator It = Overloads.begin(),
+         DeclsEnd = Overloads.end(); It != DeclsEnd; ++It) {
+    const FunctionDecl *OverloadDecl = cast<FunctionDecl>(*It);
+    QualType OverloadResultTy = OverloadDecl->getResultType();
+    if (IsPlausibleResult(OverloadResultTy))
+      PlausibleOverloads.addDecl(It.getDecl());
+  }
+  noteOverloads(S, PlausibleOverloads, Loc);
+}
+
+/// Determine whether the given expression can be called by just
+/// putting parentheses after it.  Notably, expressions with unary
+/// operators can't be because the unary operator will start parsing
+/// outside the call.
+static bool IsCallableWithAppend(Expr *E) {
+  E = E->IgnoreImplicit();
+  return (!isa<CStyleCastExpr>(E) &&
+          !isa<UnaryOperator>(E) &&
+          !isa<BinaryOperator>(E) &&
+          !isa<CXXOperatorCallExpr>(E));
+}
+
+bool Sema::tryToRecoverWithCall(ExprResult &E, const PartialDiagnostic &PD,
+                                bool ForceComplain,
+                                bool (*IsPlausibleResult)(QualType)) {
+  SourceLocation Loc = E.get()->getExprLoc();
+  SourceRange Range = E.get()->getSourceRange();
+
+  QualType ZeroArgCallTy;
+  UnresolvedSet<4> Overloads;
+  if (isExprCallable(*E.get(), ZeroArgCallTy, Overloads) &&
+      !ZeroArgCallTy.isNull() &&
+      (!IsPlausibleResult || IsPlausibleResult(ZeroArgCallTy))) {
+    // At this point, we know E is potentially callable with 0
+    // arguments and that it returns something of a reasonable type,
+    // so we can emit a fixit and carry on pretending that E was
+    // actually a CallExpr.
+    SourceLocation ParenInsertionLoc =
+      PP.getLocForEndOfToken(Range.getEnd());
+    Diag(Loc, PD) 
+      << /*zero-arg*/ 1 << Range
+      << (IsCallableWithAppend(E.get())
+          ? FixItHint::CreateInsertion(ParenInsertionLoc, "()")
+          : FixItHint());
+    notePlausibleOverloads(*this, Loc, Overloads, IsPlausibleResult);
+
+    // FIXME: Try this before emitting the fixit, and suppress diagnostics
+    // while doing so.
+    E = ActOnCallExpr(0, E.take(), ParenInsertionLoc,
+                      MultiExprArg(*this, 0, 0),
+                      ParenInsertionLoc.getLocWithOffset(1));
+    return true;
+  }
+
+  if (!ForceComplain) return false;
+
+  Diag(Loc, PD) << /*not zero-arg*/ 0 << Range;
+  notePlausibleOverloads(*this, Loc, Overloads, IsPlausibleResult);
+  E = ExprError();
+  return true;
+}
diff --git a/clang/lib/Sema/SemaAccess.cpp b/clang/lib/Sema/SemaAccess.cpp
new file mode 100644
index 0000000..01c141e
--- /dev/null
+++ b/clang/lib/Sema/SemaAccess.cpp
@@ -0,0 +1,1850 @@
+//===---- SemaAccess.cpp - C++ Access Control -------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file provides Sema routines for C++ access control semantics.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Sema/SemaInternal.h"
+#include "clang/Sema/DelayedDiagnostic.h"
+#include "clang/Sema/Initialization.h"
+#include "clang/Sema/Lookup.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/CXXInheritance.h"
+#include "clang/AST/DeclCXX.h"
+#include "clang/AST/DeclFriend.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/AST/DependentDiagnostic.h"
+#include "clang/AST/ExprCXX.h"
+
+using namespace clang;
+using namespace sema;
+
+/// A copy of Sema's enum without AR_delayed.
+enum AccessResult {
+  AR_accessible,
+  AR_inaccessible,
+  AR_dependent
+};
+
+/// SetMemberAccessSpecifier - Set the access specifier of a member.
+/// Returns true on error (when the previous member decl access specifier
+/// is different from the new member decl access specifier).
+bool Sema::SetMemberAccessSpecifier(NamedDecl *MemberDecl,
+                                    NamedDecl *PrevMemberDecl,
+                                    AccessSpecifier LexicalAS) {
+  if (!PrevMemberDecl) {
+    // Use the lexical access specifier.
+    MemberDecl->setAccess(LexicalAS);
+    return false;
+  }
+
+  // C++ [class.access.spec]p3: When a member is redeclared its access
+  // specifier must be same as its initial declaration.
+  if (LexicalAS != AS_none && LexicalAS != PrevMemberDecl->getAccess()) {
+    Diag(MemberDecl->getLocation(),
+         diag::err_class_redeclared_with_different_access)
+      << MemberDecl << LexicalAS;
+    Diag(PrevMemberDecl->getLocation(), diag::note_previous_access_declaration)
+      << PrevMemberDecl << PrevMemberDecl->getAccess();
+
+    MemberDecl->setAccess(LexicalAS);
+    return true;
+  }
+
+  MemberDecl->setAccess(PrevMemberDecl->getAccess());
+  return false;
+}
+
+static CXXRecordDecl *FindDeclaringClass(NamedDecl *D) {
+  DeclContext *DC = D->getDeclContext();
+
+  // This can only happen at top: enum decls only "publish" their
+  // immediate members.
+  if (isa<EnumDecl>(DC))
+    DC = cast<EnumDecl>(DC)->getDeclContext();
+
+  CXXRecordDecl *DeclaringClass = cast<CXXRecordDecl>(DC);
+  while (DeclaringClass->isAnonymousStructOrUnion())
+    DeclaringClass = cast<CXXRecordDecl>(DeclaringClass->getDeclContext());
+  return DeclaringClass;
+}
+
+namespace {
+struct EffectiveContext {
+  EffectiveContext() : Inner(0), Dependent(false) {}
+
+  explicit EffectiveContext(DeclContext *DC)
+    : Inner(DC),
+      Dependent(DC->isDependentContext()) {
+
+    // C++ [class.access.nest]p1:
+    //   A nested class is a member and as such has the same access
+    //   rights as any other member.
+    // C++ [class.access]p2:
+    //   A member of a class can also access all the names to which
+    //   the class has access.  A local class of a member function
+    //   may access the same names that the member function itself
+    //   may access.
+    // This almost implies that the privileges of nesting are transitive.
+    // Technically it says nothing about the local classes of non-member
+    // functions (which can gain privileges through friendship), but we
+    // take that as an oversight.
+    while (true) {
+      if (isa<CXXRecordDecl>(DC)) {
+        CXXRecordDecl *Record = cast<CXXRecordDecl>(DC)->getCanonicalDecl();
+        Records.push_back(Record);
+        DC = Record->getDeclContext();
+      } else if (isa<FunctionDecl>(DC)) {
+        FunctionDecl *Function = cast<FunctionDecl>(DC)->getCanonicalDecl();
+        Functions.push_back(Function);
+        
+        if (Function->getFriendObjectKind())
+          DC = Function->getLexicalDeclContext();
+        else
+          DC = Function->getDeclContext();
+      } else if (DC->isFileContext()) {
+        break;
+      } else {
+        DC = DC->getParent();
+      }
+    }
+  }
+
+  bool isDependent() const { return Dependent; }
+
+  bool includesClass(const CXXRecordDecl *R) const {
+    R = R->getCanonicalDecl();
+    return std::find(Records.begin(), Records.end(), R)
+             != Records.end();
+  }
+
+  /// Retrieves the innermost "useful" context.  Can be null if we're
+  /// doing access-control without privileges.
+  DeclContext *getInnerContext() const {
+    return Inner;
+  }
+
+  typedef SmallVectorImpl<CXXRecordDecl*>::const_iterator record_iterator;
+
+  DeclContext *Inner;
+  SmallVector<FunctionDecl*, 4> Functions;
+  SmallVector<CXXRecordDecl*, 4> Records;
+  bool Dependent;
+};
+
+/// Like sema::AccessedEntity, but kindly lets us scribble all over
+/// it.
+struct AccessTarget : public AccessedEntity {
+  AccessTarget(const AccessedEntity &Entity)
+    : AccessedEntity(Entity) {
+    initialize();
+  }
+    
+  AccessTarget(ASTContext &Context, 
+               MemberNonce _,
+               CXXRecordDecl *NamingClass,
+               DeclAccessPair FoundDecl,
+               QualType BaseObjectType)
+    : AccessedEntity(Context, Member, NamingClass, FoundDecl, BaseObjectType) {
+    initialize();
+  }
+
+  AccessTarget(ASTContext &Context, 
+               BaseNonce _,
+               CXXRecordDecl *BaseClass,
+               CXXRecordDecl *DerivedClass,
+               AccessSpecifier Access)
+    : AccessedEntity(Context, Base, BaseClass, DerivedClass, Access) {
+    initialize();
+  }
+
+  bool isInstanceMember() const {
+    return (isMemberAccess() && getTargetDecl()->isCXXInstanceMember());
+  }
+
+  bool hasInstanceContext() const {
+    return HasInstanceContext;
+  }
+
+  class SavedInstanceContext {
+  public:
+    ~SavedInstanceContext() {
+      Target.HasInstanceContext = Has;
+    }
+
+  private:
+    friend struct AccessTarget;
+    explicit SavedInstanceContext(AccessTarget &Target)
+      : Target(Target), Has(Target.HasInstanceContext) {}
+    AccessTarget &Target;
+    bool Has;
+  };
+
+  SavedInstanceContext saveInstanceContext() {
+    return SavedInstanceContext(*this);
+  }
+
+  void suppressInstanceContext() {
+    HasInstanceContext = false;
+  }
+
+  const CXXRecordDecl *resolveInstanceContext(Sema &S) const {
+    assert(HasInstanceContext);
+    if (CalculatedInstanceContext)
+      return InstanceContext;
+
+    CalculatedInstanceContext = true;
+    DeclContext *IC = S.computeDeclContext(getBaseObjectType());
+    InstanceContext = (IC ? cast<CXXRecordDecl>(IC)->getCanonicalDecl() : 0);
+    return InstanceContext;
+  }
+
+  const CXXRecordDecl *getDeclaringClass() const {
+    return DeclaringClass;
+  }
+
+private:
+  void initialize() {
+    HasInstanceContext = (isMemberAccess() &&
+                          !getBaseObjectType().isNull() &&
+                          getTargetDecl()->isCXXInstanceMember());
+    CalculatedInstanceContext = false;
+    InstanceContext = 0;
+
+    if (isMemberAccess())
+      DeclaringClass = FindDeclaringClass(getTargetDecl());
+    else
+      DeclaringClass = getBaseClass();
+    DeclaringClass = DeclaringClass->getCanonicalDecl();
+  }
+
+  bool HasInstanceContext : 1;
+  mutable bool CalculatedInstanceContext : 1;
+  mutable const CXXRecordDecl *InstanceContext;
+  const CXXRecordDecl *DeclaringClass;
+};
+
+}
+
+/// Checks whether one class might instantiate to the other.
+static bool MightInstantiateTo(const CXXRecordDecl *From,
+                               const CXXRecordDecl *To) {
+  // Declaration names are always preserved by instantiation.
+  if (From->getDeclName() != To->getDeclName())
+    return false;
+
+  const DeclContext *FromDC = From->getDeclContext()->getPrimaryContext();
+  const DeclContext *ToDC = To->getDeclContext()->getPrimaryContext();
+  if (FromDC == ToDC) return true;
+  if (FromDC->isFileContext() || ToDC->isFileContext()) return false;
+
+  // Be conservative.
+  return true;
+}
+
+/// Checks whether one class is derived from another, inclusively.
+/// Properly indicates when it couldn't be determined due to
+/// dependence.
+///
+/// This should probably be donated to AST or at least Sema.
+static AccessResult IsDerivedFromInclusive(const CXXRecordDecl *Derived,
+                                           const CXXRecordDecl *Target) {
+  assert(Derived->getCanonicalDecl() == Derived);
+  assert(Target->getCanonicalDecl() == Target);
+
+  if (Derived == Target) return AR_accessible;
+
+  bool CheckDependent = Derived->isDependentContext();
+  if (CheckDependent && MightInstantiateTo(Derived, Target))
+    return AR_dependent;
+
+  AccessResult OnFailure = AR_inaccessible;
+  SmallVector<const CXXRecordDecl*, 8> Queue; // actually a stack
+
+  while (true) {
+    if (Derived->isDependentContext() && !Derived->hasDefinition())
+      return AR_dependent;
+    
+    for (CXXRecordDecl::base_class_const_iterator
+           I = Derived->bases_begin(), E = Derived->bases_end(); I != E; ++I) {
+
+      const CXXRecordDecl *RD;
+
+      QualType T = I->getType();
+      if (const RecordType *RT = T->getAs<RecordType>()) {
+        RD = cast<CXXRecordDecl>(RT->getDecl());
+      } else if (const InjectedClassNameType *IT
+                   = T->getAs<InjectedClassNameType>()) {
+        RD = IT->getDecl();
+      } else {
+        assert(T->isDependentType() && "non-dependent base wasn't a record?");
+        OnFailure = AR_dependent;
+        continue;
+      }
+
+      RD = RD->getCanonicalDecl();
+      if (RD == Target) return AR_accessible;
+      if (CheckDependent && MightInstantiateTo(RD, Target))
+        OnFailure = AR_dependent;
+
+      Queue.push_back(RD);
+    }
+
+    if (Queue.empty()) break;
+
+    Derived = Queue.back();
+    Queue.pop_back();
+  }
+
+  return OnFailure;
+}
+
+
+static bool MightInstantiateTo(Sema &S, DeclContext *Context,
+                               DeclContext *Friend) {
+  if (Friend == Context)
+    return true;
+
+  assert(!Friend->isDependentContext() &&
+         "can't handle friends with dependent contexts here");
+
+  if (!Context->isDependentContext())
+    return false;
+
+  if (Friend->isFileContext())
+    return false;
+
+  // TODO: this is very conservative
+  return true;
+}
+
+// Asks whether the type in 'context' can ever instantiate to the type
+// in 'friend'.
+static bool MightInstantiateTo(Sema &S, CanQualType Context, CanQualType Friend) {
+  if (Friend == Context)
+    return true;
+
+  if (!Friend->isDependentType() && !Context->isDependentType())
+    return false;
+
+  // TODO: this is very conservative.
+  return true;
+}
+
+static bool MightInstantiateTo(Sema &S,
+                               FunctionDecl *Context,
+                               FunctionDecl *Friend) {
+  if (Context->getDeclName() != Friend->getDeclName())
+    return false;
+
+  if (!MightInstantiateTo(S,
+                          Context->getDeclContext(),
+                          Friend->getDeclContext()))
+    return false;
+
+  CanQual<FunctionProtoType> FriendTy
+    = S.Context.getCanonicalType(Friend->getType())
+         ->getAs<FunctionProtoType>();
+  CanQual<FunctionProtoType> ContextTy
+    = S.Context.getCanonicalType(Context->getType())
+         ->getAs<FunctionProtoType>();
+
+  // There isn't any way that I know of to add qualifiers
+  // during instantiation.
+  if (FriendTy.getQualifiers() != ContextTy.getQualifiers())
+    return false;
+
+  if (FriendTy->getNumArgs() != ContextTy->getNumArgs())
+    return false;
+
+  if (!MightInstantiateTo(S,
+                          ContextTy->getResultType(),
+                          FriendTy->getResultType()))
+    return false;
+
+  for (unsigned I = 0, E = FriendTy->getNumArgs(); I != E; ++I)
+    if (!MightInstantiateTo(S,
+                            ContextTy->getArgType(I),
+                            FriendTy->getArgType(I)))
+      return false;
+
+  return true;
+}
+
+static bool MightInstantiateTo(Sema &S,
+                               FunctionTemplateDecl *Context,
+                               FunctionTemplateDecl *Friend) {
+  return MightInstantiateTo(S,
+                            Context->getTemplatedDecl(),
+                            Friend->getTemplatedDecl());
+}
+
+static AccessResult MatchesFriend(Sema &S,
+                                  const EffectiveContext &EC,
+                                  const CXXRecordDecl *Friend) {
+  if (EC.includesClass(Friend))
+    return AR_accessible;
+
+  if (EC.isDependent()) {
+    CanQualType FriendTy
+      = S.Context.getCanonicalType(S.Context.getTypeDeclType(Friend));
+
+    for (EffectiveContext::record_iterator
+           I = EC.Records.begin(), E = EC.Records.end(); I != E; ++I) {
+      CanQualType ContextTy
+        = S.Context.getCanonicalType(S.Context.getTypeDeclType(*I));
+      if (MightInstantiateTo(S, ContextTy, FriendTy))
+        return AR_dependent;
+    }
+  }
+
+  return AR_inaccessible;
+}
+
+static AccessResult MatchesFriend(Sema &S,
+                                  const EffectiveContext &EC,
+                                  CanQualType Friend) {
+  if (const RecordType *RT = Friend->getAs<RecordType>())
+    return MatchesFriend(S, EC, cast<CXXRecordDecl>(RT->getDecl()));
+
+  // TODO: we can do better than this
+  if (Friend->isDependentType())
+    return AR_dependent;
+
+  return AR_inaccessible;
+}
+
+/// Determines whether the given friend class template matches
+/// anything in the effective context.
+static AccessResult MatchesFriend(Sema &S,
+                                  const EffectiveContext &EC,
+                                  ClassTemplateDecl *Friend) {
+  AccessResult OnFailure = AR_inaccessible;
+
+  // Check whether the friend is the template of a class in the
+  // context chain.
+  for (SmallVectorImpl<CXXRecordDecl*>::const_iterator
+         I = EC.Records.begin(), E = EC.Records.end(); I != E; ++I) {
+    CXXRecordDecl *Record = *I;
+
+    // Figure out whether the current class has a template:
+    ClassTemplateDecl *CTD;
+
+    // A specialization of the template...
+    if (isa<ClassTemplateSpecializationDecl>(Record)) {
+      CTD = cast<ClassTemplateSpecializationDecl>(Record)
+        ->getSpecializedTemplate();
+
+    // ... or the template pattern itself.
+    } else {
+      CTD = Record->getDescribedClassTemplate();
+      if (!CTD) continue;
+    }
+
+    // It's a match.
+    if (Friend == CTD->getCanonicalDecl())
+      return AR_accessible;
+
+    // If the context isn't dependent, it can't be a dependent match.
+    if (!EC.isDependent())
+      continue;
+
+    // If the template names don't match, it can't be a dependent
+    // match.
+    if (CTD->getDeclName() != Friend->getDeclName())
+      continue;
+
+    // If the class's context can't instantiate to the friend's
+    // context, it can't be a dependent match.
+    if (!MightInstantiateTo(S, CTD->getDeclContext(),
+                            Friend->getDeclContext()))
+      continue;
+
+    // Otherwise, it's a dependent match.
+    OnFailure = AR_dependent;
+  }
+
+  return OnFailure;
+}
+
+/// Determines whether the given friend function matches anything in
+/// the effective context.
+static AccessResult MatchesFriend(Sema &S,
+                                  const EffectiveContext &EC,
+                                  FunctionDecl *Friend) {
+  AccessResult OnFailure = AR_inaccessible;
+
+  for (SmallVectorImpl<FunctionDecl*>::const_iterator
+         I = EC.Functions.begin(), E = EC.Functions.end(); I != E; ++I) {
+    if (Friend == *I)
+      return AR_accessible;
+
+    if (EC.isDependent() && MightInstantiateTo(S, *I, Friend))
+      OnFailure = AR_dependent;
+  }
+
+  return OnFailure;
+}
+
+/// Determines whether the given friend function template matches
+/// anything in the effective context.
+static AccessResult MatchesFriend(Sema &S,
+                                  const EffectiveContext &EC,
+                                  FunctionTemplateDecl *Friend) {
+  if (EC.Functions.empty()) return AR_inaccessible;
+
+  AccessResult OnFailure = AR_inaccessible;
+
+  for (SmallVectorImpl<FunctionDecl*>::const_iterator
+         I = EC.Functions.begin(), E = EC.Functions.end(); I != E; ++I) {
+
+    FunctionTemplateDecl *FTD = (*I)->getPrimaryTemplate();
+    if (!FTD)
+      FTD = (*I)->getDescribedFunctionTemplate();
+    if (!FTD)
+      continue;
+
+    FTD = FTD->getCanonicalDecl();
+
+    if (Friend == FTD)
+      return AR_accessible;
+
+    if (EC.isDependent() && MightInstantiateTo(S, FTD, Friend))
+      OnFailure = AR_dependent;
+  }
+
+  return OnFailure;
+}
+
+/// Determines whether the given friend declaration matches anything
+/// in the effective context.
+static AccessResult MatchesFriend(Sema &S,
+                                  const EffectiveContext &EC,
+                                  FriendDecl *FriendD) {
+  // Whitelist accesses if there's an invalid or unsupported friend
+  // declaration.
+  if (FriendD->isInvalidDecl() || FriendD->isUnsupportedFriend())
+    return AR_accessible;
+
+  if (TypeSourceInfo *T = FriendD->getFriendType())
+    return MatchesFriend(S, EC, T->getType()->getCanonicalTypeUnqualified());
+
+  NamedDecl *Friend
+    = cast<NamedDecl>(FriendD->getFriendDecl()->getCanonicalDecl());
+
+  // FIXME: declarations with dependent or templated scope.
+
+  if (isa<ClassTemplateDecl>(Friend))
+    return MatchesFriend(S, EC, cast<ClassTemplateDecl>(Friend));
+
+  if (isa<FunctionTemplateDecl>(Friend))
+    return MatchesFriend(S, EC, cast<FunctionTemplateDecl>(Friend));
+
+  if (isa<CXXRecordDecl>(Friend))
+    return MatchesFriend(S, EC, cast<CXXRecordDecl>(Friend));
+
+  assert(isa<FunctionDecl>(Friend) && "unknown friend decl kind");
+  return MatchesFriend(S, EC, cast<FunctionDecl>(Friend));
+}
+
+static AccessResult GetFriendKind(Sema &S,
+                                  const EffectiveContext &EC,
+                                  const CXXRecordDecl *Class) {
+  AccessResult OnFailure = AR_inaccessible;
+
+  // Okay, check friends.
+  for (CXXRecordDecl::friend_iterator I = Class->friend_begin(),
+         E = Class->friend_end(); I != E; ++I) {
+    FriendDecl *Friend = *I;
+
+    switch (MatchesFriend(S, EC, Friend)) {
+    case AR_accessible:
+      return AR_accessible;
+
+    case AR_inaccessible:
+      continue;
+
+    case AR_dependent:
+      OnFailure = AR_dependent;
+      break;
+    }
+  }
+
+  // That's it, give up.
+  return OnFailure;
+}
+
+namespace {
+
+/// A helper class for checking for a friend which will grant access
+/// to a protected instance member.
+struct ProtectedFriendContext {
+  Sema &S;
+  const EffectiveContext &EC;
+  const CXXRecordDecl *NamingClass;
+  bool CheckDependent;
+  bool EverDependent;
+
+  /// The path down to the current base class.
+  SmallVector<const CXXRecordDecl*, 20> CurPath;
+
+  ProtectedFriendContext(Sema &S, const EffectiveContext &EC,
+                         const CXXRecordDecl *InstanceContext,
+                         const CXXRecordDecl *NamingClass)
+    : S(S), EC(EC), NamingClass(NamingClass),
+      CheckDependent(InstanceContext->isDependentContext() ||
+                     NamingClass->isDependentContext()),
+      EverDependent(false) {}
+
+  /// Check classes in the current path for friendship, starting at
+  /// the given index.
+  bool checkFriendshipAlongPath(unsigned I) {
+    assert(I < CurPath.size());
+    for (unsigned E = CurPath.size(); I != E; ++I) {
+      switch (GetFriendKind(S, EC, CurPath[I])) {
+      case AR_accessible:   return true;
+      case AR_inaccessible: continue;
+      case AR_dependent:    EverDependent = true; continue;
+      }
+    }
+    return false;
+  }
+
+  /// Perform a search starting at the given class.
+  ///
+  /// PrivateDepth is the index of the last (least derived) class
+  /// along the current path such that a notional public member of
+  /// the final class in the path would have access in that class.
+  bool findFriendship(const CXXRecordDecl *Cur, unsigned PrivateDepth) {
+    // If we ever reach the naming class, check the current path for
+    // friendship.  We can also stop recursing because we obviously
+    // won't find the naming class there again.
+    if (Cur == NamingClass)
+      return checkFriendshipAlongPath(PrivateDepth);
+
+    if (CheckDependent && MightInstantiateTo(Cur, NamingClass))
+      EverDependent = true;
+
+    // Recurse into the base classes.
+    for (CXXRecordDecl::base_class_const_iterator
+           I = Cur->bases_begin(), E = Cur->bases_end(); I != E; ++I) {
+
+      // If this is private inheritance, then a public member of the
+      // base will not have any access in classes derived from Cur.
+      unsigned BasePrivateDepth = PrivateDepth;
+      if (I->getAccessSpecifier() == AS_private)
+        BasePrivateDepth = CurPath.size() - 1;
+
+      const CXXRecordDecl *RD;
+
+      QualType T = I->getType();
+      if (const RecordType *RT = T->getAs<RecordType>()) {
+        RD = cast<CXXRecordDecl>(RT->getDecl());
+      } else if (const InjectedClassNameType *IT
+                   = T->getAs<InjectedClassNameType>()) {
+        RD = IT->getDecl();
+      } else {
+        assert(T->isDependentType() && "non-dependent base wasn't a record?");
+        EverDependent = true;
+        continue;
+      }
+
+      // Recurse.  We don't need to clean up if this returns true.
+      CurPath.push_back(RD);
+      if (findFriendship(RD->getCanonicalDecl(), BasePrivateDepth))
+        return true;
+      CurPath.pop_back();
+    }
+
+    return false;
+  }
+
+  bool findFriendship(const CXXRecordDecl *Cur) {
+    assert(CurPath.empty());
+    CurPath.push_back(Cur);
+    return findFriendship(Cur, 0);
+  }
+};
+}
+
+/// Search for a class P that EC is a friend of, under the constraint
+///   InstanceContext <= P
+/// if InstanceContext exists, or else
+///   NamingClass <= P
+/// and with the additional restriction that a protected member of
+/// NamingClass would have some natural access in P, which implicitly
+/// imposes the constraint that P <= NamingClass.
+///
+/// This isn't quite the condition laid out in the standard.
+/// Instead of saying that a notional protected member of NamingClass
+/// would have to have some natural access in P, it says the actual
+/// target has to have some natural access in P, which opens up the
+/// possibility that the target (which is not necessarily a member
+/// of NamingClass) might be more accessible along some path not
+/// passing through it.  That's really a bad idea, though, because it
+/// introduces two problems:
+///   - Most importantly, it breaks encapsulation because you can
+///     access a forbidden base class's members by directly subclassing
+///     it elsewhere.
+///   - It also makes access substantially harder to compute because it
+///     breaks the hill-climbing algorithm: knowing that the target is
+///     accessible in some base class would no longer let you change
+///     the question solely to whether the base class is accessible,
+///     because the original target might have been more accessible
+///     because of crazy subclassing.
+/// So we don't implement that.
+static AccessResult GetProtectedFriendKind(Sema &S, const EffectiveContext &EC,
+                                           const CXXRecordDecl *InstanceContext,
+                                           const CXXRecordDecl *NamingClass) {
+  assert(InstanceContext == 0 ||
+         InstanceContext->getCanonicalDecl() == InstanceContext);
+  assert(NamingClass->getCanonicalDecl() == NamingClass);
+
+  // If we don't have an instance context, our constraints give us
+  // that NamingClass <= P <= NamingClass, i.e. P == NamingClass.
+  // This is just the usual friendship check.
+  if (!InstanceContext) return GetFriendKind(S, EC, NamingClass);
+
+  ProtectedFriendContext PRC(S, EC, InstanceContext, NamingClass);
+  if (PRC.findFriendship(InstanceContext)) return AR_accessible;
+  if (PRC.EverDependent) return AR_dependent;
+  return AR_inaccessible;
+}
+
+static AccessResult HasAccess(Sema &S,
+                              const EffectiveContext &EC,
+                              const CXXRecordDecl *NamingClass,
+                              AccessSpecifier Access,
+                              const AccessTarget &Target) {
+  assert(NamingClass->getCanonicalDecl() == NamingClass &&
+         "declaration should be canonicalized before being passed here");
+
+  if (Access == AS_public) return AR_accessible;
+  assert(Access == AS_private || Access == AS_protected);
+
+  AccessResult OnFailure = AR_inaccessible;
+
+  for (EffectiveContext::record_iterator
+         I = EC.Records.begin(), E = EC.Records.end(); I != E; ++I) {
+    // All the declarations in EC have been canonicalized, so pointer
+    // equality from this point on will work fine.
+    const CXXRecordDecl *ECRecord = *I;
+
+    // [B2] and [M2]
+    if (Access == AS_private) {
+      if (ECRecord == NamingClass)
+        return AR_accessible;
+
+      if (EC.isDependent() && MightInstantiateTo(ECRecord, NamingClass))
+        OnFailure = AR_dependent;
+
+    // [B3] and [M3]
+    } else {
+      assert(Access == AS_protected);
+      switch (IsDerivedFromInclusive(ECRecord, NamingClass)) {
+      case AR_accessible: break;
+      case AR_inaccessible: continue;
+      case AR_dependent: OnFailure = AR_dependent; continue;
+      }
+
+      // C++ [class.protected]p1:
+      //   An additional access check beyond those described earlier in
+      //   [class.access] is applied when a non-static data member or
+      //   non-static member function is a protected member of its naming
+      //   class.  As described earlier, access to a protected member is
+      //   granted because the reference occurs in a friend or member of
+      //   some class C.  If the access is to form a pointer to member,
+      //   the nested-name-specifier shall name C or a class derived from
+      //   C. All other accesses involve a (possibly implicit) object
+      //   expression. In this case, the class of the object expression
+      //   shall be C or a class derived from C.
+      //
+      // We interpret this as a restriction on [M3].
+
+      // In this part of the code, 'C' is just our context class ECRecord.
+      
+      // These rules are different if we don't have an instance context.
+      if (!Target.hasInstanceContext()) {
+        // If it's not an instance member, these restrictions don't apply.
+        if (!Target.isInstanceMember()) return AR_accessible;
+
+        // If it's an instance member, use the pointer-to-member rule
+        // that the naming class has to be derived from the effective
+        // context.
+
+        // Emulate a MSVC bug where the creation of pointer-to-member
+        // to protected member of base class is allowed but only from
+        // a static function member functions.
+        if (S.getLangOpts().MicrosoftMode && !EC.Functions.empty())
+          if (CXXMethodDecl* MD = dyn_cast<CXXMethodDecl>(EC.Functions.front()))
+            if (MD->isStatic()) return AR_accessible;
+
+        // Despite the standard's confident wording, there is a case
+        // where you can have an instance member that's neither in a
+        // pointer-to-member expression nor in a member access:  when
+        // it names a field in an unevaluated context that can't be an
+        // implicit member.  Pending clarification, we just apply the
+        // same naming-class restriction here.
+        //   FIXME: we're probably not correctly adding the
+        //   protected-member restriction when we retroactively convert
+        //   an expression to being evaluated.
+
+        // We know that ECRecord derives from NamingClass.  The
+        // restriction says to check whether NamingClass derives from
+        // ECRecord, but that's not really necessary: two distinct
+        // classes can't be recursively derived from each other.  So
+        // along this path, we just need to check whether the classes
+        // are equal.
+        if (NamingClass == ECRecord) return AR_accessible;
+
+        // Otherwise, this context class tells us nothing;  on to the next.
+        continue;
+      }
+
+      assert(Target.isInstanceMember());
+
+      const CXXRecordDecl *InstanceContext = Target.resolveInstanceContext(S);
+      if (!InstanceContext) {
+        OnFailure = AR_dependent;
+        continue;
+      }
+
+      switch (IsDerivedFromInclusive(InstanceContext, ECRecord)) {
+      case AR_accessible: return AR_accessible;
+      case AR_inaccessible: continue;
+      case AR_dependent: OnFailure = AR_dependent; continue;
+      }
+    }
+  }
+
+  // [M3] and [B3] say that, if the target is protected in N, we grant
+  // access if the access occurs in a friend or member of some class P
+  // that's a subclass of N and where the target has some natural
+  // access in P.  The 'member' aspect is easy to handle because P
+  // would necessarily be one of the effective-context records, and we
+  // address that above.  The 'friend' aspect is completely ridiculous
+  // to implement because there are no restrictions at all on P
+  // *unless* the [class.protected] restriction applies.  If it does,
+  // however, we should ignore whether the naming class is a friend,
+  // and instead rely on whether any potential P is a friend.
+  if (Access == AS_protected && Target.isInstanceMember()) {
+    // Compute the instance context if possible.
+    const CXXRecordDecl *InstanceContext = 0;
+    if (Target.hasInstanceContext()) {
+      InstanceContext = Target.resolveInstanceContext(S);
+      if (!InstanceContext) return AR_dependent;
+    }
+
+    switch (GetProtectedFriendKind(S, EC, InstanceContext, NamingClass)) {
+    case AR_accessible: return AR_accessible;
+    case AR_inaccessible: return OnFailure;
+    case AR_dependent: return AR_dependent;
+    }
+    llvm_unreachable("impossible friendship kind");
+  }
+
+  switch (GetFriendKind(S, EC, NamingClass)) {
+  case AR_accessible: return AR_accessible;
+  case AR_inaccessible: return OnFailure;
+  case AR_dependent: return AR_dependent;
+  }
+
+  // Silence bogus warnings
+  llvm_unreachable("impossible friendship kind");
+}
+
+/// Finds the best path from the naming class to the declaring class,
+/// taking friend declarations into account.
+///
+/// C++0x [class.access.base]p5:
+///   A member m is accessible at the point R when named in class N if
+///   [M1] m as a member of N is public, or
+///   [M2] m as a member of N is private, and R occurs in a member or
+///        friend of class N, or
+///   [M3] m as a member of N is protected, and R occurs in a member or
+///        friend of class N, or in a member or friend of a class P
+///        derived from N, where m as a member of P is public, private,
+///        or protected, or
+///   [M4] there exists a base class B of N that is accessible at R, and
+///        m is accessible at R when named in class B.
+///
+/// C++0x [class.access.base]p4:
+///   A base class B of N is accessible at R, if
+///   [B1] an invented public member of B would be a public member of N, or
+///   [B2] R occurs in a member or friend of class N, and an invented public
+///        member of B would be a private or protected member of N, or
+///   [B3] R occurs in a member or friend of a class P derived from N, and an
+///        invented public member of B would be a private or protected member
+///        of P, or
+///   [B4] there exists a class S such that B is a base class of S accessible
+///        at R and S is a base class of N accessible at R.
+///
+/// Along a single inheritance path we can restate both of these
+/// iteratively:
+///
+/// First, we note that M1-4 are equivalent to B1-4 if the member is
+/// treated as a notional base of its declaring class with inheritance
+/// access equivalent to the member's access.  Therefore we need only
+/// ask whether a class B is accessible from a class N in context R.
+///
+/// Let B_1 .. B_n be the inheritance path in question (i.e. where
+/// B_1 = N, B_n = B, and for all i, B_{i+1} is a direct base class of
+/// B_i).  For i in 1..n, we will calculate ACAB(i), the access to the
+/// closest accessible base in the path:
+///   Access(a, b) = (* access on the base specifier from a to b *)
+///   Merge(a, forbidden) = forbidden
+///   Merge(a, private) = forbidden
+///   Merge(a, b) = min(a,b)
+///   Accessible(c, forbidden) = false
+///   Accessible(c, private) = (R is c) || IsFriend(c, R)
+///   Accessible(c, protected) = (R derived from c) || IsFriend(c, R)
+///   Accessible(c, public) = true
+///   ACAB(n) = public
+///   ACAB(i) =
+///     let AccessToBase = Merge(Access(B_i, B_{i+1}), ACAB(i+1)) in
+///     if Accessible(B_i, AccessToBase) then public else AccessToBase
+///
+/// B is an accessible base of N at R iff ACAB(1) = public.
+///
+/// \param FinalAccess the access of the "final step", or AS_public if
+///   there is no final step.
+/// \return null if friendship is dependent
+static CXXBasePath *FindBestPath(Sema &S,
+                                 const EffectiveContext &EC,
+                                 AccessTarget &Target,
+                                 AccessSpecifier FinalAccess,
+                                 CXXBasePaths &Paths) {
+  // Derive the paths to the desired base.
+  const CXXRecordDecl *Derived = Target.getNamingClass();
+  const CXXRecordDecl *Base = Target.getDeclaringClass();
+
+  // FIXME: fail correctly when there are dependent paths.
+  bool isDerived = Derived->isDerivedFrom(const_cast<CXXRecordDecl*>(Base),
+                                          Paths);
+  assert(isDerived && "derived class not actually derived from base");
+  (void) isDerived;
+
+  CXXBasePath *BestPath = 0;
+
+  assert(FinalAccess != AS_none && "forbidden access after declaring class");
+
+  bool AnyDependent = false;
+
+  // Derive the friend-modified access along each path.
+  for (CXXBasePaths::paths_iterator PI = Paths.begin(), PE = Paths.end();
+         PI != PE; ++PI) {
+    AccessTarget::SavedInstanceContext _ = Target.saveInstanceContext();
+
+    // Walk through the path backwards.
+    AccessSpecifier PathAccess = FinalAccess;
+    CXXBasePath::iterator I = PI->end(), E = PI->begin();
+    while (I != E) {
+      --I;
+
+      assert(PathAccess != AS_none);
+
+      // If the declaration is a private member of a base class, there
+      // is no level of friendship in derived classes that can make it
+      // accessible.
+      if (PathAccess == AS_private) {
+        PathAccess = AS_none;
+        break;
+      }
+
+      const CXXRecordDecl *NC = I->Class->getCanonicalDecl();
+
+      AccessSpecifier BaseAccess = I->Base->getAccessSpecifier();
+      PathAccess = std::max(PathAccess, BaseAccess);
+
+      switch (HasAccess(S, EC, NC, PathAccess, Target)) {
+      case AR_inaccessible: break;
+      case AR_accessible:
+        PathAccess = AS_public;
+
+        // Future tests are not against members and so do not have
+        // instance context.
+        Target.suppressInstanceContext();
+        break;
+      case AR_dependent:
+        AnyDependent = true;
+        goto Next;
+      }
+    }
+
+    // Note that we modify the path's Access field to the
+    // friend-modified access.
+    if (BestPath == 0 || PathAccess < BestPath->Access) {
+      BestPath = &*PI;
+      BestPath->Access = PathAccess;
+
+      // Short-circuit if we found a public path.
+      if (BestPath->Access == AS_public)
+        return BestPath;
+    }
+
+  Next: ;
+  }
+
+  assert((!BestPath || BestPath->Access != AS_public) &&
+         "fell out of loop with public path");
+
+  // We didn't find a public path, but at least one path was subject
+  // to dependent friendship, so delay the check.
+  if (AnyDependent)
+    return 0;
+
+  return BestPath;
+}
+
+/// Given that an entity has protected natural access, check whether
+/// access might be denied because of the protected member access
+/// restriction.
+///
+/// \return true if a note was emitted
+static bool TryDiagnoseProtectedAccess(Sema &S, const EffectiveContext &EC,
+                                       AccessTarget &Target) {
+  // Only applies to instance accesses.
+  if (!Target.isInstanceMember())
+    return false;
+
+  assert(Target.isMemberAccess());
+
+  const CXXRecordDecl *NamingClass = Target.getNamingClass();
+  NamingClass = NamingClass->getCanonicalDecl();
+
+  for (EffectiveContext::record_iterator
+         I = EC.Records.begin(), E = EC.Records.end(); I != E; ++I) {
+    const CXXRecordDecl *ECRecord = *I;
+    switch (IsDerivedFromInclusive(ECRecord, NamingClass)) {
+    case AR_accessible: break;
+    case AR_inaccessible: continue;
+    case AR_dependent: continue;
+    }
+
+    // The effective context is a subclass of the declaring class.
+    // Check whether the [class.protected] restriction is limiting
+    // access.
+
+    // To get this exactly right, this might need to be checked more
+    // holistically;  it's not necessarily the case that gaining
+    // access here would grant us access overall.
+
+    NamedDecl *D = Target.getTargetDecl();
+
+    // If we don't have an instance context, [class.protected] says the
+    // naming class has to equal the context class.
+    if (!Target.hasInstanceContext()) {
+      // If it does, the restriction doesn't apply.
+      if (NamingClass == ECRecord) continue;
+
+      // TODO: it would be great to have a fixit here, since this is
+      // such an obvious error.
+      S.Diag(D->getLocation(), diag::note_access_protected_restricted_noobject)
+        << S.Context.getTypeDeclType(ECRecord);
+      return true;
+    }
+
+    const CXXRecordDecl *InstanceContext = Target.resolveInstanceContext(S);
+    assert(InstanceContext && "diagnosing dependent access");
+
+    switch (IsDerivedFromInclusive(InstanceContext, ECRecord)) {
+    case AR_accessible: continue;
+    case AR_dependent: continue;
+    case AR_inaccessible:
+      break;
+    }
+
+    // Okay, the restriction seems to be what's limiting us.
+
+    // Use a special diagnostic for constructors and destructors.
+    if (isa<CXXConstructorDecl>(D) || isa<CXXDestructorDecl>(D) ||
+        (isa<FunctionTemplateDecl>(D) &&
+         isa<CXXConstructorDecl>(
+                cast<FunctionTemplateDecl>(D)->getTemplatedDecl()))) {
+      S.Diag(D->getLocation(), diag::note_access_protected_restricted_ctordtor)
+        << isa<CXXDestructorDecl>(D);
+      return true;
+    }
+
+    // Otherwise, use the generic diagnostic.
+    S.Diag(D->getLocation(), diag::note_access_protected_restricted_object)
+      << S.Context.getTypeDeclType(ECRecord);
+    return true;
+  }
+
+  return false;
+}
+
+/// Diagnose the path which caused the given declaration or base class
+/// to become inaccessible.
+static void DiagnoseAccessPath(Sema &S,
+                               const EffectiveContext &EC,
+                               AccessTarget &Entity) {
+  AccessSpecifier Access = Entity.getAccess();
+
+  NamedDecl *D = (Entity.isMemberAccess() ? Entity.getTargetDecl() : 0);
+  const CXXRecordDecl *DeclaringClass = Entity.getDeclaringClass();
+
+  // Easy case: the decl's natural access determined its path access.
+  // We have to check against AS_private here in case Access is AS_none,
+  // indicating a non-public member of a private base class.
+  if (D && (Access == D->getAccess() || D->getAccess() == AS_private)) {
+    switch (HasAccess(S, EC, DeclaringClass, D->getAccess(), Entity)) {
+    case AR_inaccessible: {
+      if (Access == AS_protected &&
+          TryDiagnoseProtectedAccess(S, EC, Entity))
+        return;
+
+      // Find an original declaration.
+      while (D->isOutOfLine()) {
+        NamedDecl *PrevDecl = 0;
+        if (VarDecl *VD = dyn_cast<VarDecl>(D))
+          PrevDecl = VD->getPreviousDecl();
+        else if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
+          PrevDecl = FD->getPreviousDecl();
+        else if (TypedefNameDecl *TND = dyn_cast<TypedefNameDecl>(D))
+          PrevDecl = TND->getPreviousDecl();
+        else if (TagDecl *TD = dyn_cast<TagDecl>(D)) {
+          if (isa<RecordDecl>(D) && cast<RecordDecl>(D)->isInjectedClassName())
+            break;
+          PrevDecl = TD->getPreviousDecl();
+        }
+        if (!PrevDecl) break;
+        D = PrevDecl;
+      }
+
+      CXXRecordDecl *DeclaringClass = FindDeclaringClass(D);
+      Decl *ImmediateChild;
+      if (D->getDeclContext() == DeclaringClass)
+        ImmediateChild = D;
+      else {
+        DeclContext *DC = D->getDeclContext();
+        while (DC->getParent() != DeclaringClass)
+          DC = DC->getParent();
+        ImmediateChild = cast<Decl>(DC);
+      }
+      
+      // Check whether there's an AccessSpecDecl preceding this in the
+      // chain of the DeclContext.
+      bool Implicit = true;
+      for (CXXRecordDecl::decl_iterator
+             I = DeclaringClass->decls_begin(), E = DeclaringClass->decls_end();
+           I != E; ++I) {
+        if (*I == ImmediateChild) break;
+        if (isa<AccessSpecDecl>(*I)) {
+          Implicit = false;
+          break;
+        }
+      }
+
+      S.Diag(D->getLocation(), diag::note_access_natural)
+        << (unsigned) (Access == AS_protected)
+        << Implicit;
+      return;
+    }
+
+    case AR_accessible: break;
+
+    case AR_dependent:
+      llvm_unreachable("can't diagnose dependent access failures");
+    }
+  }
+
+  CXXBasePaths Paths;
+  CXXBasePath &Path = *FindBestPath(S, EC, Entity, AS_public, Paths);
+
+  CXXBasePath::iterator I = Path.end(), E = Path.begin();
+  while (I != E) {
+    --I;
+
+    const CXXBaseSpecifier *BS = I->Base;
+    AccessSpecifier BaseAccess = BS->getAccessSpecifier();
+
+    // If this is public inheritance, or the derived class is a friend,
+    // skip this step.
+    if (BaseAccess == AS_public)
+      continue;
+
+    switch (GetFriendKind(S, EC, I->Class)) {
+    case AR_accessible: continue;
+    case AR_inaccessible: break;
+    case AR_dependent:
+      llvm_unreachable("can't diagnose dependent access failures");
+    }
+
+    // Check whether this base specifier is the tighest point
+    // constraining access.  We have to check against AS_private for
+    // the same reasons as above.
+    if (BaseAccess == AS_private || BaseAccess >= Access) {
+
+      // We're constrained by inheritance, but we want to say
+      // "declared private here" if we're diagnosing a hierarchy
+      // conversion and this is the final step.
+      unsigned diagnostic;
+      if (D) diagnostic = diag::note_access_constrained_by_path;
+      else if (I + 1 == Path.end()) diagnostic = diag::note_access_natural;
+      else diagnostic = diag::note_access_constrained_by_path;
+
+      S.Diag(BS->getSourceRange().getBegin(), diagnostic)
+        << BS->getSourceRange()
+        << (BaseAccess == AS_protected)
+        << (BS->getAccessSpecifierAsWritten() == AS_none);
+      
+      if (D)
+        S.Diag(D->getLocation(), diag::note_field_decl);
+      
+      return;
+    }
+  }
+
+  llvm_unreachable("access not apparently constrained by path");
+}
+
+static void DiagnoseBadAccess(Sema &S, SourceLocation Loc,
+                              const EffectiveContext &EC,
+                              AccessTarget &Entity) {
+  const CXXRecordDecl *NamingClass = Entity.getNamingClass();
+  const CXXRecordDecl *DeclaringClass = Entity.getDeclaringClass();
+  NamedDecl *D = (Entity.isMemberAccess() ? Entity.getTargetDecl() : 0);
+
+  S.Diag(Loc, Entity.getDiag())
+    << (Entity.getAccess() == AS_protected)
+    << (D ? D->getDeclName() : DeclarationName())
+    << S.Context.getTypeDeclType(NamingClass)
+    << S.Context.getTypeDeclType(DeclaringClass);
+  DiagnoseAccessPath(S, EC, Entity);
+}
+
+/// MSVC has a bug where if during an using declaration name lookup, 
+/// the declaration found is unaccessible (private) and that declaration 
+/// was bring into scope via another using declaration whose target
+/// declaration is accessible (public) then no error is generated.
+/// Example:
+///   class A {
+///   public:
+///     int f();
+///   };
+///   class B : public A {
+///   private:
+///     using A::f;
+///   };
+///   class C : public B {
+///   private:
+///     using B::f;
+///   };
+///
+/// Here, B::f is private so this should fail in Standard C++, but 
+/// because B::f refers to A::f which is public MSVC accepts it.
+static bool IsMicrosoftUsingDeclarationAccessBug(Sema& S, 
+                                                 SourceLocation AccessLoc,
+                                                 AccessTarget &Entity) {
+  if (UsingShadowDecl *Shadow =
+                         dyn_cast<UsingShadowDecl>(Entity.getTargetDecl())) {
+    const NamedDecl *OrigDecl = Entity.getTargetDecl()->getUnderlyingDecl();
+    if (Entity.getTargetDecl()->getAccess() == AS_private && 
+        (OrigDecl->getAccess() == AS_public ||
+         OrigDecl->getAccess() == AS_protected)) {
+      S.Diag(AccessLoc, diag::ext_ms_using_declaration_inaccessible)
+        << Shadow->getUsingDecl()->getQualifiedNameAsString()
+        << OrigDecl->getQualifiedNameAsString();
+      return true;
+    }
+  }
+  return false;
+}
+
+/// Determines whether the accessed entity is accessible.  Public members
+/// have been weeded out by this point.
+static AccessResult IsAccessible(Sema &S,
+                                 const EffectiveContext &EC,
+                                 AccessTarget &Entity) {
+  // Determine the actual naming class.
+  CXXRecordDecl *NamingClass = Entity.getNamingClass();
+  while (NamingClass->isAnonymousStructOrUnion())
+    NamingClass = cast<CXXRecordDecl>(NamingClass->getParent());
+  NamingClass = NamingClass->getCanonicalDecl();
+
+  AccessSpecifier UnprivilegedAccess = Entity.getAccess();
+  assert(UnprivilegedAccess != AS_public && "public access not weeded out");
+
+  // Before we try to recalculate access paths, try to white-list
+  // accesses which just trade in on the final step, i.e. accesses
+  // which don't require [M4] or [B4]. These are by far the most
+  // common forms of privileged access.
+  if (UnprivilegedAccess != AS_none) {
+    switch (HasAccess(S, EC, NamingClass, UnprivilegedAccess, Entity)) {
+    case AR_dependent:
+      // This is actually an interesting policy decision.  We don't
+      // *have* to delay immediately here: we can do the full access
+      // calculation in the hope that friendship on some intermediate
+      // class will make the declaration accessible non-dependently.
+      // But that's not cheap, and odds are very good (note: assertion
+      // made without data) that the friend declaration will determine
+      // access.
+      return AR_dependent;
+
+    case AR_accessible: return AR_accessible;
+    case AR_inaccessible: break;
+    }
+  }
+
+  AccessTarget::SavedInstanceContext _ = Entity.saveInstanceContext();
+
+  // We lower member accesses to base accesses by pretending that the
+  // member is a base class of its declaring class.
+  AccessSpecifier FinalAccess;
+
+  if (Entity.isMemberAccess()) {
+    // Determine if the declaration is accessible from EC when named
+    // in its declaring class.
+    NamedDecl *Target = Entity.getTargetDecl();
+    const CXXRecordDecl *DeclaringClass = Entity.getDeclaringClass();
+
+    FinalAccess = Target->getAccess();
+    switch (HasAccess(S, EC, DeclaringClass, FinalAccess, Entity)) {
+    case AR_accessible:
+      FinalAccess = AS_public;
+      break;
+    case AR_inaccessible: break;
+    case AR_dependent: return AR_dependent; // see above
+    }
+
+    if (DeclaringClass == NamingClass)
+      return (FinalAccess == AS_public ? AR_accessible : AR_inaccessible);
+
+    Entity.suppressInstanceContext();
+  } else {
+    FinalAccess = AS_public;
+  }
+
+  assert(Entity.getDeclaringClass() != NamingClass);
+
+  // Append the declaration's access if applicable.
+  CXXBasePaths Paths;
+  CXXBasePath *Path = FindBestPath(S, EC, Entity, FinalAccess, Paths);
+  if (!Path)
+    return AR_dependent;
+
+  assert(Path->Access <= UnprivilegedAccess &&
+         "access along best path worse than direct?");
+  if (Path->Access == AS_public)
+    return AR_accessible;
+  return AR_inaccessible;
+}
+
+static void DelayDependentAccess(Sema &S,
+                                 const EffectiveContext &EC,
+                                 SourceLocation Loc,
+                                 const AccessTarget &Entity) {
+  assert(EC.isDependent() && "delaying non-dependent access");
+  DeclContext *DC = EC.getInnerContext();
+  assert(DC->isDependentContext() && "delaying non-dependent access");
+  DependentDiagnostic::Create(S.Context, DC, DependentDiagnostic::Access,
+                              Loc,
+                              Entity.isMemberAccess(),
+                              Entity.getAccess(),
+                              Entity.getTargetDecl(),
+                              Entity.getNamingClass(),
+                              Entity.getBaseObjectType(),
+                              Entity.getDiag());
+}
+
+/// Checks access to an entity from the given effective context.
+static AccessResult CheckEffectiveAccess(Sema &S,
+                                         const EffectiveContext &EC,
+                                         SourceLocation Loc,
+                                         AccessTarget &Entity) {
+  assert(Entity.getAccess() != AS_public && "called for public access!");
+
+  if (S.getLangOpts().MicrosoftMode &&
+      IsMicrosoftUsingDeclarationAccessBug(S, Loc, Entity))
+    return AR_accessible;
+
+  switch (IsAccessible(S, EC, Entity)) {
+  case AR_dependent:
+    DelayDependentAccess(S, EC, Loc, Entity);
+    return AR_dependent;
+
+  case AR_inaccessible:
+    if (!Entity.isQuiet())
+      DiagnoseBadAccess(S, Loc, EC, Entity);
+    return AR_inaccessible;
+
+  case AR_accessible:
+    return AR_accessible;
+  }
+
+  // silence unnecessary warning
+  llvm_unreachable("invalid access result");
+}
+
+static Sema::AccessResult CheckAccess(Sema &S, SourceLocation Loc,
+                                      AccessTarget &Entity) {
+  // If the access path is public, it's accessible everywhere.
+  if (Entity.getAccess() == AS_public)
+    return Sema::AR_accessible;
+
+  if (S.SuppressAccessChecking)
+    return Sema::AR_accessible;
+
+  // If we're currently parsing a declaration, we may need to delay
+  // access control checking, because our effective context might be
+  // different based on what the declaration comes out as.
+  //
+  // For example, we might be parsing a declaration with a scope
+  // specifier, like this:
+  //   A::private_type A::foo() { ... }
+  //
+  // Or we might be parsing something that will turn out to be a friend:
+  //   void foo(A::private_type);
+  //   void B::foo(A::private_type);
+  if (S.DelayedDiagnostics.shouldDelayDiagnostics()) {
+    S.DelayedDiagnostics.add(DelayedDiagnostic::makeAccess(Loc, Entity));
+    return Sema::AR_delayed;
+  }
+
+  EffectiveContext EC(S.CurContext);
+  switch (CheckEffectiveAccess(S, EC, Loc, Entity)) {
+  case AR_accessible: return Sema::AR_accessible;
+  case AR_inaccessible: return Sema::AR_inaccessible;
+  case AR_dependent: return Sema::AR_dependent;
+  }
+  llvm_unreachable("falling off end");
+}
+
+void Sema::HandleDelayedAccessCheck(DelayedDiagnostic &DD, Decl *decl) {
+  // Access control for names used in the declarations of functions
+  // and function templates should normally be evaluated in the context
+  // of the declaration, just in case it's a friend of something.
+  // However, this does not apply to local extern declarations.
+
+  DeclContext *DC = decl->getDeclContext();
+  if (FunctionDecl *fn = dyn_cast<FunctionDecl>(decl)) {
+    if (!DC->isFunctionOrMethod()) DC = fn;
+  } else if (FunctionTemplateDecl *fnt = dyn_cast<FunctionTemplateDecl>(decl)) {
+    // Never a local declaration.
+    DC = fnt->getTemplatedDecl();
+  }
+
+  EffectiveContext EC(DC);
+
+  AccessTarget Target(DD.getAccessData());
+
+  if (CheckEffectiveAccess(*this, EC, DD.Loc, Target) == ::AR_inaccessible)
+    DD.Triggered = true;
+}
+
+void Sema::HandleDependentAccessCheck(const DependentDiagnostic &DD,
+                        const MultiLevelTemplateArgumentList &TemplateArgs) {
+  SourceLocation Loc = DD.getAccessLoc();
+  AccessSpecifier Access = DD.getAccess();
+
+  Decl *NamingD = FindInstantiatedDecl(Loc, DD.getAccessNamingClass(),
+                                       TemplateArgs);
+  if (!NamingD) return;
+  Decl *TargetD = FindInstantiatedDecl(Loc, DD.getAccessTarget(),
+                                       TemplateArgs);
+  if (!TargetD) return;
+
+  if (DD.isAccessToMember()) {
+    CXXRecordDecl *NamingClass = cast<CXXRecordDecl>(NamingD);
+    NamedDecl *TargetDecl = cast<NamedDecl>(TargetD);
+    QualType BaseObjectType = DD.getAccessBaseObjectType();
+    if (!BaseObjectType.isNull()) {
+      BaseObjectType = SubstType(BaseObjectType, TemplateArgs, Loc,
+                                 DeclarationName());
+      if (BaseObjectType.isNull()) return;
+    }
+
+    AccessTarget Entity(Context,
+                        AccessTarget::Member,
+                        NamingClass,
+                        DeclAccessPair::make(TargetDecl, Access),
+                        BaseObjectType);
+    Entity.setDiag(DD.getDiagnostic());
+    CheckAccess(*this, Loc, Entity);
+  } else {
+    AccessTarget Entity(Context,
+                        AccessTarget::Base,
+                        cast<CXXRecordDecl>(TargetD),
+                        cast<CXXRecordDecl>(NamingD),
+                        Access);
+    Entity.setDiag(DD.getDiagnostic());
+    CheckAccess(*this, Loc, Entity);
+  }
+}
+
+Sema::AccessResult Sema::CheckUnresolvedLookupAccess(UnresolvedLookupExpr *E,
+                                                     DeclAccessPair Found) {
+  if (!getLangOpts().AccessControl ||
+      !E->getNamingClass() ||
+      Found.getAccess() == AS_public)
+    return AR_accessible;
+
+  AccessTarget Entity(Context, AccessTarget::Member, E->getNamingClass(), 
+                      Found, QualType());
+  Entity.setDiag(diag::err_access) << E->getSourceRange();
+
+  return CheckAccess(*this, E->getNameLoc(), Entity);
+}
+
+/// Perform access-control checking on a previously-unresolved member
+/// access which has now been resolved to a member.
+Sema::AccessResult Sema::CheckUnresolvedMemberAccess(UnresolvedMemberExpr *E,
+                                                     DeclAccessPair Found) {
+  if (!getLangOpts().AccessControl ||
+      Found.getAccess() == AS_public)
+    return AR_accessible;
+
+  QualType BaseType = E->getBaseType();
+  if (E->isArrow())
+    BaseType = BaseType->getAs<PointerType>()->getPointeeType();
+
+  AccessTarget Entity(Context, AccessTarget::Member, E->getNamingClass(),
+                      Found, BaseType);
+  Entity.setDiag(diag::err_access) << E->getSourceRange();
+
+  return CheckAccess(*this, E->getMemberLoc(), Entity);
+}
+
+/// Is the given special member function accessible for the purposes of
+/// deciding whether to define a special member function as deleted?
+bool Sema::isSpecialMemberAccessibleForDeletion(CXXMethodDecl *decl,
+                                                AccessSpecifier access,
+                                                QualType objectType) {
+  // Fast path.
+  if (access == AS_public || !getLangOpts().AccessControl) return true;
+
+  AccessTarget entity(Context, AccessTarget::Member, decl->getParent(),
+                      DeclAccessPair::make(decl, access), objectType);
+
+  // Suppress diagnostics.
+  entity.setDiag(PDiag());
+
+  switch (CheckAccess(*this, SourceLocation(), entity)) {
+  case AR_accessible: return true;
+  case AR_inaccessible: return false;
+  case AR_dependent: llvm_unreachable("dependent for =delete computation");
+  case AR_delayed: llvm_unreachable("cannot delay =delete computation");
+  }
+  llvm_unreachable("bad access result");
+}
+
+Sema::AccessResult Sema::CheckDestructorAccess(SourceLocation Loc,
+                                               CXXDestructorDecl *Dtor,
+                                               const PartialDiagnostic &PDiag,
+                                               QualType ObjectTy) {
+  if (!getLangOpts().AccessControl)
+    return AR_accessible;
+
+  // There's never a path involved when checking implicit destructor access.
+  AccessSpecifier Access = Dtor->getAccess();
+  if (Access == AS_public)
+    return AR_accessible;
+
+  CXXRecordDecl *NamingClass = Dtor->getParent();
+  if (ObjectTy.isNull()) ObjectTy = Context.getTypeDeclType(NamingClass);
+
+  AccessTarget Entity(Context, AccessTarget::Member, NamingClass,
+                      DeclAccessPair::make(Dtor, Access),
+                      ObjectTy);
+  Entity.setDiag(PDiag); // TODO: avoid copy
+
+  return CheckAccess(*this, Loc, Entity);
+}
+
+/// Checks access to a constructor.
+Sema::AccessResult Sema::CheckConstructorAccess(SourceLocation UseLoc,
+                                                CXXConstructorDecl *Constructor,
+                                                const InitializedEntity &Entity,
+                                                AccessSpecifier Access,
+                                                bool IsCopyBindingRefToTemp) {
+  if (!getLangOpts().AccessControl || Access == AS_public)
+    return AR_accessible;
+
+  PartialDiagnostic PD(PDiag());
+  switch (Entity.getKind()) {
+  default:
+    PD = PDiag(IsCopyBindingRefToTemp
+                 ? diag::ext_rvalue_to_reference_access_ctor
+                 : diag::err_access_ctor);
+
+    break;
+
+  case InitializedEntity::EK_Base:
+    PD = PDiag(diag::err_access_base_ctor);
+    PD << Entity.isInheritedVirtualBase()
+       << Entity.getBaseSpecifier()->getType() << getSpecialMember(Constructor);
+    break;
+
+  case InitializedEntity::EK_Member: {
+    const FieldDecl *Field = cast<FieldDecl>(Entity.getDecl());
+    PD = PDiag(diag::err_access_field_ctor);
+    PD << Field->getType() << getSpecialMember(Constructor);
+    break;
+  }
+
+  case InitializedEntity::EK_LambdaCapture: {
+    const VarDecl *Var = Entity.getCapturedVar();
+    PD = PDiag(diag::err_access_lambda_capture);
+    PD << Var->getName() << Entity.getType() << getSpecialMember(Constructor);
+    break;
+  }
+
+  }
+
+  return CheckConstructorAccess(UseLoc, Constructor, Entity, Access, PD);
+}
+
+/// Checks access to a constructor.
+Sema::AccessResult Sema::CheckConstructorAccess(SourceLocation UseLoc,
+                                                CXXConstructorDecl *Constructor,
+                                                const InitializedEntity &Entity,
+                                                AccessSpecifier Access,
+                                                const PartialDiagnostic &PD) {
+  if (!getLangOpts().AccessControl ||
+      Access == AS_public)
+    return AR_accessible;
+
+  CXXRecordDecl *NamingClass = Constructor->getParent();
+
+  // Initializing a base sub-object is an instance method call on an
+  // object of the derived class.  Otherwise, we have an instance method
+  // call on an object of the constructed type.
+  CXXRecordDecl *ObjectClass;
+  if (Entity.getKind() == InitializedEntity::EK_Base) {
+    ObjectClass = cast<CXXConstructorDecl>(CurContext)->getParent();
+  } else {
+    ObjectClass = NamingClass;
+  }
+
+  AccessTarget AccessEntity(Context, AccessTarget::Member, NamingClass,
+                            DeclAccessPair::make(Constructor, Access),
+                            Context.getTypeDeclType(ObjectClass));
+  AccessEntity.setDiag(PD);
+
+  return CheckAccess(*this, UseLoc, AccessEntity);
+} 
+
+/// Checks direct (i.e. non-inherited) access to an arbitrary class
+/// member.
+Sema::AccessResult Sema::CheckDirectMemberAccess(SourceLocation UseLoc,
+                                                 NamedDecl *Target,
+                                           const PartialDiagnostic &Diag) {
+  AccessSpecifier Access = Target->getAccess();
+  if (!getLangOpts().AccessControl ||
+      Access == AS_public)
+    return AR_accessible;
+
+  CXXRecordDecl *NamingClass = cast<CXXRecordDecl>(Target->getDeclContext());
+  AccessTarget Entity(Context, AccessTarget::Member, NamingClass,
+                      DeclAccessPair::make(Target, Access),
+                      QualType());
+  Entity.setDiag(Diag);
+  return CheckAccess(*this, UseLoc, Entity);
+}
+                                           
+
+/// Checks access to an overloaded operator new or delete.
+Sema::AccessResult Sema::CheckAllocationAccess(SourceLocation OpLoc,
+                                               SourceRange PlacementRange,
+                                               CXXRecordDecl *NamingClass,
+                                               DeclAccessPair Found,
+                                               bool Diagnose) {
+  if (!getLangOpts().AccessControl ||
+      !NamingClass ||
+      Found.getAccess() == AS_public)
+    return AR_accessible;
+
+  AccessTarget Entity(Context, AccessTarget::Member, NamingClass, Found,
+                      QualType());
+  if (Diagnose)
+    Entity.setDiag(diag::err_access)
+      << PlacementRange;
+
+  return CheckAccess(*this, OpLoc, Entity);
+}
+
+/// Checks access to an overloaded member operator, including
+/// conversion operators.
+Sema::AccessResult Sema::CheckMemberOperatorAccess(SourceLocation OpLoc,
+                                                   Expr *ObjectExpr,
+                                                   Expr *ArgExpr,
+                                                   DeclAccessPair Found) {
+  if (!getLangOpts().AccessControl ||
+      Found.getAccess() == AS_public)
+    return AR_accessible;
+
+  const RecordType *RT = ObjectExpr->getType()->castAs<RecordType>();
+  CXXRecordDecl *NamingClass = cast<CXXRecordDecl>(RT->getDecl());
+
+  AccessTarget Entity(Context, AccessTarget::Member, NamingClass, Found,
+                      ObjectExpr->getType());
+  Entity.setDiag(diag::err_access)
+    << ObjectExpr->getSourceRange()
+    << (ArgExpr ? ArgExpr->getSourceRange() : SourceRange());
+
+  return CheckAccess(*this, OpLoc, Entity);
+}
+
+Sema::AccessResult Sema::CheckAddressOfMemberAccess(Expr *OvlExpr,
+                                                    DeclAccessPair Found) {
+  if (!getLangOpts().AccessControl ||
+      Found.getAccess() == AS_none ||
+      Found.getAccess() == AS_public)
+    return AR_accessible;
+
+  OverloadExpr *Ovl = OverloadExpr::find(OvlExpr).Expression;
+  CXXRecordDecl *NamingClass = Ovl->getNamingClass();
+
+  AccessTarget Entity(Context, AccessTarget::Member, NamingClass, Found,
+                      /*no instance context*/ QualType());
+  Entity.setDiag(diag::err_access)
+    << Ovl->getSourceRange();
+
+  return CheckAccess(*this, Ovl->getNameLoc(), Entity);
+}
+
+/// Checks access for a hierarchy conversion.
+///
+/// \param IsBaseToDerived whether this is a base-to-derived conversion (true)
+///     or a derived-to-base conversion (false)
+/// \param ForceCheck true if this check should be performed even if access
+///     control is disabled;  some things rely on this for semantics
+/// \param ForceUnprivileged true if this check should proceed as if the
+///     context had no special privileges
+/// \param ADK controls the kind of diagnostics that are used
+Sema::AccessResult Sema::CheckBaseClassAccess(SourceLocation AccessLoc,
+                                              QualType Base,
+                                              QualType Derived,
+                                              const CXXBasePath &Path,
+                                              unsigned DiagID,
+                                              bool ForceCheck,
+                                              bool ForceUnprivileged) {
+  if (!ForceCheck && !getLangOpts().AccessControl)
+    return AR_accessible;
+
+  if (Path.Access == AS_public)
+    return AR_accessible;
+
+  CXXRecordDecl *BaseD, *DerivedD;
+  BaseD = cast<CXXRecordDecl>(Base->getAs<RecordType>()->getDecl());
+  DerivedD = cast<CXXRecordDecl>(Derived->getAs<RecordType>()->getDecl());
+
+  AccessTarget Entity(Context, AccessTarget::Base, BaseD, DerivedD, 
+                      Path.Access);
+  if (DiagID)
+    Entity.setDiag(DiagID) << Derived << Base;
+
+  if (ForceUnprivileged) {
+    switch (CheckEffectiveAccess(*this, EffectiveContext(),
+                                 AccessLoc, Entity)) {
+    case ::AR_accessible: return Sema::AR_accessible;
+    case ::AR_inaccessible: return Sema::AR_inaccessible;
+    case ::AR_dependent: return Sema::AR_dependent;
+    }
+    llvm_unreachable("unexpected result from CheckEffectiveAccess");
+  }
+  return CheckAccess(*this, AccessLoc, Entity);
+}
+
+/// Checks access to all the declarations in the given result set.
+void Sema::CheckLookupAccess(const LookupResult &R) {
+  assert(getLangOpts().AccessControl
+         && "performing access check without access control");
+  assert(R.getNamingClass() && "performing access check without naming class");
+
+  for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I) {
+    if (I.getAccess() != AS_public) {
+      AccessTarget Entity(Context, AccessedEntity::Member,
+                          R.getNamingClass(), I.getPair(),
+                          R.getBaseObjectType());
+      Entity.setDiag(diag::err_access);
+      CheckAccess(*this, R.getNameLoc(), Entity);
+    }
+  }
+}
+
+/// Checks access to Decl from the given class. The check will take access
+/// specifiers into account, but no member access expressions and such.
+///
+/// \param Decl the declaration to check if it can be accessed
+/// \param Class the class/context from which to start the search
+/// \return true if the Decl is accessible from the Class, false otherwise.
+bool Sema::IsSimplyAccessible(NamedDecl *Decl, DeclContext *Ctx) {
+  if (CXXRecordDecl *Class = dyn_cast<CXXRecordDecl>(Ctx)) {
+    if (!Decl->isCXXClassMember())
+      return true;
+
+    QualType qType = Class->getTypeForDecl()->getCanonicalTypeInternal();
+    AccessTarget Entity(Context, AccessedEntity::Member, Class,
+                        DeclAccessPair::make(Decl, Decl->getAccess()),
+                        qType);
+    if (Entity.getAccess() == AS_public)
+      return true;
+
+    EffectiveContext EC(CurContext);
+    return ::IsAccessible(*this, EC, Entity) != ::AR_inaccessible;
+  }
+  
+  if (ObjCIvarDecl *Ivar = dyn_cast<ObjCIvarDecl>(Decl)) {
+    // @public and @package ivars are always accessible.
+    if (Ivar->getCanonicalAccessControl() == ObjCIvarDecl::Public ||
+        Ivar->getCanonicalAccessControl() == ObjCIvarDecl::Package)
+      return true;
+    
+    
+    
+    // If we are inside a class or category implementation, determine the
+    // interface we're in.
+    ObjCInterfaceDecl *ClassOfMethodDecl = 0;
+    if (ObjCMethodDecl *MD = getCurMethodDecl())
+      ClassOfMethodDecl =  MD->getClassInterface();
+    else if (FunctionDecl *FD = getCurFunctionDecl()) {
+      if (ObjCImplDecl *Impl 
+            = dyn_cast<ObjCImplDecl>(FD->getLexicalDeclContext())) {
+        if (ObjCImplementationDecl *IMPD
+              = dyn_cast<ObjCImplementationDecl>(Impl))
+          ClassOfMethodDecl = IMPD->getClassInterface();
+        else if (ObjCCategoryImplDecl* CatImplClass
+                   = dyn_cast<ObjCCategoryImplDecl>(Impl))
+          ClassOfMethodDecl = CatImplClass->getClassInterface();
+      }
+    }
+    
+    // If we're not in an interface, this ivar is inaccessible.
+    if (!ClassOfMethodDecl)
+      return false;
+    
+    // If we're inside the same interface that owns the ivar, we're fine.
+    if (declaresSameEntity(ClassOfMethodDecl, Ivar->getContainingInterface()))
+      return true;
+    
+    // If the ivar is private, it's inaccessible.
+    if (Ivar->getCanonicalAccessControl() == ObjCIvarDecl::Private)
+      return false;
+    
+    return Ivar->getContainingInterface()->isSuperClassOf(ClassOfMethodDecl);
+  }
+  
+  return true;
+}
+
+void Sema::ActOnStartSuppressingAccessChecks() {
+  assert(!SuppressAccessChecking &&
+         "Tried to start access check suppression when already started.");
+  SuppressAccessChecking = true;
+}
+
+void Sema::ActOnStopSuppressingAccessChecks() {
+  assert(SuppressAccessChecking &&
+         "Tried to stop access check suprression when already stopped.");
+  SuppressAccessChecking = false;
+}
diff --git a/clang/lib/Sema/SemaAttr.cpp b/clang/lib/Sema/SemaAttr.cpp
new file mode 100644
index 0000000..e935fc7
--- /dev/null
+++ b/clang/lib/Sema/SemaAttr.cpp
@@ -0,0 +1,426 @@
+//===--- SemaAttr.cpp - Semantic Analysis for Attributes ------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements semantic analysis for non-trivial attributes and
+// pragmas.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Sema/SemaInternal.h"
+#include "clang/Sema/Lookup.h"
+#include "clang/AST/Attr.h"
+#include "clang/AST/Expr.h"
+#include "clang/Basic/TargetInfo.h"
+#include "clang/Lex/Preprocessor.h"
+using namespace clang;
+
+//===----------------------------------------------------------------------===//
+// Pragma 'pack' and 'options align'
+//===----------------------------------------------------------------------===//
+
+namespace {
+  struct PackStackEntry {
+    // We just use a sentinel to represent when the stack is set to mac68k
+    // alignment.
+    static const unsigned kMac68kAlignmentSentinel = ~0U;
+
+    unsigned Alignment;
+    IdentifierInfo *Name;
+  };
+
+  /// PragmaPackStack - Simple class to wrap the stack used by #pragma
+  /// pack.
+  class PragmaPackStack {
+    typedef std::vector<PackStackEntry> stack_ty;
+
+    /// Alignment - The current user specified alignment.
+    unsigned Alignment;
+
+    /// Stack - Entries in the #pragma pack stack, consisting of saved
+    /// alignments and optional names.
+    stack_ty Stack;
+
+  public:
+    PragmaPackStack() : Alignment(0) {}
+
+    void setAlignment(unsigned A) { Alignment = A; }
+    unsigned getAlignment() { return Alignment; }
+
+    /// push - Push the current alignment onto the stack, optionally
+    /// using the given \arg Name for the record, if non-zero.
+    void push(IdentifierInfo *Name) {
+      PackStackEntry PSE = { Alignment, Name };
+      Stack.push_back(PSE);
+    }
+
+    /// pop - Pop a record from the stack and restore the current
+    /// alignment to the previous value. If \arg Name is non-zero then
+    /// the first such named record is popped, otherwise the top record
+    /// is popped. Returns true if the pop succeeded.
+    bool pop(IdentifierInfo *Name, bool IsReset);
+  };
+}  // end anonymous namespace.
+
+bool PragmaPackStack::pop(IdentifierInfo *Name, bool IsReset) {
+  // If name is empty just pop top.
+  if (!Name) {
+    // An empty stack is a special case...
+    if (Stack.empty()) {
+      // If this isn't a reset, it is always an error.
+      if (!IsReset)
+        return false;
+
+      // Otherwise, it is an error only if some alignment has been set.
+      if (!Alignment)
+        return false;
+
+      // Otherwise, reset to the default alignment.
+      Alignment = 0;
+    } else {
+      Alignment = Stack.back().Alignment;
+      Stack.pop_back();
+    }
+
+    return true;
+  }
+
+  // Otherwise, find the named record.
+  for (unsigned i = Stack.size(); i != 0; ) {
+    --i;
+    if (Stack[i].Name == Name) {
+      // Found it, pop up to and including this record.
+      Alignment = Stack[i].Alignment;
+      Stack.erase(Stack.begin() + i, Stack.end());
+      return true;
+    }
+  }
+
+  return false;
+}
+
+
+/// FreePackedContext - Deallocate and null out PackContext.
+void Sema::FreePackedContext() {
+  delete static_cast<PragmaPackStack*>(PackContext);
+  PackContext = 0;
+}
+
+void Sema::AddAlignmentAttributesForRecord(RecordDecl *RD) {
+  // If there is no pack context, we don't need any attributes.
+  if (!PackContext)
+    return;
+
+  PragmaPackStack *Stack = static_cast<PragmaPackStack*>(PackContext);
+
+  // Otherwise, check to see if we need a max field alignment attribute.
+  if (unsigned Alignment = Stack->getAlignment()) {
+    if (Alignment == PackStackEntry::kMac68kAlignmentSentinel)
+      RD->addAttr(::new (Context) AlignMac68kAttr(SourceLocation(), Context));
+    else
+      RD->addAttr(::new (Context) MaxFieldAlignmentAttr(SourceLocation(),
+                                                        Context,
+                                                        Alignment * 8));
+  }
+}
+
+void Sema::AddMsStructLayoutForRecord(RecordDecl *RD) {
+  if (!MSStructPragmaOn)
+    return;
+  RD->addAttr(::new (Context) MsStructAttr(SourceLocation(), Context));
+}
+
+void Sema::ActOnPragmaOptionsAlign(PragmaOptionsAlignKind Kind,
+                                   SourceLocation PragmaLoc,
+                                   SourceLocation KindLoc) {
+  if (PackContext == 0)
+    PackContext = new PragmaPackStack();
+
+  PragmaPackStack *Context = static_cast<PragmaPackStack*>(PackContext);
+
+  // Reset just pops the top of the stack, or resets the current alignment to
+  // default.
+  if (Kind == Sema::POAK_Reset) {
+    if (!Context->pop(0, /*IsReset=*/true)) {
+      Diag(PragmaLoc, diag::warn_pragma_options_align_reset_failed)
+        << "stack empty";
+    }
+    return;
+  }
+
+  switch (Kind) {
+    // For all targets we support native and natural are the same.
+    //
+    // FIXME: This is not true on Darwin/PPC.
+  case POAK_Native:
+  case POAK_Power:
+  case POAK_Natural:
+    Context->push(0);
+    Context->setAlignment(0);
+    break;
+
+    // Note that '#pragma options align=packed' is not equivalent to attribute
+    // packed, it has a different precedence relative to attribute aligned.
+  case POAK_Packed:
+    Context->push(0);
+    Context->setAlignment(1);
+    break;
+
+  case POAK_Mac68k:
+    // Check if the target supports this.
+    if (!PP.getTargetInfo().hasAlignMac68kSupport()) {
+      Diag(PragmaLoc, diag::err_pragma_options_align_mac68k_target_unsupported);
+      return;
+    }
+    Context->push(0);
+    Context->setAlignment(PackStackEntry::kMac68kAlignmentSentinel);
+    break;
+
+  default:
+    Diag(PragmaLoc, diag::warn_pragma_options_align_unsupported_option)
+      << KindLoc;
+    break;
+  }
+}
+
+void Sema::ActOnPragmaPack(PragmaPackKind Kind, IdentifierInfo *Name,
+                           Expr *alignment, SourceLocation PragmaLoc,
+                           SourceLocation LParenLoc, SourceLocation RParenLoc) {
+  Expr *Alignment = static_cast<Expr *>(alignment);
+
+  // If specified then alignment must be a "small" power of two.
+  unsigned AlignmentVal = 0;
+  if (Alignment) {
+    llvm::APSInt Val;
+
+    // pack(0) is like pack(), which just works out since that is what
+    // we use 0 for in PackAttr.
+    if (Alignment->isTypeDependent() ||
+        Alignment->isValueDependent() ||
+        !Alignment->isIntegerConstantExpr(Val, Context) ||
+        !(Val == 0 || Val.isPowerOf2()) ||
+        Val.getZExtValue() > 16) {
+      Diag(PragmaLoc, diag::warn_pragma_pack_invalid_alignment);
+      return; // Ignore
+    }
+
+    AlignmentVal = (unsigned) Val.getZExtValue();
+  }
+
+  if (PackContext == 0)
+    PackContext = new PragmaPackStack();
+
+  PragmaPackStack *Context = static_cast<PragmaPackStack*>(PackContext);
+
+  switch (Kind) {
+  case Sema::PPK_Default: // pack([n])
+    Context->setAlignment(AlignmentVal);
+    break;
+
+  case Sema::PPK_Show: // pack(show)
+    // Show the current alignment, making sure to show the right value
+    // for the default.
+    AlignmentVal = Context->getAlignment();
+    // FIXME: This should come from the target.
+    if (AlignmentVal == 0)
+      AlignmentVal = 8;
+    if (AlignmentVal == PackStackEntry::kMac68kAlignmentSentinel)
+      Diag(PragmaLoc, diag::warn_pragma_pack_show) << "mac68k";
+    else
+      Diag(PragmaLoc, diag::warn_pragma_pack_show) << AlignmentVal;
+    break;
+
+  case Sema::PPK_Push: // pack(push [, id] [, [n])
+    Context->push(Name);
+    // Set the new alignment if specified.
+    if (Alignment)
+      Context->setAlignment(AlignmentVal);
+    break;
+
+  case Sema::PPK_Pop: // pack(pop [, id] [,  n])
+    // MSDN, C/C++ Preprocessor Reference > Pragma Directives > pack:
+    // "#pragma pack(pop, identifier, n) is undefined"
+    if (Alignment && Name)
+      Diag(PragmaLoc, diag::warn_pragma_pack_pop_identifer_and_alignment);
+
+    // Do the pop.
+    if (!Context->pop(Name, /*IsReset=*/false)) {
+      // If a name was specified then failure indicates the name
+      // wasn't found. Otherwise failure indicates the stack was
+      // empty.
+      Diag(PragmaLoc, diag::warn_pragma_pack_pop_failed)
+        << (Name ? "no record matching name" : "stack empty");
+
+      // FIXME: Warn about popping named records as MSVC does.
+    } else {
+      // Pop succeeded, set the new alignment if specified.
+      if (Alignment)
+        Context->setAlignment(AlignmentVal);
+    }
+    break;
+  }
+}
+
+void Sema::ActOnPragmaMSStruct(PragmaMSStructKind Kind) { 
+  MSStructPragmaOn = (Kind == PMSST_ON);
+}
+
+void Sema::ActOnPragmaUnused(const Token &IdTok, Scope *curScope,
+                             SourceLocation PragmaLoc) {
+
+  IdentifierInfo *Name = IdTok.getIdentifierInfo();
+  LookupResult Lookup(*this, Name, IdTok.getLocation(), LookupOrdinaryName);
+  LookupParsedName(Lookup, curScope, NULL, true);
+
+  if (Lookup.empty()) {
+    Diag(PragmaLoc, diag::warn_pragma_unused_undeclared_var)
+      << Name << SourceRange(IdTok.getLocation());
+    return;
+  }
+
+  VarDecl *VD = Lookup.getAsSingle<VarDecl>();
+  if (!VD) {
+    Diag(PragmaLoc, diag::warn_pragma_unused_expected_var_arg)
+      << Name << SourceRange(IdTok.getLocation());
+    return;
+  }
+
+  // Warn if this was used before being marked unused.
+  if (VD->isUsed())
+    Diag(PragmaLoc, diag::warn_used_but_marked_unused) << Name;
+
+  VD->addAttr(::new (Context) UnusedAttr(IdTok.getLocation(), Context));
+}
+
+void Sema::AddCFAuditedAttribute(Decl *D) {
+  SourceLocation Loc = PP.getPragmaARCCFCodeAuditedLoc();
+  if (!Loc.isValid()) return;
+
+  // Don't add a redundant or conflicting attribute.
+  if (D->hasAttr<CFAuditedTransferAttr>() ||
+      D->hasAttr<CFUnknownTransferAttr>())
+    return;
+
+  D->addAttr(::new (Context) CFAuditedTransferAttr(Loc, Context));
+}
+
+typedef std::vector<std::pair<unsigned, SourceLocation> > VisStack;
+enum { NoVisibility = (unsigned) -1 };
+
+void Sema::AddPushedVisibilityAttribute(Decl *D) {
+  if (!VisContext)
+    return;
+
+  if (isa<NamedDecl>(D) && cast<NamedDecl>(D)->getExplicitVisibility())
+    return;
+
+  VisStack *Stack = static_cast<VisStack*>(VisContext);
+  unsigned rawType = Stack->back().first;
+  if (rawType == NoVisibility) return;
+
+  VisibilityAttr::VisibilityType type
+    = (VisibilityAttr::VisibilityType) rawType;
+  SourceLocation loc = Stack->back().second;
+
+  D->addAttr(::new (Context) VisibilityAttr(loc, Context, type));
+}
+
+/// FreeVisContext - Deallocate and null out VisContext.
+void Sema::FreeVisContext() {
+  delete static_cast<VisStack*>(VisContext);
+  VisContext = 0;
+}
+
+static void PushPragmaVisibility(Sema &S, unsigned type, SourceLocation loc) {
+  // Put visibility on stack.
+  if (!S.VisContext)
+    S.VisContext = new VisStack;
+
+  VisStack *Stack = static_cast<VisStack*>(S.VisContext);
+  Stack->push_back(std::make_pair(type, loc));
+}
+
+void Sema::ActOnPragmaVisibility(const IdentifierInfo* VisType,
+                                 SourceLocation PragmaLoc) {
+  if (VisType) {
+    // Compute visibility to use.
+    VisibilityAttr::VisibilityType type;
+    if (VisType->isStr("default"))
+      type = VisibilityAttr::Default;
+    else if (VisType->isStr("hidden"))
+      type = VisibilityAttr::Hidden;
+    else if (VisType->isStr("internal"))
+      type = VisibilityAttr::Hidden; // FIXME
+    else if (VisType->isStr("protected"))
+      type = VisibilityAttr::Protected;
+    else {
+      Diag(PragmaLoc, diag::warn_attribute_unknown_visibility) <<
+        VisType->getName();
+      return;
+    }
+    PushPragmaVisibility(*this, type, PragmaLoc);
+  } else {
+    PopPragmaVisibility(false, PragmaLoc);
+  }
+}
+
+void Sema::ActOnPragmaFPContract(tok::OnOffSwitch OOS) {
+  switch (OOS) {
+  case tok::OOS_ON:
+    FPFeatures.fp_contract = 1;
+    break;
+  case tok::OOS_OFF:
+    FPFeatures.fp_contract = 0; 
+    break;
+  case tok::OOS_DEFAULT:
+    FPFeatures.fp_contract = getLangOpts().DefaultFPContract;
+    break;
+  }
+}
+
+void Sema::PushNamespaceVisibilityAttr(const VisibilityAttr *Attr,
+                                       SourceLocation Loc) {
+  // Visibility calculations will consider the namespace's visibility.
+  // Here we just want to note that we're in a visibility context
+  // which overrides any enclosing #pragma context, but doesn't itself
+  // contribute visibility.
+  PushPragmaVisibility(*this, NoVisibility, Loc);
+}
+
+void Sema::PopPragmaVisibility(bool IsNamespaceEnd, SourceLocation EndLoc) {
+  if (!VisContext) {
+    Diag(EndLoc, diag::err_pragma_pop_visibility_mismatch);
+    return;
+  }
+
+  // Pop visibility from stack
+  VisStack *Stack = static_cast<VisStack*>(VisContext);
+
+  const std::pair<unsigned, SourceLocation> *Back = &Stack->back();
+  bool StartsWithPragma = Back->first != NoVisibility;
+  if (StartsWithPragma && IsNamespaceEnd) {
+    Diag(Back->second, diag::err_pragma_push_visibility_mismatch);
+    Diag(EndLoc, diag::note_surrounding_namespace_ends_here);
+
+    // For better error recovery, eat all pushes inside the namespace.
+    do {
+      Stack->pop_back();
+      Back = &Stack->back();
+      StartsWithPragma = Back->first != NoVisibility;
+    } while (StartsWithPragma);
+  } else if (!StartsWithPragma && !IsNamespaceEnd) {
+    Diag(EndLoc, diag::err_pragma_pop_visibility_mismatch);
+    Diag(Back->second, diag::note_surrounding_namespace_starts_here);
+    return;
+  }
+
+  Stack->pop_back();
+  // To simplify the implementation, never keep around an empty stack.
+  if (Stack->empty())
+    FreeVisContext();
+}
diff --git a/clang/lib/Sema/SemaCXXScopeSpec.cpp b/clang/lib/Sema/SemaCXXScopeSpec.cpp
new file mode 100644
index 0000000..5a0fcec
--- /dev/null
+++ b/clang/lib/Sema/SemaCXXScopeSpec.cpp
@@ -0,0 +1,958 @@
+//===--- SemaCXXScopeSpec.cpp - Semantic Analysis for C++ scope specifiers-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements C++ semantic analysis for scope specifiers.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Sema/SemaInternal.h"
+#include "clang/Sema/Lookup.h"
+#include "clang/Sema/Template.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/DeclTemplate.h"
+#include "clang/AST/ExprCXX.h"
+#include "clang/AST/NestedNameSpecifier.h"
+#include "clang/Basic/PartialDiagnostic.h"
+#include "clang/Sema/DeclSpec.h"
+#include "TypeLocBuilder.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/Support/raw_ostream.h"
+using namespace clang;
+
+/// \brief Find the current instantiation that associated with the given type.
+static CXXRecordDecl *getCurrentInstantiationOf(QualType T, 
+                                                DeclContext *CurContext) {
+  if (T.isNull())
+    return 0;
+
+  const Type *Ty = T->getCanonicalTypeInternal().getTypePtr();
+  if (const RecordType *RecordTy = dyn_cast<RecordType>(Ty)) {
+    CXXRecordDecl *Record = cast<CXXRecordDecl>(RecordTy->getDecl());
+    if (!T->isDependentType())
+      return Record;
+
+    // This may be a member of a class template or class template partial
+    // specialization. If it's part of the current semantic context, then it's
+    // an injected-class-name;
+    for (; !CurContext->isFileContext(); CurContext = CurContext->getParent())
+      if (CurContext->Equals(Record))
+        return Record;
+    
+    return 0;
+  } else if (isa<InjectedClassNameType>(Ty))
+    return cast<InjectedClassNameType>(Ty)->getDecl();
+  else
+    return 0;
+}
+
+/// \brief Compute the DeclContext that is associated with the given type.
+///
+/// \param T the type for which we are attempting to find a DeclContext.
+///
+/// \returns the declaration context represented by the type T,
+/// or NULL if the declaration context cannot be computed (e.g., because it is
+/// dependent and not the current instantiation).
+DeclContext *Sema::computeDeclContext(QualType T) {
+  if (!T->isDependentType())
+    if (const TagType *Tag = T->getAs<TagType>())
+      return Tag->getDecl();
+
+  return ::getCurrentInstantiationOf(T, CurContext);
+}
+
+/// \brief Compute the DeclContext that is associated with the given
+/// scope specifier.
+///
+/// \param SS the C++ scope specifier as it appears in the source
+///
+/// \param EnteringContext when true, we will be entering the context of
+/// this scope specifier, so we can retrieve the declaration context of a
+/// class template or class template partial specialization even if it is
+/// not the current instantiation.
+///
+/// \returns the declaration context represented by the scope specifier @p SS,
+/// or NULL if the declaration context cannot be computed (e.g., because it is
+/// dependent and not the current instantiation).
+DeclContext *Sema::computeDeclContext(const CXXScopeSpec &SS,
+                                      bool EnteringContext) {
+  if (!SS.isSet() || SS.isInvalid())
+    return 0;
+
+  NestedNameSpecifier *NNS
+    = static_cast<NestedNameSpecifier *>(SS.getScopeRep());
+  if (NNS->isDependent()) {
+    // If this nested-name-specifier refers to the current
+    // instantiation, return its DeclContext.
+    if (CXXRecordDecl *Record = getCurrentInstantiationOf(NNS))
+      return Record;
+
+    if (EnteringContext) {
+      const Type *NNSType = NNS->getAsType();
+      if (!NNSType) {
+        return 0;
+      }
+
+      // Look through type alias templates, per C++0x [temp.dep.type]p1.
+      NNSType = Context.getCanonicalType(NNSType);
+      if (const TemplateSpecializationType *SpecType
+            = NNSType->getAs<TemplateSpecializationType>()) {
+        // We are entering the context of the nested name specifier, so try to
+        // match the nested name specifier to either a primary class template
+        // or a class template partial specialization.
+        if (ClassTemplateDecl *ClassTemplate
+              = dyn_cast_or_null<ClassTemplateDecl>(
+                            SpecType->getTemplateName().getAsTemplateDecl())) {
+          QualType ContextType
+            = Context.getCanonicalType(QualType(SpecType, 0));
+
+          // If the type of the nested name specifier is the same as the
+          // injected class name of the named class template, we're entering
+          // into that class template definition.
+          QualType Injected
+            = ClassTemplate->getInjectedClassNameSpecialization();
+          if (Context.hasSameType(Injected, ContextType))
+            return ClassTemplate->getTemplatedDecl();
+
+          // If the type of the nested name specifier is the same as the
+          // type of one of the class template's class template partial
+          // specializations, we're entering into the definition of that
+          // class template partial specialization.
+          if (ClassTemplatePartialSpecializationDecl *PartialSpec
+                = ClassTemplate->findPartialSpecialization(ContextType))
+            return PartialSpec;
+        }
+      } else if (const RecordType *RecordT = NNSType->getAs<RecordType>()) {
+        // The nested name specifier refers to a member of a class template.
+        return RecordT->getDecl();
+      }
+    }
+
+    return 0;
+  }
+
+  switch (NNS->getKind()) {
+  case NestedNameSpecifier::Identifier:
+    llvm_unreachable("Dependent nested-name-specifier has no DeclContext");
+
+  case NestedNameSpecifier::Namespace:
+    return NNS->getAsNamespace();
+
+  case NestedNameSpecifier::NamespaceAlias:
+    return NNS->getAsNamespaceAlias()->getNamespace();
+
+  case NestedNameSpecifier::TypeSpec:
+  case NestedNameSpecifier::TypeSpecWithTemplate: {
+    const TagType *Tag = NNS->getAsType()->getAs<TagType>();
+    assert(Tag && "Non-tag type in nested-name-specifier");
+    return Tag->getDecl();
+  }
+
+  case NestedNameSpecifier::Global:
+    return Context.getTranslationUnitDecl();
+  }
+
+  llvm_unreachable("Invalid NestedNameSpecifier::Kind!");
+}
+
+bool Sema::isDependentScopeSpecifier(const CXXScopeSpec &SS) {
+  if (!SS.isSet() || SS.isInvalid())
+    return false;
+
+  NestedNameSpecifier *NNS
+    = static_cast<NestedNameSpecifier *>(SS.getScopeRep());
+  return NNS->isDependent();
+}
+
+// \brief Determine whether this C++ scope specifier refers to an
+// unknown specialization, i.e., a dependent type that is not the
+// current instantiation.
+bool Sema::isUnknownSpecialization(const CXXScopeSpec &SS) {
+  if (!isDependentScopeSpecifier(SS))
+    return false;
+
+  NestedNameSpecifier *NNS
+    = static_cast<NestedNameSpecifier *>(SS.getScopeRep());
+  return getCurrentInstantiationOf(NNS) == 0;
+}
+
+/// \brief If the given nested name specifier refers to the current
+/// instantiation, return the declaration that corresponds to that
+/// current instantiation (C++0x [temp.dep.type]p1).
+///
+/// \param NNS a dependent nested name specifier.
+CXXRecordDecl *Sema::getCurrentInstantiationOf(NestedNameSpecifier *NNS) {
+  assert(getLangOpts().CPlusPlus && "Only callable in C++");
+  assert(NNS->isDependent() && "Only dependent nested-name-specifier allowed");
+
+  if (!NNS->getAsType())
+    return 0;
+
+  QualType T = QualType(NNS->getAsType(), 0);
+  return ::getCurrentInstantiationOf(T, CurContext);
+}
+
+/// \brief Require that the context specified by SS be complete.
+///
+/// If SS refers to a type, this routine checks whether the type is
+/// complete enough (or can be made complete enough) for name lookup
+/// into the DeclContext. A type that is not yet completed can be
+/// considered "complete enough" if it is a class/struct/union/enum
+/// that is currently being defined. Or, if we have a type that names
+/// a class template specialization that is not a complete type, we
+/// will attempt to instantiate that class template.
+bool Sema::RequireCompleteDeclContext(CXXScopeSpec &SS,
+                                      DeclContext *DC) {
+  assert(DC != 0 && "given null context");
+
+  TagDecl *tag = dyn_cast<TagDecl>(DC);
+
+  // If this is a dependent type, then we consider it complete.
+  if (!tag || tag->isDependentContext())
+    return false;
+
+  // If we're currently defining this type, then lookup into the
+  // type is okay: don't complain that it isn't complete yet.
+  QualType type = Context.getTypeDeclType(tag);
+  const TagType *tagType = type->getAs<TagType>();
+  if (tagType && tagType->isBeingDefined())
+    return false;
+
+  SourceLocation loc = SS.getLastQualifierNameLoc();
+  if (loc.isInvalid()) loc = SS.getRange().getBegin();
+
+  // The type must be complete.
+  if (RequireCompleteType(loc, type,
+                          PDiag(diag::err_incomplete_nested_name_spec)
+                            << SS.getRange())) {
+    SS.SetInvalid(SS.getRange());
+    return true;
+  }
+
+  // Fixed enum types are complete, but they aren't valid as scopes
+  // until we see a definition, so awkwardly pull out this special
+  // case.
+  const EnumType *enumType = dyn_cast_or_null<EnumType>(tagType);
+  if (!enumType || enumType->getDecl()->isCompleteDefinition())
+    return false;
+
+  // Try to instantiate the definition, if this is a specialization of an
+  // enumeration temploid.
+  EnumDecl *ED = enumType->getDecl();
+  if (EnumDecl *Pattern = ED->getInstantiatedFromMemberEnum()) {
+    MemberSpecializationInfo *MSI = ED->getMemberSpecializationInfo();
+    if (MSI->getTemplateSpecializationKind() != TSK_ExplicitSpecialization) {
+      if (InstantiateEnum(loc, ED, Pattern, getTemplateInstantiationArgs(ED),
+                          TSK_ImplicitInstantiation)) {
+        SS.SetInvalid(SS.getRange());
+        return true;
+      }
+      return false;
+    }
+  }
+
+  Diag(loc, diag::err_incomplete_nested_name_spec)
+    << type << SS.getRange();
+  SS.SetInvalid(SS.getRange());
+  return true;
+}
+
+bool Sema::ActOnCXXGlobalScopeSpecifier(Scope *S, SourceLocation CCLoc,
+                                        CXXScopeSpec &SS) {
+  SS.MakeGlobal(Context, CCLoc);
+  return false;
+}
+
+/// \brief Determines whether the given declaration is an valid acceptable
+/// result for name lookup of a nested-name-specifier.
+bool Sema::isAcceptableNestedNameSpecifier(NamedDecl *SD) {
+  if (!SD)
+    return false;
+
+  // Namespace and namespace aliases are fine.
+  if (isa<NamespaceDecl>(SD) || isa<NamespaceAliasDecl>(SD))
+    return true;
+
+  if (!isa<TypeDecl>(SD))
+    return false;
+
+  // Determine whether we have a class (or, in C++11, an enum) or
+  // a typedef thereof. If so, build the nested-name-specifier.
+  QualType T = Context.getTypeDeclType(cast<TypeDecl>(SD));
+  if (T->isDependentType())
+    return true;
+  else if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(SD)) {
+    if (TD->getUnderlyingType()->isRecordType() ||
+        (Context.getLangOpts().CPlusPlus0x &&
+         TD->getUnderlyingType()->isEnumeralType()))
+      return true;
+  } else if (isa<RecordDecl>(SD) ||
+             (Context.getLangOpts().CPlusPlus0x && isa<EnumDecl>(SD)))
+    return true;
+
+  return false;
+}
+
+/// \brief If the given nested-name-specifier begins with a bare identifier
+/// (e.g., Base::), perform name lookup for that identifier as a
+/// nested-name-specifier within the given scope, and return the result of that
+/// name lookup.
+NamedDecl *Sema::FindFirstQualifierInScope(Scope *S, NestedNameSpecifier *NNS) {
+  if (!S || !NNS)
+    return 0;
+
+  while (NNS->getPrefix())
+    NNS = NNS->getPrefix();
+
+  if (NNS->getKind() != NestedNameSpecifier::Identifier)
+    return 0;
+
+  LookupResult Found(*this, NNS->getAsIdentifier(), SourceLocation(),
+                     LookupNestedNameSpecifierName);
+  LookupName(Found, S);
+  assert(!Found.isAmbiguous() && "Cannot handle ambiguities here yet");
+
+  if (!Found.isSingleResult())
+    return 0;
+
+  NamedDecl *Result = Found.getFoundDecl();
+  if (isAcceptableNestedNameSpecifier(Result))
+    return Result;
+
+  return 0;
+}
+
+bool Sema::isNonTypeNestedNameSpecifier(Scope *S, CXXScopeSpec &SS,
+                                        SourceLocation IdLoc,
+                                        IdentifierInfo &II,
+                                        ParsedType ObjectTypePtr) {
+  QualType ObjectType = GetTypeFromParser(ObjectTypePtr);
+  LookupResult Found(*this, &II, IdLoc, LookupNestedNameSpecifierName);
+  
+  // Determine where to perform name lookup
+  DeclContext *LookupCtx = 0;
+  bool isDependent = false;
+  if (!ObjectType.isNull()) {
+    // This nested-name-specifier occurs in a member access expression, e.g.,
+    // x->B::f, and we are looking into the type of the object.
+    assert(!SS.isSet() && "ObjectType and scope specifier cannot coexist");
+    LookupCtx = computeDeclContext(ObjectType);
+    isDependent = ObjectType->isDependentType();
+  } else if (SS.isSet()) {
+    // This nested-name-specifier occurs after another nested-name-specifier,
+    // so long into the context associated with the prior nested-name-specifier.
+    LookupCtx = computeDeclContext(SS, false);
+    isDependent = isDependentScopeSpecifier(SS);
+    Found.setContextRange(SS.getRange());
+  }
+  
+  if (LookupCtx) {
+    // Perform "qualified" name lookup into the declaration context we
+    // computed, which is either the type of the base of a member access
+    // expression or the declaration context associated with a prior
+    // nested-name-specifier.
+    
+    // The declaration context must be complete.
+    if (!LookupCtx->isDependentContext() &&
+        RequireCompleteDeclContext(SS, LookupCtx))
+      return false;
+    
+    LookupQualifiedName(Found, LookupCtx);
+  } else if (isDependent) {
+    return false;
+  } else {
+    LookupName(Found, S);
+  }
+  Found.suppressDiagnostics();
+  
+  if (NamedDecl *ND = Found.getAsSingle<NamedDecl>())
+    return isa<NamespaceDecl>(ND) || isa<NamespaceAliasDecl>(ND);
+  
+  return false;
+}
+
+namespace {
+
+// Callback to only accept typo corrections that can be a valid C++ member
+// intializer: either a non-static field member or a base class.
+class NestedNameSpecifierValidatorCCC : public CorrectionCandidateCallback {
+ public:
+  explicit NestedNameSpecifierValidatorCCC(Sema &SRef)
+      : SRef(SRef) {}
+
+  virtual bool ValidateCandidate(const TypoCorrection &candidate) {
+    return SRef.isAcceptableNestedNameSpecifier(candidate.getCorrectionDecl());
+  }
+
+ private:
+  Sema &SRef;
+};
+
+}
+
+/// \brief Build a new nested-name-specifier for "identifier::", as described
+/// by ActOnCXXNestedNameSpecifier.
+///
+/// This routine differs only slightly from ActOnCXXNestedNameSpecifier, in
+/// that it contains an extra parameter \p ScopeLookupResult, which provides
+/// the result of name lookup within the scope of the nested-name-specifier
+/// that was computed at template definition time.
+///
+/// If ErrorRecoveryLookup is true, then this call is used to improve error
+/// recovery.  This means that it should not emit diagnostics, it should
+/// just return true on failure.  It also means it should only return a valid
+/// scope if it *knows* that the result is correct.  It should not return in a
+/// dependent context, for example. Nor will it extend \p SS with the scope
+/// specifier.
+bool Sema::BuildCXXNestedNameSpecifier(Scope *S,
+                                       IdentifierInfo &Identifier,
+                                       SourceLocation IdentifierLoc,
+                                       SourceLocation CCLoc,
+                                       QualType ObjectType,
+                                       bool EnteringContext,
+                                       CXXScopeSpec &SS,
+                                       NamedDecl *ScopeLookupResult,
+                                       bool ErrorRecoveryLookup) {
+  LookupResult Found(*this, &Identifier, IdentifierLoc, 
+                     LookupNestedNameSpecifierName);
+
+  // Determine where to perform name lookup
+  DeclContext *LookupCtx = 0;
+  bool isDependent = false;
+  if (!ObjectType.isNull()) {
+    // This nested-name-specifier occurs in a member access expression, e.g.,
+    // x->B::f, and we are looking into the type of the object.
+    assert(!SS.isSet() && "ObjectType and scope specifier cannot coexist");
+    LookupCtx = computeDeclContext(ObjectType);
+    isDependent = ObjectType->isDependentType();
+  } else if (SS.isSet()) {
+    // This nested-name-specifier occurs after another nested-name-specifier,
+    // so look into the context associated with the prior nested-name-specifier.
+    LookupCtx = computeDeclContext(SS, EnteringContext);
+    isDependent = isDependentScopeSpecifier(SS);
+    Found.setContextRange(SS.getRange());
+  }
+
+
+  bool ObjectTypeSearchedInScope = false;
+  if (LookupCtx) {
+    // Perform "qualified" name lookup into the declaration context we
+    // computed, which is either the type of the base of a member access
+    // expression or the declaration context associated with a prior
+    // nested-name-specifier.
+
+    // The declaration context must be complete.
+    if (!LookupCtx->isDependentContext() &&
+        RequireCompleteDeclContext(SS, LookupCtx))
+      return true;
+
+    LookupQualifiedName(Found, LookupCtx);
+
+    if (!ObjectType.isNull() && Found.empty()) {
+      // C++ [basic.lookup.classref]p4:
+      //   If the id-expression in a class member access is a qualified-id of
+      //   the form
+      //
+      //        class-name-or-namespace-name::...
+      //
+      //   the class-name-or-namespace-name following the . or -> operator is
+      //   looked up both in the context of the entire postfix-expression and in
+      //   the scope of the class of the object expression. If the name is found
+      //   only in the scope of the class of the object expression, the name
+      //   shall refer to a class-name. If the name is found only in the
+      //   context of the entire postfix-expression, the name shall refer to a
+      //   class-name or namespace-name. [...]
+      //
+      // Qualified name lookup into a class will not find a namespace-name,
+      // so we do not need to diagnose that case specifically. However,
+      // this qualified name lookup may find nothing. In that case, perform
+      // unqualified name lookup in the given scope (if available) or
+      // reconstruct the result from when name lookup was performed at template
+      // definition time.
+      if (S)
+        LookupName(Found, S);
+      else if (ScopeLookupResult)
+        Found.addDecl(ScopeLookupResult);
+
+      ObjectTypeSearchedInScope = true;
+    }
+  } else if (!isDependent) {
+    // Perform unqualified name lookup in the current scope.
+    LookupName(Found, S);
+  }
+
+  // If we performed lookup into a dependent context and did not find anything,
+  // that's fine: just build a dependent nested-name-specifier.
+  if (Found.empty() && isDependent &&
+      !(LookupCtx && LookupCtx->isRecord() &&
+        (!cast<CXXRecordDecl>(LookupCtx)->hasDefinition() ||
+         !cast<CXXRecordDecl>(LookupCtx)->hasAnyDependentBases()))) {
+    // Don't speculate if we're just trying to improve error recovery.
+    if (ErrorRecoveryLookup)
+      return true;
+    
+    // We were not able to compute the declaration context for a dependent
+    // base object type or prior nested-name-specifier, so this
+    // nested-name-specifier refers to an unknown specialization. Just build
+    // a dependent nested-name-specifier.
+    SS.Extend(Context, &Identifier, IdentifierLoc, CCLoc);
+    return false;
+  } 
+  
+  // FIXME: Deal with ambiguities cleanly.
+
+  if (Found.empty() && !ErrorRecoveryLookup) {
+    // We haven't found anything, and we're not recovering from a
+    // different kind of error, so look for typos.
+    DeclarationName Name = Found.getLookupName();
+    NestedNameSpecifierValidatorCCC Validator(*this);
+    TypoCorrection Corrected;
+    Found.clear();
+    if ((Corrected = CorrectTypo(Found.getLookupNameInfo(),
+                                 Found.getLookupKind(), S, &SS, Validator,
+                                 LookupCtx, EnteringContext))) {
+      std::string CorrectedStr(Corrected.getAsString(getLangOpts()));
+      std::string CorrectedQuotedStr(Corrected.getQuoted(getLangOpts()));
+      if (LookupCtx)
+        Diag(Found.getNameLoc(), diag::err_no_member_suggest)
+          << Name << LookupCtx << CorrectedQuotedStr << SS.getRange()
+          << FixItHint::CreateReplacement(Found.getNameLoc(), CorrectedStr);
+      else
+        Diag(Found.getNameLoc(), diag::err_undeclared_var_use_suggest)
+          << Name << CorrectedQuotedStr
+          << FixItHint::CreateReplacement(Found.getNameLoc(), CorrectedStr);
+      
+      if (NamedDecl *ND = Corrected.getCorrectionDecl()) {
+        Diag(ND->getLocation(), diag::note_previous_decl) << CorrectedQuotedStr;
+        Found.addDecl(ND);
+      }
+      Found.setLookupName(Corrected.getCorrection());
+    } else {
+      Found.setLookupName(&Identifier);
+    }
+  }
+
+  NamedDecl *SD = Found.getAsSingle<NamedDecl>();
+  if (isAcceptableNestedNameSpecifier(SD)) {
+    if (!ObjectType.isNull() && !ObjectTypeSearchedInScope) {
+      // C++ [basic.lookup.classref]p4:
+      //   [...] If the name is found in both contexts, the
+      //   class-name-or-namespace-name shall refer to the same entity.
+      //
+      // We already found the name in the scope of the object. Now, look
+      // into the current scope (the scope of the postfix-expression) to
+      // see if we can find the same name there. As above, if there is no
+      // scope, reconstruct the result from the template instantiation itself.
+      NamedDecl *OuterDecl;
+      if (S) {
+        LookupResult FoundOuter(*this, &Identifier, IdentifierLoc, 
+                                LookupNestedNameSpecifierName);
+        LookupName(FoundOuter, S);
+        OuterDecl = FoundOuter.getAsSingle<NamedDecl>();
+      } else
+        OuterDecl = ScopeLookupResult;
+
+      if (isAcceptableNestedNameSpecifier(OuterDecl) &&
+          OuterDecl->getCanonicalDecl() != SD->getCanonicalDecl() &&
+          (!isa<TypeDecl>(OuterDecl) || !isa<TypeDecl>(SD) ||
+           !Context.hasSameType(
+                            Context.getTypeDeclType(cast<TypeDecl>(OuterDecl)),
+                               Context.getTypeDeclType(cast<TypeDecl>(SD))))) {
+         if (ErrorRecoveryLookup)
+           return true;
+
+         Diag(IdentifierLoc, 
+              diag::err_nested_name_member_ref_lookup_ambiguous)
+           << &Identifier;
+         Diag(SD->getLocation(), diag::note_ambig_member_ref_object_type)
+           << ObjectType;
+         Diag(OuterDecl->getLocation(), diag::note_ambig_member_ref_scope);
+
+         // Fall through so that we'll pick the name we found in the object
+         // type, since that's probably what the user wanted anyway.
+       }
+    }
+
+    // If we're just performing this lookup for error-recovery purposes, 
+    // don't extend the nested-name-specifier. Just return now.
+    if (ErrorRecoveryLookup)
+      return false;
+    
+    if (NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(SD)) {
+      SS.Extend(Context, Namespace, IdentifierLoc, CCLoc);
+      return false;
+    }
+
+    if (NamespaceAliasDecl *Alias = dyn_cast<NamespaceAliasDecl>(SD)) {
+      SS.Extend(Context, Alias, IdentifierLoc, CCLoc);
+      return false;
+    }
+
+    QualType T = Context.getTypeDeclType(cast<TypeDecl>(SD));
+    TypeLocBuilder TLB;
+    if (isa<InjectedClassNameType>(T)) {
+      InjectedClassNameTypeLoc InjectedTL
+        = TLB.push<InjectedClassNameTypeLoc>(T);
+      InjectedTL.setNameLoc(IdentifierLoc);
+    } else if (isa<RecordType>(T)) {
+      RecordTypeLoc RecordTL = TLB.push<RecordTypeLoc>(T);
+      RecordTL.setNameLoc(IdentifierLoc);
+    } else if (isa<TypedefType>(T)) {
+      TypedefTypeLoc TypedefTL = TLB.push<TypedefTypeLoc>(T);
+      TypedefTL.setNameLoc(IdentifierLoc);
+    } else if (isa<EnumType>(T)) {
+      EnumTypeLoc EnumTL = TLB.push<EnumTypeLoc>(T);
+      EnumTL.setNameLoc(IdentifierLoc);
+    } else if (isa<TemplateTypeParmType>(T)) {
+      TemplateTypeParmTypeLoc TemplateTypeTL
+        = TLB.push<TemplateTypeParmTypeLoc>(T);
+      TemplateTypeTL.setNameLoc(IdentifierLoc);
+    } else if (isa<UnresolvedUsingType>(T)) {
+      UnresolvedUsingTypeLoc UnresolvedTL
+        = TLB.push<UnresolvedUsingTypeLoc>(T);
+      UnresolvedTL.setNameLoc(IdentifierLoc);
+    } else if (isa<SubstTemplateTypeParmType>(T)) {
+      SubstTemplateTypeParmTypeLoc TL 
+        = TLB.push<SubstTemplateTypeParmTypeLoc>(T);
+      TL.setNameLoc(IdentifierLoc);
+    } else if (isa<SubstTemplateTypeParmPackType>(T)) {
+      SubstTemplateTypeParmPackTypeLoc TL
+        = TLB.push<SubstTemplateTypeParmPackTypeLoc>(T);
+      TL.setNameLoc(IdentifierLoc);
+    } else {
+      llvm_unreachable("Unhandled TypeDecl node in nested-name-specifier");
+    }
+
+    if (T->isEnumeralType())
+      Diag(IdentifierLoc, diag::warn_cxx98_compat_enum_nested_name_spec);
+
+    SS.Extend(Context, SourceLocation(), TLB.getTypeLocInContext(Context, T),
+              CCLoc);
+    return false;
+  }
+
+  // Otherwise, we have an error case.  If we don't want diagnostics, just
+  // return an error now.
+  if (ErrorRecoveryLookup)
+    return true;
+
+  // If we didn't find anything during our lookup, try again with
+  // ordinary name lookup, which can help us produce better error
+  // messages.
+  if (Found.empty()) {
+    Found.clear(LookupOrdinaryName);
+    LookupName(Found, S);
+  }
+
+  // In Microsoft mode, if we are within a templated function and we can't
+  // resolve Identifier, then extend the SS with Identifier. This will have 
+  // the effect of resolving Identifier during template instantiation. 
+  // The goal is to be able to resolve a function call whose
+  // nested-name-specifier is located inside a dependent base class.
+  // Example: 
+  //
+  // class C {
+  // public:
+  //    static void foo2() {  }
+  // };
+  // template <class T> class A { public: typedef C D; };
+  //
+  // template <class T> class B : public A<T> {
+  // public:
+  //   void foo() { D::foo2(); }
+  // };
+  if (getLangOpts().MicrosoftExt) {
+    DeclContext *DC = LookupCtx ? LookupCtx : CurContext;
+    if (DC->isDependentContext() && DC->isFunctionOrMethod()) {
+      SS.Extend(Context, &Identifier, IdentifierLoc, CCLoc);
+      return false;
+    }
+  }
+
+  unsigned DiagID;
+  if (!Found.empty())
+    DiagID = diag::err_expected_class_or_namespace;
+  else if (SS.isSet()) {
+    Diag(IdentifierLoc, diag::err_no_member) 
+      << &Identifier << LookupCtx << SS.getRange();
+    return true;
+  } else
+    DiagID = diag::err_undeclared_var_use;
+
+  if (SS.isSet())
+    Diag(IdentifierLoc, DiagID) << &Identifier << SS.getRange();
+  else
+    Diag(IdentifierLoc, DiagID) << &Identifier;
+
+  return true;
+}
+
+bool Sema::ActOnCXXNestedNameSpecifier(Scope *S,
+                                       IdentifierInfo &Identifier,
+                                       SourceLocation IdentifierLoc,
+                                       SourceLocation CCLoc,
+                                       ParsedType ObjectType,
+                                       bool EnteringContext,
+                                       CXXScopeSpec &SS) {
+  if (SS.isInvalid())
+    return true;
+  
+  return BuildCXXNestedNameSpecifier(S, Identifier, IdentifierLoc, CCLoc,
+                                     GetTypeFromParser(ObjectType),
+                                     EnteringContext, SS, 
+                                     /*ScopeLookupResult=*/0, false);
+}
+
+bool Sema::ActOnCXXNestedNameSpecifierDecltype(CXXScopeSpec &SS,
+                                               const DeclSpec &DS,
+                                               SourceLocation ColonColonLoc) {
+  if (SS.isInvalid() || DS.getTypeSpecType() == DeclSpec::TST_error)
+    return true;
+
+  assert(DS.getTypeSpecType() == DeclSpec::TST_decltype);
+
+  QualType T = BuildDecltypeType(DS.getRepAsExpr(), DS.getTypeSpecTypeLoc());
+  if (!T->isDependentType() && !T->getAs<TagType>()) {
+    Diag(DS.getTypeSpecTypeLoc(), diag::err_expected_class) 
+      << T << getLangOpts().CPlusPlus;
+    return true;
+  }
+
+  TypeLocBuilder TLB;
+  DecltypeTypeLoc DecltypeTL = TLB.push<DecltypeTypeLoc>(T);
+  DecltypeTL.setNameLoc(DS.getTypeSpecTypeLoc());
+  SS.Extend(Context, SourceLocation(), TLB.getTypeLocInContext(Context, T),
+            ColonColonLoc);
+  return false;
+}
+
+/// IsInvalidUnlessNestedName - This method is used for error recovery
+/// purposes to determine whether the specified identifier is only valid as
+/// a nested name specifier, for example a namespace name.  It is
+/// conservatively correct to always return false from this method.
+///
+/// The arguments are the same as those passed to ActOnCXXNestedNameSpecifier.
+bool Sema::IsInvalidUnlessNestedName(Scope *S, CXXScopeSpec &SS,
+                                     IdentifierInfo &Identifier, 
+                                     SourceLocation IdentifierLoc,
+                                     SourceLocation ColonLoc,
+                                     ParsedType ObjectType,
+                                     bool EnteringContext) {
+  if (SS.isInvalid())
+    return false;
+  
+  return !BuildCXXNestedNameSpecifier(S, Identifier, IdentifierLoc, ColonLoc,
+                                      GetTypeFromParser(ObjectType),
+                                      EnteringContext, SS, 
+                                      /*ScopeLookupResult=*/0, true);
+}
+
+bool Sema::ActOnCXXNestedNameSpecifier(Scope *S,
+                                       CXXScopeSpec &SS,
+                                       SourceLocation TemplateKWLoc,
+                                       TemplateTy Template,
+                                       SourceLocation TemplateNameLoc,
+                                       SourceLocation LAngleLoc,
+                                       ASTTemplateArgsPtr TemplateArgsIn,
+                                       SourceLocation RAngleLoc,
+                                       SourceLocation CCLoc,
+                                       bool EnteringContext) {
+  if (SS.isInvalid())
+    return true;
+  
+  // Translate the parser's template argument list in our AST format.
+  TemplateArgumentListInfo TemplateArgs(LAngleLoc, RAngleLoc);
+  translateTemplateArguments(TemplateArgsIn, TemplateArgs);
+
+  if (DependentTemplateName *DTN = Template.get().getAsDependentTemplateName()){
+    // Handle a dependent template specialization for which we cannot resolve
+    // the template name.
+    assert(DTN->getQualifier()
+             == static_cast<NestedNameSpecifier*>(SS.getScopeRep()));
+    QualType T = Context.getDependentTemplateSpecializationType(ETK_None,
+                                                          DTN->getQualifier(),
+                                                          DTN->getIdentifier(),
+                                                                TemplateArgs);
+    
+    // Create source-location information for this type.
+    TypeLocBuilder Builder;
+    DependentTemplateSpecializationTypeLoc SpecTL
+      = Builder.push<DependentTemplateSpecializationTypeLoc>(T);
+    SpecTL.setElaboratedKeywordLoc(SourceLocation());
+    SpecTL.setQualifierLoc(SS.getWithLocInContext(Context));
+    SpecTL.setTemplateKeywordLoc(TemplateKWLoc);
+    SpecTL.setTemplateNameLoc(TemplateNameLoc);
+    SpecTL.setLAngleLoc(LAngleLoc);
+    SpecTL.setRAngleLoc(RAngleLoc);
+    for (unsigned I = 0, N = TemplateArgs.size(); I != N; ++I)
+      SpecTL.setArgLocInfo(I, TemplateArgs[I].getLocInfo());
+    
+    SS.Extend(Context, TemplateKWLoc, Builder.getTypeLocInContext(Context, T),
+              CCLoc);
+    return false;
+  }
+  
+  
+  if (Template.get().getAsOverloadedTemplate() ||
+      isa<FunctionTemplateDecl>(Template.get().getAsTemplateDecl())) {
+    SourceRange R(TemplateNameLoc, RAngleLoc);
+    if (SS.getRange().isValid())
+      R.setBegin(SS.getRange().getBegin());
+      
+    Diag(CCLoc, diag::err_non_type_template_in_nested_name_specifier)
+      << Template.get() << R;
+    NoteAllFoundTemplates(Template.get());
+    return true;
+  }
+                                
+  // We were able to resolve the template name to an actual template. 
+  // Build an appropriate nested-name-specifier.
+  QualType T = CheckTemplateIdType(Template.get(), TemplateNameLoc, 
+                                   TemplateArgs);
+  if (T.isNull())
+    return true;
+
+  // Alias template specializations can produce types which are not valid
+  // nested name specifiers.
+  if (!T->isDependentType() && !T->getAs<TagType>()) {
+    Diag(TemplateNameLoc, diag::err_nested_name_spec_non_tag) << T;
+    NoteAllFoundTemplates(Template.get());
+    return true;
+  }
+
+  // Provide source-location information for the template specialization type.
+  TypeLocBuilder Builder;
+  TemplateSpecializationTypeLoc SpecTL
+    = Builder.push<TemplateSpecializationTypeLoc>(T);
+  SpecTL.setTemplateKeywordLoc(TemplateKWLoc);
+  SpecTL.setTemplateNameLoc(TemplateNameLoc);
+  SpecTL.setLAngleLoc(LAngleLoc);
+  SpecTL.setRAngleLoc(RAngleLoc);
+  for (unsigned I = 0, N = TemplateArgs.size(); I != N; ++I)
+    SpecTL.setArgLocInfo(I, TemplateArgs[I].getLocInfo());
+
+
+  SS.Extend(Context, TemplateKWLoc, Builder.getTypeLocInContext(Context, T),
+            CCLoc);
+  return false;
+}
+
+namespace {
+  /// \brief A structure that stores a nested-name-specifier annotation,
+  /// including both the nested-name-specifier 
+  struct NestedNameSpecifierAnnotation {
+    NestedNameSpecifier *NNS;
+  };
+}
+
+void *Sema::SaveNestedNameSpecifierAnnotation(CXXScopeSpec &SS) {
+  if (SS.isEmpty() || SS.isInvalid())
+    return 0;
+  
+  void *Mem = Context.Allocate((sizeof(NestedNameSpecifierAnnotation) +
+                                                        SS.location_size()),
+                               llvm::alignOf<NestedNameSpecifierAnnotation>());
+  NestedNameSpecifierAnnotation *Annotation
+    = new (Mem) NestedNameSpecifierAnnotation;
+  Annotation->NNS = SS.getScopeRep();
+  memcpy(Annotation + 1, SS.location_data(), SS.location_size());
+  return Annotation;
+}
+
+void Sema::RestoreNestedNameSpecifierAnnotation(void *AnnotationPtr, 
+                                                SourceRange AnnotationRange,
+                                                CXXScopeSpec &SS) {
+  if (!AnnotationPtr) {
+    SS.SetInvalid(AnnotationRange);
+    return;
+  }
+  
+  NestedNameSpecifierAnnotation *Annotation
+    = static_cast<NestedNameSpecifierAnnotation *>(AnnotationPtr);
+  SS.Adopt(NestedNameSpecifierLoc(Annotation->NNS, Annotation + 1));
+}
+
+bool Sema::ShouldEnterDeclaratorScope(Scope *S, const CXXScopeSpec &SS) {
+  assert(SS.isSet() && "Parser passed invalid CXXScopeSpec.");
+
+  NestedNameSpecifier *Qualifier =
+    static_cast<NestedNameSpecifier*>(SS.getScopeRep());
+
+  // There are only two places a well-formed program may qualify a
+  // declarator: first, when defining a namespace or class member
+  // out-of-line, and second, when naming an explicitly-qualified
+  // friend function.  The latter case is governed by
+  // C++03 [basic.lookup.unqual]p10:
+  //   In a friend declaration naming a member function, a name used
+  //   in the function declarator and not part of a template-argument
+  //   in a template-id is first looked up in the scope of the member
+  //   function's class. If it is not found, or if the name is part of
+  //   a template-argument in a template-id, the look up is as
+  //   described for unqualified names in the definition of the class
+  //   granting friendship.
+  // i.e. we don't push a scope unless it's a class member.
+
+  switch (Qualifier->getKind()) {
+  case NestedNameSpecifier::Global:
+  case NestedNameSpecifier::Namespace:
+  case NestedNameSpecifier::NamespaceAlias:
+    // These are always namespace scopes.  We never want to enter a
+    // namespace scope from anything but a file context.
+    return CurContext->getRedeclContext()->isFileContext();
+
+  case NestedNameSpecifier::Identifier:
+  case NestedNameSpecifier::TypeSpec:
+  case NestedNameSpecifier::TypeSpecWithTemplate:
+    // These are never namespace scopes.
+    return true;
+  }
+
+  llvm_unreachable("Invalid NestedNameSpecifier::Kind!");
+}
+
+/// ActOnCXXEnterDeclaratorScope - Called when a C++ scope specifier (global
+/// scope or nested-name-specifier) is parsed, part of a declarator-id.
+/// After this method is called, according to [C++ 3.4.3p3], names should be
+/// looked up in the declarator-id's scope, until the declarator is parsed and
+/// ActOnCXXExitDeclaratorScope is called.
+/// The 'SS' should be a non-empty valid CXXScopeSpec.
+bool Sema::ActOnCXXEnterDeclaratorScope(Scope *S, CXXScopeSpec &SS) {
+  assert(SS.isSet() && "Parser passed invalid CXXScopeSpec.");
+
+  if (SS.isInvalid()) return true;
+
+  DeclContext *DC = computeDeclContext(SS, true);
+  if (!DC) return true;
+
+  // Before we enter a declarator's context, we need to make sure that
+  // it is a complete declaration context.
+  if (!DC->isDependentContext() && RequireCompleteDeclContext(SS, DC))
+    return true;
+    
+  EnterDeclaratorContext(S, DC);
+
+  // Rebuild the nested name specifier for the new scope.
+  if (DC->isDependentContext())
+    RebuildNestedNameSpecifierInCurrentInstantiation(SS);
+
+  return false;
+}
+
+/// ActOnCXXExitDeclaratorScope - Called when a declarator that previously
+/// invoked ActOnCXXEnterDeclaratorScope(), is finished. 'SS' is the same
+/// CXXScopeSpec that was passed to ActOnCXXEnterDeclaratorScope as well.
+/// Used to indicate that names should revert to being looked up in the
+/// defining scope.
+void Sema::ActOnCXXExitDeclaratorScope(Scope *S, const CXXScopeSpec &SS) {
+  assert(SS.isSet() && "Parser passed invalid CXXScopeSpec.");
+  if (SS.isInvalid())
+    return;
+  assert(!SS.isInvalid() && computeDeclContext(SS, true) &&
+         "exiting declarator scope we never really entered");
+  ExitDeclaratorContext(S);
+}
diff --git a/clang/lib/Sema/SemaCast.cpp b/clang/lib/Sema/SemaCast.cpp
new file mode 100644
index 0000000..54683e1
--- /dev/null
+++ b/clang/lib/Sema/SemaCast.cpp
@@ -0,0 +1,2112 @@
+//===--- SemaCast.cpp - Semantic Analysis for Casts -----------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+//  This file implements semantic analysis for cast expressions, including
+//  1) C-style casts like '(int) x'
+//  2) C++ functional casts like 'int(x)'
+//  3) C++ named casts like 'static_cast<int>(x)'
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Sema/SemaInternal.h"
+#include "clang/Sema/Initialization.h"
+#include "clang/AST/ExprCXX.h"
+#include "clang/AST/ExprObjC.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/CXXInheritance.h"
+#include "clang/Basic/PartialDiagnostic.h"
+#include "llvm/ADT/SmallVector.h"
+#include <set>
+using namespace clang;
+
+
+
+enum TryCastResult {
+  TC_NotApplicable, ///< The cast method is not applicable.
+  TC_Success,       ///< The cast method is appropriate and successful.
+  TC_Failed         ///< The cast method is appropriate, but failed. A
+                    ///< diagnostic has been emitted.
+};
+
+enum CastType {
+  CT_Const,       ///< const_cast
+  CT_Static,      ///< static_cast
+  CT_Reinterpret, ///< reinterpret_cast
+  CT_Dynamic,     ///< dynamic_cast
+  CT_CStyle,      ///< (Type)expr
+  CT_Functional   ///< Type(expr)
+};
+
+namespace {
+  struct CastOperation {
+    CastOperation(Sema &S, QualType destType, ExprResult src)
+      : Self(S), SrcExpr(src), DestType(destType),
+        ResultType(destType.getNonLValueExprType(S.Context)),
+        ValueKind(Expr::getValueKindForType(destType)),
+        Kind(CK_Dependent), IsARCUnbridgedCast(false) {
+
+      if (const BuiltinType *placeholder =
+            src.get()->getType()->getAsPlaceholderType()) {
+        PlaceholderKind = placeholder->getKind();
+      } else {
+        PlaceholderKind = (BuiltinType::Kind) 0;
+      }
+    }
+
+    Sema &Self;
+    ExprResult SrcExpr;
+    QualType DestType;
+    QualType ResultType;
+    ExprValueKind ValueKind;
+    CastKind Kind;
+    BuiltinType::Kind PlaceholderKind;
+    CXXCastPath BasePath;
+    bool IsARCUnbridgedCast;
+
+    SourceRange OpRange;
+    SourceRange DestRange;
+
+    // Top-level semantics-checking routines.
+    void CheckConstCast();
+    void CheckReinterpretCast();
+    void CheckStaticCast();
+    void CheckDynamicCast();
+    void CheckCXXCStyleCast(bool FunctionalCast, bool ListInitialization);
+    void CheckCStyleCast();
+
+    /// Complete an apparently-successful cast operation that yields
+    /// the given expression.
+    ExprResult complete(CastExpr *castExpr) {
+      // If this is an unbridged cast, wrap the result in an implicit
+      // cast that yields the unbridged-cast placeholder type.
+      if (IsARCUnbridgedCast) {
+        castExpr = ImplicitCastExpr::Create(Self.Context,
+                                            Self.Context.ARCUnbridgedCastTy,
+                                            CK_Dependent, castExpr, 0,
+                                            castExpr->getValueKind());
+      }
+      return Self.Owned(castExpr);
+    }
+
+    // Internal convenience methods.
+
+    /// Try to handle the given placeholder expression kind.  Return
+    /// true if the source expression has the appropriate placeholder
+    /// kind.  A placeholder can only be claimed once.
+    bool claimPlaceholder(BuiltinType::Kind K) {
+      if (PlaceholderKind != K) return false;
+
+      PlaceholderKind = (BuiltinType::Kind) 0;
+      return true;
+    }
+
+    bool isPlaceholder() const {
+      return PlaceholderKind != 0;
+    }
+    bool isPlaceholder(BuiltinType::Kind K) const {
+      return PlaceholderKind == K;
+    }
+
+    void checkCastAlign() {
+      Self.CheckCastAlign(SrcExpr.get(), DestType, OpRange);
+    }
+
+    void checkObjCARCConversion(Sema::CheckedConversionKind CCK) {
+      assert(Self.getLangOpts().ObjCAutoRefCount);
+
+      Expr *src = SrcExpr.get();
+      if (Self.CheckObjCARCConversion(OpRange, DestType, src, CCK) ==
+            Sema::ACR_unbridged)
+        IsARCUnbridgedCast = true;
+      SrcExpr = src;
+    }
+
+    /// Check for and handle non-overload placeholder expressions.
+    void checkNonOverloadPlaceholders() {
+      if (!isPlaceholder() || isPlaceholder(BuiltinType::Overload))
+        return;
+
+      SrcExpr = Self.CheckPlaceholderExpr(SrcExpr.take());
+      if (SrcExpr.isInvalid())
+        return;
+      PlaceholderKind = (BuiltinType::Kind) 0;
+    }
+  };
+}
+
+static bool CastsAwayConstness(Sema &Self, QualType SrcType, QualType DestType,
+                               bool CheckCVR, bool CheckObjCLifetime);
+
+// The Try functions attempt a specific way of casting. If they succeed, they
+// return TC_Success. If their way of casting is not appropriate for the given
+// arguments, they return TC_NotApplicable and *may* set diag to a diagnostic
+// to emit if no other way succeeds. If their way of casting is appropriate but
+// fails, they return TC_Failed and *must* set diag; they can set it to 0 if
+// they emit a specialized diagnostic.
+// All diagnostics returned by these functions must expect the same three
+// arguments:
+// %0: Cast Type (a value from the CastType enumeration)
+// %1: Source Type
+// %2: Destination Type
+static TryCastResult TryLValueToRValueCast(Sema &Self, Expr *SrcExpr,
+                                           QualType DestType, bool CStyle,
+                                           CastKind &Kind,
+                                           CXXCastPath &BasePath,
+                                           unsigned &msg);
+static TryCastResult TryStaticReferenceDowncast(Sema &Self, Expr *SrcExpr,
+                                               QualType DestType, bool CStyle,
+                                               const SourceRange &OpRange,
+                                               unsigned &msg,
+                                               CastKind &Kind,
+                                               CXXCastPath &BasePath);
+static TryCastResult TryStaticPointerDowncast(Sema &Self, QualType SrcType,
+                                              QualType DestType, bool CStyle,
+                                              const SourceRange &OpRange,
+                                              unsigned &msg,
+                                              CastKind &Kind,
+                                              CXXCastPath &BasePath);
+static TryCastResult TryStaticDowncast(Sema &Self, CanQualType SrcType,
+                                       CanQualType DestType, bool CStyle,
+                                       const SourceRange &OpRange,
+                                       QualType OrigSrcType,
+                                       QualType OrigDestType, unsigned &msg,
+                                       CastKind &Kind,
+                                       CXXCastPath &BasePath);
+static TryCastResult TryStaticMemberPointerUpcast(Sema &Self, ExprResult &SrcExpr,
+                                               QualType SrcType,
+                                               QualType DestType,bool CStyle,
+                                               const SourceRange &OpRange,
+                                               unsigned &msg,
+                                               CastKind &Kind,
+                                               CXXCastPath &BasePath);
+
+static TryCastResult TryStaticImplicitCast(Sema &Self, ExprResult &SrcExpr,
+                                           QualType DestType, 
+                                           Sema::CheckedConversionKind CCK,
+                                           const SourceRange &OpRange,
+                                           unsigned &msg, CastKind &Kind,
+                                           bool ListInitialization);
+static TryCastResult TryStaticCast(Sema &Self, ExprResult &SrcExpr,
+                                   QualType DestType, 
+                                   Sema::CheckedConversionKind CCK,
+                                   const SourceRange &OpRange,
+                                   unsigned &msg, CastKind &Kind,
+                                   CXXCastPath &BasePath,
+                                   bool ListInitialization);
+static TryCastResult TryConstCast(Sema &Self, Expr *SrcExpr, QualType DestType,
+                                  bool CStyle, unsigned &msg);
+static TryCastResult TryReinterpretCast(Sema &Self, ExprResult &SrcExpr,
+                                        QualType DestType, bool CStyle,
+                                        const SourceRange &OpRange,
+                                        unsigned &msg,
+                                        CastKind &Kind);
+
+
+/// ActOnCXXNamedCast - Parse {dynamic,static,reinterpret,const}_cast's.
+ExprResult
+Sema::ActOnCXXNamedCast(SourceLocation OpLoc, tok::TokenKind Kind,
+                        SourceLocation LAngleBracketLoc, Declarator &D,
+                        SourceLocation RAngleBracketLoc,
+                        SourceLocation LParenLoc, Expr *E,
+                        SourceLocation RParenLoc) {
+
+  assert(!D.isInvalidType());
+
+  TypeSourceInfo *TInfo = GetTypeForDeclaratorCast(D, E->getType());
+  if (D.isInvalidType())
+    return ExprError();
+
+  if (getLangOpts().CPlusPlus) {
+    // Check that there are no default arguments (C++ only).
+    CheckExtraCXXDefaultArguments(D);
+  }
+
+  return BuildCXXNamedCast(OpLoc, Kind, TInfo, move(E),
+                           SourceRange(LAngleBracketLoc, RAngleBracketLoc),
+                           SourceRange(LParenLoc, RParenLoc));
+}
+
+ExprResult
+Sema::BuildCXXNamedCast(SourceLocation OpLoc, tok::TokenKind Kind,
+                        TypeSourceInfo *DestTInfo, Expr *E,
+                        SourceRange AngleBrackets, SourceRange Parens) {
+  ExprResult Ex = Owned(E);
+  QualType DestType = DestTInfo->getType();
+
+  // If the type is dependent, we won't do the semantic analysis now.
+  // FIXME: should we check this in a more fine-grained manner?
+  bool TypeDependent = DestType->isDependentType() || Ex.get()->isTypeDependent();
+
+  CastOperation Op(*this, DestType, E);
+  Op.OpRange = SourceRange(OpLoc, Parens.getEnd());
+  Op.DestRange = AngleBrackets;
+
+  switch (Kind) {
+  default: llvm_unreachable("Unknown C++ cast!");
+
+  case tok::kw_const_cast:
+    if (!TypeDependent) {
+      Op.CheckConstCast();
+      if (Op.SrcExpr.isInvalid())
+        return ExprError();
+    }
+    return Op.complete(CXXConstCastExpr::Create(Context, Op.ResultType,
+                                  Op.ValueKind, Op.SrcExpr.take(), DestTInfo,
+                                                OpLoc, Parens.getEnd()));
+
+  case tok::kw_dynamic_cast: {
+    if (!TypeDependent) {
+      Op.CheckDynamicCast();
+      if (Op.SrcExpr.isInvalid())
+        return ExprError();
+    }
+    return Op.complete(CXXDynamicCastExpr::Create(Context, Op.ResultType,
+                                    Op.ValueKind, Op.Kind, Op.SrcExpr.take(),
+                                                  &Op.BasePath, DestTInfo,
+                                                  OpLoc, Parens.getEnd()));
+  }
+  case tok::kw_reinterpret_cast: {
+    if (!TypeDependent) {
+      Op.CheckReinterpretCast();
+      if (Op.SrcExpr.isInvalid())
+        return ExprError();
+    }
+    return Op.complete(CXXReinterpretCastExpr::Create(Context, Op.ResultType,
+                                    Op.ValueKind, Op.Kind, Op.SrcExpr.take(),
+                                                      0, DestTInfo, OpLoc,
+                                                      Parens.getEnd()));
+  }
+  case tok::kw_static_cast: {
+    if (!TypeDependent) {
+      Op.CheckStaticCast();
+      if (Op.SrcExpr.isInvalid())
+        return ExprError();
+    }
+    
+    return Op.complete(CXXStaticCastExpr::Create(Context, Op.ResultType,
+                                   Op.ValueKind, Op.Kind, Op.SrcExpr.take(),
+                                                 &Op.BasePath, DestTInfo,
+                                                 OpLoc, Parens.getEnd()));
+  }
+  }
+}
+
+/// Try to diagnose a failed overloaded cast.  Returns true if
+/// diagnostics were emitted.
+static bool tryDiagnoseOverloadedCast(Sema &S, CastType CT,
+                                      SourceRange range, Expr *src,
+                                      QualType destType,
+                                      bool listInitialization) {
+  switch (CT) {
+  // These cast kinds don't consider user-defined conversions.
+  case CT_Const:
+  case CT_Reinterpret:
+  case CT_Dynamic:
+    return false;
+
+  // These do.
+  case CT_Static:
+  case CT_CStyle:
+  case CT_Functional:
+    break;
+  }
+
+  QualType srcType = src->getType();
+  if (!destType->isRecordType() && !srcType->isRecordType())
+    return false;
+
+  InitializedEntity entity = InitializedEntity::InitializeTemporary(destType);
+  InitializationKind initKind
+    = (CT == CT_CStyle)? InitializationKind::CreateCStyleCast(range.getBegin(),
+                                                      range, listInitialization)
+    : (CT == CT_Functional)? InitializationKind::CreateFunctionalCast(range,
+                                                             listInitialization)
+    : InitializationKind::CreateCast(/*type range?*/ range);
+  InitializationSequence sequence(S, entity, initKind, &src, 1);
+
+  assert(sequence.Failed() && "initialization succeeded on second try?");
+  switch (sequence.getFailureKind()) {
+  default: return false;
+
+  case InitializationSequence::FK_ConstructorOverloadFailed:
+  case InitializationSequence::FK_UserConversionOverloadFailed:
+    break;
+  }
+
+  OverloadCandidateSet &candidates = sequence.getFailedCandidateSet();
+
+  unsigned msg = 0;
+  OverloadCandidateDisplayKind howManyCandidates = OCD_AllCandidates;
+
+  switch (sequence.getFailedOverloadResult()) {
+  case OR_Success: llvm_unreachable("successful failed overload");
+  case OR_No_Viable_Function:
+    if (candidates.empty())
+      msg = diag::err_ovl_no_conversion_in_cast;
+    else
+      msg = diag::err_ovl_no_viable_conversion_in_cast;
+    howManyCandidates = OCD_AllCandidates;
+    break;
+
+  case OR_Ambiguous:
+    msg = diag::err_ovl_ambiguous_conversion_in_cast;
+    howManyCandidates = OCD_ViableCandidates;
+    break;
+
+  case OR_Deleted:
+    msg = diag::err_ovl_deleted_conversion_in_cast;
+    howManyCandidates = OCD_ViableCandidates;
+    break;
+  }
+
+  S.Diag(range.getBegin(), msg)
+    << CT << srcType << destType
+    << range << src->getSourceRange();
+
+  candidates.NoteCandidates(S, howManyCandidates, src);
+
+  return true;
+}
+
+/// Diagnose a failed cast.
+static void diagnoseBadCast(Sema &S, unsigned msg, CastType castType,
+                            SourceRange opRange, Expr *src, QualType destType,
+                            bool listInitialization) {
+  if (src->getType() == S.Context.BoundMemberTy) {
+    (void) S.CheckPlaceholderExpr(src); // will always fail
+    return;
+  }
+
+  if (msg == diag::err_bad_cxx_cast_generic &&
+      tryDiagnoseOverloadedCast(S, castType, opRange, src, destType,
+                                listInitialization))
+    return;
+
+  S.Diag(opRange.getBegin(), msg) << castType
+    << src->getType() << destType << opRange << src->getSourceRange();
+}
+
+/// UnwrapDissimilarPointerTypes - Like Sema::UnwrapSimilarPointerTypes,
+/// this removes one level of indirection from both types, provided that they're
+/// the same kind of pointer (plain or to-member). Unlike the Sema function,
+/// this one doesn't care if the two pointers-to-member don't point into the
+/// same class. This is because CastsAwayConstness doesn't care.
+static bool UnwrapDissimilarPointerTypes(QualType& T1, QualType& T2) {
+  const PointerType *T1PtrType = T1->getAs<PointerType>(),
+                    *T2PtrType = T2->getAs<PointerType>();
+  if (T1PtrType && T2PtrType) {
+    T1 = T1PtrType->getPointeeType();
+    T2 = T2PtrType->getPointeeType();
+    return true;
+  }
+  const ObjCObjectPointerType *T1ObjCPtrType = 
+                                            T1->getAs<ObjCObjectPointerType>(),
+                              *T2ObjCPtrType = 
+                                            T2->getAs<ObjCObjectPointerType>();
+  if (T1ObjCPtrType) {
+    if (T2ObjCPtrType) {
+      T1 = T1ObjCPtrType->getPointeeType();
+      T2 = T2ObjCPtrType->getPointeeType();
+      return true;
+    }
+    else if (T2PtrType) {
+      T1 = T1ObjCPtrType->getPointeeType();
+      T2 = T2PtrType->getPointeeType();
+      return true;
+    }
+  }
+  else if (T2ObjCPtrType) {
+    if (T1PtrType) {
+      T2 = T2ObjCPtrType->getPointeeType();
+      T1 = T1PtrType->getPointeeType();
+      return true;
+    }
+  }
+  
+  const MemberPointerType *T1MPType = T1->getAs<MemberPointerType>(),
+                          *T2MPType = T2->getAs<MemberPointerType>();
+  if (T1MPType && T2MPType) {
+    T1 = T1MPType->getPointeeType();
+    T2 = T2MPType->getPointeeType();
+    return true;
+  }
+  
+  const BlockPointerType *T1BPType = T1->getAs<BlockPointerType>(),
+                         *T2BPType = T2->getAs<BlockPointerType>();
+  if (T1BPType && T2BPType) {
+    T1 = T1BPType->getPointeeType();
+    T2 = T2BPType->getPointeeType();
+    return true;
+  }
+  
+  return false;
+}
+
+/// CastsAwayConstness - Check if the pointer conversion from SrcType to
+/// DestType casts away constness as defined in C++ 5.2.11p8ff. This is used by
+/// the cast checkers.  Both arguments must denote pointer (possibly to member)
+/// types.
+///
+/// \param CheckCVR Whether to check for const/volatile/restrict qualifiers.
+///
+/// \param CheckObjCLifetime Whether to check Objective-C lifetime qualifiers.
+static bool
+CastsAwayConstness(Sema &Self, QualType SrcType, QualType DestType,
+                   bool CheckCVR, bool CheckObjCLifetime) {
+  // If the only checking we care about is for Objective-C lifetime qualifiers,
+  // and we're not in ARC mode, there's nothing to check.
+  if (!CheckCVR && CheckObjCLifetime && 
+      !Self.Context.getLangOpts().ObjCAutoRefCount)
+    return false;
+    
+  // Casting away constness is defined in C++ 5.2.11p8 with reference to
+  // C++ 4.4. We piggyback on Sema::IsQualificationConversion for this, since
+  // the rules are non-trivial. So first we construct Tcv *...cv* as described
+  // in C++ 5.2.11p8.
+  assert((SrcType->isAnyPointerType() || SrcType->isMemberPointerType() ||
+          SrcType->isBlockPointerType()) &&
+         "Source type is not pointer or pointer to member.");
+  assert((DestType->isAnyPointerType() || DestType->isMemberPointerType() ||
+          DestType->isBlockPointerType()) &&
+         "Destination type is not pointer or pointer to member.");
+
+  QualType UnwrappedSrcType = Self.Context.getCanonicalType(SrcType), 
+           UnwrappedDestType = Self.Context.getCanonicalType(DestType);
+  SmallVector<Qualifiers, 8> cv1, cv2;
+
+  // Find the qualifiers. We only care about cvr-qualifiers for the 
+  // purpose of this check, because other qualifiers (address spaces, 
+  // Objective-C GC, etc.) are part of the type's identity.
+  while (UnwrapDissimilarPointerTypes(UnwrappedSrcType, UnwrappedDestType)) {
+    // Determine the relevant qualifiers at this level.
+    Qualifiers SrcQuals, DestQuals;
+    Self.Context.getUnqualifiedArrayType(UnwrappedSrcType, SrcQuals);
+    Self.Context.getUnqualifiedArrayType(UnwrappedDestType, DestQuals);
+    
+    Qualifiers RetainedSrcQuals, RetainedDestQuals;
+    if (CheckCVR) {
+      RetainedSrcQuals.setCVRQualifiers(SrcQuals.getCVRQualifiers());
+      RetainedDestQuals.setCVRQualifiers(DestQuals.getCVRQualifiers());
+    }
+    
+    if (CheckObjCLifetime &&
+        !DestQuals.compatiblyIncludesObjCLifetime(SrcQuals))
+      return true;
+    
+    cv1.push_back(RetainedSrcQuals);
+    cv2.push_back(RetainedDestQuals);
+  }
+  if (cv1.empty())
+    return false;
+
+  // Construct void pointers with those qualifiers (in reverse order of
+  // unwrapping, of course).
+  QualType SrcConstruct = Self.Context.VoidTy;
+  QualType DestConstruct = Self.Context.VoidTy;
+  ASTContext &Context = Self.Context;
+  for (SmallVector<Qualifiers, 8>::reverse_iterator i1 = cv1.rbegin(),
+                                                          i2 = cv2.rbegin();
+       i1 != cv1.rend(); ++i1, ++i2) {
+    SrcConstruct
+      = Context.getPointerType(Context.getQualifiedType(SrcConstruct, *i1));
+    DestConstruct
+      = Context.getPointerType(Context.getQualifiedType(DestConstruct, *i2));
+  }
+
+  // Test if they're compatible.
+  bool ObjCLifetimeConversion;
+  return SrcConstruct != DestConstruct &&
+    !Self.IsQualificationConversion(SrcConstruct, DestConstruct, false,
+                                    ObjCLifetimeConversion);
+}
+
+/// CheckDynamicCast - Check that a dynamic_cast\<DestType\>(SrcExpr) is valid.
+/// Refer to C++ 5.2.7 for details. Dynamic casts are used mostly for runtime-
+/// checked downcasts in class hierarchies.
+void CastOperation::CheckDynamicCast() {
+  if (ValueKind == VK_RValue)
+    SrcExpr = Self.DefaultFunctionArrayLvalueConversion(SrcExpr.take());
+  else if (isPlaceholder())
+    SrcExpr = Self.CheckPlaceholderExpr(SrcExpr.take());
+  if (SrcExpr.isInvalid()) // if conversion failed, don't report another error
+    return;
+
+  QualType OrigSrcType = SrcExpr.get()->getType();
+  QualType DestType = Self.Context.getCanonicalType(this->DestType);
+
+  // C++ 5.2.7p1: T shall be a pointer or reference to a complete class type,
+  //   or "pointer to cv void".
+
+  QualType DestPointee;
+  const PointerType *DestPointer = DestType->getAs<PointerType>();
+  const ReferenceType *DestReference = 0;
+  if (DestPointer) {
+    DestPointee = DestPointer->getPointeeType();
+  } else if ((DestReference = DestType->getAs<ReferenceType>())) {
+    DestPointee = DestReference->getPointeeType();
+  } else {
+    Self.Diag(OpRange.getBegin(), diag::err_bad_dynamic_cast_not_ref_or_ptr)
+      << this->DestType << DestRange;
+    return;
+  }
+
+  const RecordType *DestRecord = DestPointee->getAs<RecordType>();
+  if (DestPointee->isVoidType()) {
+    assert(DestPointer && "Reference to void is not possible");
+  } else if (DestRecord) {
+    if (Self.RequireCompleteType(OpRange.getBegin(), DestPointee,
+                               Self.PDiag(diag::err_bad_dynamic_cast_incomplete)
+                                   << DestRange))
+      return;
+  } else {
+    Self.Diag(OpRange.getBegin(), diag::err_bad_dynamic_cast_not_class)
+      << DestPointee.getUnqualifiedType() << DestRange;
+    return;
+  }
+
+  // C++0x 5.2.7p2: If T is a pointer type, v shall be an rvalue of a pointer to
+  //   complete class type, [...]. If T is an lvalue reference type, v shall be
+  //   an lvalue of a complete class type, [...]. If T is an rvalue reference 
+  //   type, v shall be an expression having a complete class type, [...]
+  QualType SrcType = Self.Context.getCanonicalType(OrigSrcType);
+  QualType SrcPointee;
+  if (DestPointer) {
+    if (const PointerType *SrcPointer = SrcType->getAs<PointerType>()) {
+      SrcPointee = SrcPointer->getPointeeType();
+    } else {
+      Self.Diag(OpRange.getBegin(), diag::err_bad_dynamic_cast_not_ptr)
+        << OrigSrcType << SrcExpr.get()->getSourceRange();
+      return;
+    }
+  } else if (DestReference->isLValueReferenceType()) {
+    if (!SrcExpr.get()->isLValue()) {
+      Self.Diag(OpRange.getBegin(), diag::err_bad_cxx_cast_rvalue)
+        << CT_Dynamic << OrigSrcType << this->DestType << OpRange;
+    }
+    SrcPointee = SrcType;
+  } else {
+    SrcPointee = SrcType;
+  }
+
+  const RecordType *SrcRecord = SrcPointee->getAs<RecordType>();
+  if (SrcRecord) {
+    if (Self.RequireCompleteType(OpRange.getBegin(), SrcPointee,
+                             Self.PDiag(diag::err_bad_dynamic_cast_incomplete)
+                                   << SrcExpr.get()->getSourceRange()))
+      return;
+  } else {
+    Self.Diag(OpRange.getBegin(), diag::err_bad_dynamic_cast_not_class)
+      << SrcPointee.getUnqualifiedType() << SrcExpr.get()->getSourceRange();
+    return;
+  }
+
+  assert((DestPointer || DestReference) &&
+    "Bad destination non-ptr/ref slipped through.");
+  assert((DestRecord || DestPointee->isVoidType()) &&
+    "Bad destination pointee slipped through.");
+  assert(SrcRecord && "Bad source pointee slipped through.");
+
+  // C++ 5.2.7p1: The dynamic_cast operator shall not cast away constness.
+  if (!DestPointee.isAtLeastAsQualifiedAs(SrcPointee)) {
+    Self.Diag(OpRange.getBegin(), diag::err_bad_cxx_cast_qualifiers_away)
+      << CT_Dynamic << OrigSrcType << this->DestType << OpRange;
+    return;
+  }
+
+  // C++ 5.2.7p3: If the type of v is the same as the required result type,
+  //   [except for cv].
+  if (DestRecord == SrcRecord) {
+    Kind = CK_NoOp;
+    return;
+  }
+
+  // C++ 5.2.7p5
+  // Upcasts are resolved statically.
+  if (DestRecord && Self.IsDerivedFrom(SrcPointee, DestPointee)) {
+    if (Self.CheckDerivedToBaseConversion(SrcPointee, DestPointee,
+                                           OpRange.getBegin(), OpRange, 
+                                           &BasePath))
+        return;
+        
+    Kind = CK_DerivedToBase;
+
+    // If we are casting to or through a virtual base class, we need a
+    // vtable.
+    if (Self.BasePathInvolvesVirtualBase(BasePath))
+      Self.MarkVTableUsed(OpRange.getBegin(), 
+                          cast<CXXRecordDecl>(SrcRecord->getDecl()));
+    return;
+  }
+
+  // C++ 5.2.7p6: Otherwise, v shall be [polymorphic].
+  const RecordDecl *SrcDecl = SrcRecord->getDecl()->getDefinition();
+  assert(SrcDecl && "Definition missing");
+  if (!cast<CXXRecordDecl>(SrcDecl)->isPolymorphic()) {
+    Self.Diag(OpRange.getBegin(), diag::err_bad_dynamic_cast_not_polymorphic)
+      << SrcPointee.getUnqualifiedType() << SrcExpr.get()->getSourceRange();
+  }
+  Self.MarkVTableUsed(OpRange.getBegin(), 
+                      cast<CXXRecordDecl>(SrcRecord->getDecl()));
+
+  // Done. Everything else is run-time checks.
+  Kind = CK_Dynamic;
+}
+
+/// CheckConstCast - Check that a const_cast\<DestType\>(SrcExpr) is valid.
+/// Refer to C++ 5.2.11 for details. const_cast is typically used in code
+/// like this:
+/// const char *str = "literal";
+/// legacy_function(const_cast\<char*\>(str));
+void CastOperation::CheckConstCast() {
+  if (ValueKind == VK_RValue)
+    SrcExpr = Self.DefaultFunctionArrayLvalueConversion(SrcExpr.take());
+  else if (isPlaceholder())
+    SrcExpr = Self.CheckPlaceholderExpr(SrcExpr.take());
+  if (SrcExpr.isInvalid()) // if conversion failed, don't report another error
+    return;
+
+  unsigned msg = diag::err_bad_cxx_cast_generic;
+  if (TryConstCast(Self, SrcExpr.get(), DestType, /*CStyle*/false, msg) != TC_Success
+      && msg != 0)
+    Self.Diag(OpRange.getBegin(), msg) << CT_Const
+      << SrcExpr.get()->getType() << DestType << OpRange;
+}
+
+/// CheckReinterpretCast - Check that a reinterpret_cast\<DestType\>(SrcExpr) is
+/// valid.
+/// Refer to C++ 5.2.10 for details. reinterpret_cast is typically used in code
+/// like this:
+/// char *bytes = reinterpret_cast\<char*\>(int_ptr);
+void CastOperation::CheckReinterpretCast() {
+  if (ValueKind == VK_RValue && !isPlaceholder(BuiltinType::Overload))
+    SrcExpr = Self.DefaultFunctionArrayLvalueConversion(SrcExpr.take());
+  else
+    checkNonOverloadPlaceholders();
+  if (SrcExpr.isInvalid()) // if conversion failed, don't report another error
+    return;
+
+  unsigned msg = diag::err_bad_cxx_cast_generic;
+  TryCastResult tcr = 
+    TryReinterpretCast(Self, SrcExpr, DestType, 
+                       /*CStyle*/false, OpRange, msg, Kind);
+  if (tcr != TC_Success && msg != 0)
+  {
+    if (SrcExpr.isInvalid()) // if conversion failed, don't report another error
+      return;
+    if (SrcExpr.get()->getType() == Self.Context.OverloadTy) {
+      //FIXME: &f<int>; is overloaded and resolvable 
+      Self.Diag(OpRange.getBegin(), diag::err_bad_reinterpret_cast_overload) 
+        << OverloadExpr::find(SrcExpr.get()).Expression->getName()
+        << DestType << OpRange;
+      Self.NoteAllOverloadCandidates(SrcExpr.get());
+
+    } else {
+      diagnoseBadCast(Self, msg, CT_Reinterpret, OpRange, SrcExpr.get(),
+                      DestType, /*listInitialization=*/false);
+    }
+  } else if (tcr == TC_Success && Self.getLangOpts().ObjCAutoRefCount) {
+    checkObjCARCConversion(Sema::CCK_OtherCast);
+  }
+}
+
+
+/// CheckStaticCast - Check that a static_cast\<DestType\>(SrcExpr) is valid.
+/// Refer to C++ 5.2.9 for details. Static casts are mostly used for making
+/// implicit conversions explicit and getting rid of data loss warnings.
+void CastOperation::CheckStaticCast() {
+  if (isPlaceholder()) {
+    checkNonOverloadPlaceholders();
+    if (SrcExpr.isInvalid())
+      return;
+  }
+
+  // This test is outside everything else because it's the only case where
+  // a non-lvalue-reference target type does not lead to decay.
+  // C++ 5.2.9p4: Any expression can be explicitly converted to type "cv void".
+  if (DestType->isVoidType()) {
+    Kind = CK_ToVoid;
+
+    if (claimPlaceholder(BuiltinType::Overload)) {
+      Self.ResolveAndFixSingleFunctionTemplateSpecialization(SrcExpr, 
+                false, // Decay Function to ptr 
+                true, // Complain
+                OpRange, DestType, diag::err_bad_static_cast_overload);
+      if (SrcExpr.isInvalid())
+        return;
+    }
+
+    SrcExpr = Self.IgnoredValueConversions(SrcExpr.take());
+    return;
+  }
+
+  if (ValueKind == VK_RValue && !DestType->isRecordType() &&
+      !isPlaceholder(BuiltinType::Overload)) {
+    SrcExpr = Self.DefaultFunctionArrayLvalueConversion(SrcExpr.take());
+    if (SrcExpr.isInvalid()) // if conversion failed, don't report another error
+      return;
+  }
+
+  unsigned msg = diag::err_bad_cxx_cast_generic;
+  TryCastResult tcr
+    = TryStaticCast(Self, SrcExpr, DestType, Sema::CCK_OtherCast, OpRange, msg,
+                    Kind, BasePath, /*ListInitialization=*/false);
+  if (tcr != TC_Success && msg != 0) {
+    if (SrcExpr.isInvalid())
+      return;
+    if (SrcExpr.get()->getType() == Self.Context.OverloadTy) {
+      OverloadExpr* oe = OverloadExpr::find(SrcExpr.get()).Expression;
+      Self.Diag(OpRange.getBegin(), diag::err_bad_static_cast_overload)
+        << oe->getName() << DestType << OpRange 
+        << oe->getQualifierLoc().getSourceRange();
+      Self.NoteAllOverloadCandidates(SrcExpr.get());
+    } else {
+      diagnoseBadCast(Self, msg, CT_Static, OpRange, SrcExpr.get(), DestType,
+                      /*listInitialization=*/false);
+    }
+  } else if (tcr == TC_Success) {
+    if (Kind == CK_BitCast)
+      checkCastAlign();
+    if (Self.getLangOpts().ObjCAutoRefCount)
+      checkObjCARCConversion(Sema::CCK_OtherCast);
+  } else if (Kind == CK_BitCast) {
+    checkCastAlign();
+  }
+}
+
+/// TryStaticCast - Check if a static cast can be performed, and do so if
+/// possible. If @p CStyle, ignore access restrictions on hierarchy casting
+/// and casting away constness.
+static TryCastResult TryStaticCast(Sema &Self, ExprResult &SrcExpr,
+                                   QualType DestType, 
+                                   Sema::CheckedConversionKind CCK,
+                                   const SourceRange &OpRange, unsigned &msg,
+                                   CastKind &Kind, CXXCastPath &BasePath,
+                                   bool ListInitialization) {
+  // Determine whether we have the semantics of a C-style cast.
+  bool CStyle 
+    = (CCK == Sema::CCK_CStyleCast || CCK == Sema::CCK_FunctionalCast);
+  
+  // The order the tests is not entirely arbitrary. There is one conversion
+  // that can be handled in two different ways. Given:
+  // struct A {};
+  // struct B : public A {
+  //   B(); B(const A&);
+  // };
+  // const A &a = B();
+  // the cast static_cast<const B&>(a) could be seen as either a static
+  // reference downcast, or an explicit invocation of the user-defined
+  // conversion using B's conversion constructor.
+  // DR 427 specifies that the downcast is to be applied here.
+
+  // C++ 5.2.9p4: Any expression can be explicitly converted to type "cv void".
+  // Done outside this function.
+
+  TryCastResult tcr;
+
+  // C++ 5.2.9p5, reference downcast.
+  // See the function for details.
+  // DR 427 specifies that this is to be applied before paragraph 2.
+  tcr = TryStaticReferenceDowncast(Self, SrcExpr.get(), DestType, CStyle,
+                                   OpRange, msg, Kind, BasePath);
+  if (tcr != TC_NotApplicable)
+    return tcr;
+
+  // C++0x [expr.static.cast]p3: 
+  //   A glvalue of type "cv1 T1" can be cast to type "rvalue reference to cv2
+  //   T2" if "cv2 T2" is reference-compatible with "cv1 T1".
+  tcr = TryLValueToRValueCast(Self, SrcExpr.get(), DestType, CStyle, Kind, 
+                              BasePath, msg);
+  if (tcr != TC_NotApplicable)
+    return tcr;
+
+  // C++ 5.2.9p2: An expression e can be explicitly converted to a type T
+  //   [...] if the declaration "T t(e);" is well-formed, [...].
+  tcr = TryStaticImplicitCast(Self, SrcExpr, DestType, CCK, OpRange, msg,
+                              Kind, ListInitialization);
+  if (SrcExpr.isInvalid())
+    return TC_Failed;
+  if (tcr != TC_NotApplicable)
+    return tcr;
+  
+  // C++ 5.2.9p6: May apply the reverse of any standard conversion, except
+  // lvalue-to-rvalue, array-to-pointer, function-to-pointer, and boolean
+  // conversions, subject to further restrictions.
+  // Also, C++ 5.2.9p1 forbids casting away constness, which makes reversal
+  // of qualification conversions impossible.
+  // In the CStyle case, the earlier attempt to const_cast should have taken
+  // care of reverse qualification conversions.
+
+  QualType SrcType = Self.Context.getCanonicalType(SrcExpr.get()->getType());
+
+  // C++0x 5.2.9p9: A value of a scoped enumeration type can be explicitly
+  // converted to an integral type. [...] A value of a scoped enumeration type
+  // can also be explicitly converted to a floating-point type [...].
+  if (const EnumType *Enum = SrcType->getAs<EnumType>()) {
+    if (Enum->getDecl()->isScoped()) {
+      if (DestType->isBooleanType()) {
+        Kind = CK_IntegralToBoolean;
+        return TC_Success;
+      } else if (DestType->isIntegralType(Self.Context)) {
+        Kind = CK_IntegralCast;
+        return TC_Success;
+      } else if (DestType->isRealFloatingType()) {
+        Kind = CK_IntegralToFloating;
+        return TC_Success;
+      }
+    }
+  }
+  
+  // Reverse integral promotion/conversion. All such conversions are themselves
+  // again integral promotions or conversions and are thus already handled by
+  // p2 (TryDirectInitialization above).
+  // (Note: any data loss warnings should be suppressed.)
+  // The exception is the reverse of enum->integer, i.e. integer->enum (and
+  // enum->enum). See also C++ 5.2.9p7.
+  // The same goes for reverse floating point promotion/conversion and
+  // floating-integral conversions. Again, only floating->enum is relevant.
+  if (DestType->isEnumeralType()) {
+    if (SrcType->isIntegralOrEnumerationType()) {
+      Kind = CK_IntegralCast;
+      return TC_Success;
+    } else if (SrcType->isRealFloatingType())   {
+      Kind = CK_FloatingToIntegral;
+      return TC_Success;
+    }
+  }
+
+  // Reverse pointer upcast. C++ 4.10p3 specifies pointer upcast.
+  // C++ 5.2.9p8 additionally disallows a cast path through virtual inheritance.
+  tcr = TryStaticPointerDowncast(Self, SrcType, DestType, CStyle, OpRange, msg,
+                                 Kind, BasePath);
+  if (tcr != TC_NotApplicable)
+    return tcr;
+
+  // Reverse member pointer conversion. C++ 4.11 specifies member pointer
+  // conversion. C++ 5.2.9p9 has additional information.
+  // DR54's access restrictions apply here also.
+  tcr = TryStaticMemberPointerUpcast(Self, SrcExpr, SrcType, DestType, CStyle,
+                                     OpRange, msg, Kind, BasePath);
+  if (tcr != TC_NotApplicable)
+    return tcr;
+
+  // Reverse pointer conversion to void*. C++ 4.10.p2 specifies conversion to
+  // void*. C++ 5.2.9p10 specifies additional restrictions, which really is
+  // just the usual constness stuff.
+  if (const PointerType *SrcPointer = SrcType->getAs<PointerType>()) {
+    QualType SrcPointee = SrcPointer->getPointeeType();
+    if (SrcPointee->isVoidType()) {
+      if (const PointerType *DestPointer = DestType->getAs<PointerType>()) {
+        QualType DestPointee = DestPointer->getPointeeType();
+        if (DestPointee->isIncompleteOrObjectType()) {
+          // This is definitely the intended conversion, but it might fail due
+          // to a qualifier violation. Note that we permit Objective-C lifetime
+          // and GC qualifier mismatches here.
+          if (!CStyle) {
+            Qualifiers DestPointeeQuals = DestPointee.getQualifiers();
+            Qualifiers SrcPointeeQuals = SrcPointee.getQualifiers();
+            DestPointeeQuals.removeObjCGCAttr();
+            DestPointeeQuals.removeObjCLifetime();
+            SrcPointeeQuals.removeObjCGCAttr();
+            SrcPointeeQuals.removeObjCLifetime();
+            if (DestPointeeQuals != SrcPointeeQuals &&
+                !DestPointeeQuals.compatiblyIncludes(SrcPointeeQuals)) {
+              msg = diag::err_bad_cxx_cast_qualifiers_away;
+              return TC_Failed;
+            }
+          }
+          Kind = CK_BitCast;
+          return TC_Success;
+        }
+      }
+      else if (DestType->isObjCObjectPointerType()) {
+        // allow both c-style cast and static_cast of objective-c pointers as 
+        // they are pervasive.
+        Kind = CK_CPointerToObjCPointerCast;
+        return TC_Success;
+      }
+      else if (CStyle && DestType->isBlockPointerType()) {
+        // allow c-style cast of void * to block pointers.
+        Kind = CK_AnyPointerToBlockPointerCast;
+        return TC_Success;
+      }
+    }
+  }
+  // Allow arbitray objective-c pointer conversion with static casts.
+  if (SrcType->isObjCObjectPointerType() &&
+      DestType->isObjCObjectPointerType()) {
+    Kind = CK_BitCast;
+    return TC_Success;
+  }
+  
+  // We tried everything. Everything! Nothing works! :-(
+  return TC_NotApplicable;
+}
+
+/// Tests whether a conversion according to N2844 is valid.
+TryCastResult
+TryLValueToRValueCast(Sema &Self, Expr *SrcExpr, QualType DestType,
+                      bool CStyle, CastKind &Kind, CXXCastPath &BasePath, 
+                      unsigned &msg) {
+  // C++0x [expr.static.cast]p3:
+  //   A glvalue of type "cv1 T1" can be cast to type "rvalue reference to 
+  //   cv2 T2" if "cv2 T2" is reference-compatible with "cv1 T1".
+  const RValueReferenceType *R = DestType->getAs<RValueReferenceType>();
+  if (!R)
+    return TC_NotApplicable;
+
+  if (!SrcExpr->isGLValue())
+    return TC_NotApplicable;
+
+  // Because we try the reference downcast before this function, from now on
+  // this is the only cast possibility, so we issue an error if we fail now.
+  // FIXME: Should allow casting away constness if CStyle.
+  bool DerivedToBase;
+  bool ObjCConversion;
+  bool ObjCLifetimeConversion;
+  QualType FromType = SrcExpr->getType();
+  QualType ToType = R->getPointeeType();
+  if (CStyle) {
+    FromType = FromType.getUnqualifiedType();
+    ToType = ToType.getUnqualifiedType();
+  }
+  
+  if (Self.CompareReferenceRelationship(SrcExpr->getLocStart(),
+                                        ToType, FromType,
+                                        DerivedToBase, ObjCConversion,
+                                        ObjCLifetimeConversion) 
+        < Sema::Ref_Compatible_With_Added_Qualification) {
+    msg = diag::err_bad_lvalue_to_rvalue_cast;
+    return TC_Failed;
+  }
+
+  if (DerivedToBase) {
+    Kind = CK_DerivedToBase;
+    CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
+                       /*DetectVirtual=*/true);
+    if (!Self.IsDerivedFrom(SrcExpr->getType(), R->getPointeeType(), Paths))
+      return TC_NotApplicable;
+  
+    Self.BuildBasePathArray(Paths, BasePath);
+  } else
+    Kind = CK_NoOp;
+  
+  return TC_Success;
+}
+
+/// Tests whether a conversion according to C++ 5.2.9p5 is valid.
+TryCastResult
+TryStaticReferenceDowncast(Sema &Self, Expr *SrcExpr, QualType DestType,
+                           bool CStyle, const SourceRange &OpRange,
+                           unsigned &msg, CastKind &Kind,
+                           CXXCastPath &BasePath) {
+  // C++ 5.2.9p5: An lvalue of type "cv1 B", where B is a class type, can be
+  //   cast to type "reference to cv2 D", where D is a class derived from B,
+  //   if a valid standard conversion from "pointer to D" to "pointer to B"
+  //   exists, cv2 >= cv1, and B is not a virtual base class of D.
+  // In addition, DR54 clarifies that the base must be accessible in the
+  // current context. Although the wording of DR54 only applies to the pointer
+  // variant of this rule, the intent is clearly for it to apply to the this
+  // conversion as well.
+
+  const ReferenceType *DestReference = DestType->getAs<ReferenceType>();
+  if (!DestReference) {
+    return TC_NotApplicable;
+  }
+  bool RValueRef = DestReference->isRValueReferenceType();
+  if (!RValueRef && !SrcExpr->isLValue()) {
+    // We know the left side is an lvalue reference, so we can suggest a reason.
+    msg = diag::err_bad_cxx_cast_rvalue;
+    return TC_NotApplicable;
+  }
+
+  QualType DestPointee = DestReference->getPointeeType();
+
+  return TryStaticDowncast(Self, 
+                           Self.Context.getCanonicalType(SrcExpr->getType()), 
+                           Self.Context.getCanonicalType(DestPointee), CStyle,
+                           OpRange, SrcExpr->getType(), DestType, msg, Kind,
+                           BasePath);
+}
+
+/// Tests whether a conversion according to C++ 5.2.9p8 is valid.
+TryCastResult
+TryStaticPointerDowncast(Sema &Self, QualType SrcType, QualType DestType,
+                         bool CStyle, const SourceRange &OpRange,
+                         unsigned &msg, CastKind &Kind,
+                         CXXCastPath &BasePath) {
+  // C++ 5.2.9p8: An rvalue of type "pointer to cv1 B", where B is a class
+  //   type, can be converted to an rvalue of type "pointer to cv2 D", where D
+  //   is a class derived from B, if a valid standard conversion from "pointer
+  //   to D" to "pointer to B" exists, cv2 >= cv1, and B is not a virtual base
+  //   class of D.
+  // In addition, DR54 clarifies that the base must be accessible in the
+  // current context.
+
+  const PointerType *DestPointer = DestType->getAs<PointerType>();
+  if (!DestPointer) {
+    return TC_NotApplicable;
+  }
+
+  const PointerType *SrcPointer = SrcType->getAs<PointerType>();
+  if (!SrcPointer) {
+    msg = diag::err_bad_static_cast_pointer_nonpointer;
+    return TC_NotApplicable;
+  }
+
+  return TryStaticDowncast(Self, 
+                   Self.Context.getCanonicalType(SrcPointer->getPointeeType()),
+                  Self.Context.getCanonicalType(DestPointer->getPointeeType()), 
+                           CStyle, OpRange, SrcType, DestType, msg, Kind,
+                           BasePath);
+}
+
+/// TryStaticDowncast - Common functionality of TryStaticReferenceDowncast and
+/// TryStaticPointerDowncast. Tests whether a static downcast from SrcType to
+/// DestType is possible and allowed.
+TryCastResult
+TryStaticDowncast(Sema &Self, CanQualType SrcType, CanQualType DestType,
+                  bool CStyle, const SourceRange &OpRange, QualType OrigSrcType,
+                  QualType OrigDestType, unsigned &msg, 
+                  CastKind &Kind, CXXCastPath &BasePath) {
+  // We can only work with complete types. But don't complain if it doesn't work
+  if (Self.RequireCompleteType(OpRange.getBegin(), SrcType, Self.PDiag(0)) ||
+      Self.RequireCompleteType(OpRange.getBegin(), DestType, Self.PDiag(0)))
+    return TC_NotApplicable;
+
+  // Downcast can only happen in class hierarchies, so we need classes.
+  if (!DestType->getAs<RecordType>() || !SrcType->getAs<RecordType>()) {
+    return TC_NotApplicable;
+  }
+
+  CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
+                     /*DetectVirtual=*/true);
+  if (!Self.IsDerivedFrom(DestType, SrcType, Paths)) {
+    return TC_NotApplicable;
+  }
+
+  // Target type does derive from source type. Now we're serious. If an error
+  // appears now, it's not ignored.
+  // This may not be entirely in line with the standard. Take for example:
+  // struct A {};
+  // struct B : virtual A {
+  //   B(A&);
+  // };
+  //
+  // void f()
+  // {
+  //   (void)static_cast<const B&>(*((A*)0));
+  // }
+  // As far as the standard is concerned, p5 does not apply (A is virtual), so
+  // p2 should be used instead - "const B& t(*((A*)0));" is perfectly valid.
+  // However, both GCC and Comeau reject this example, and accepting it would
+  // mean more complex code if we're to preserve the nice error message.
+  // FIXME: Being 100% compliant here would be nice to have.
+
+  // Must preserve cv, as always, unless we're in C-style mode.
+  if (!CStyle && !DestType.isAtLeastAsQualifiedAs(SrcType)) {
+    msg = diag::err_bad_cxx_cast_qualifiers_away;
+    return TC_Failed;
+  }
+
+  if (Paths.isAmbiguous(SrcType.getUnqualifiedType())) {
+    // This code is analoguous to that in CheckDerivedToBaseConversion, except
+    // that it builds the paths in reverse order.
+    // To sum up: record all paths to the base and build a nice string from
+    // them. Use it to spice up the error message.
+    if (!Paths.isRecordingPaths()) {
+      Paths.clear();
+      Paths.setRecordingPaths(true);
+      Self.IsDerivedFrom(DestType, SrcType, Paths);
+    }
+    std::string PathDisplayStr;
+    std::set<unsigned> DisplayedPaths;
+    for (CXXBasePaths::paths_iterator PI = Paths.begin(), PE = Paths.end();
+         PI != PE; ++PI) {
+      if (DisplayedPaths.insert(PI->back().SubobjectNumber).second) {
+        // We haven't displayed a path to this particular base
+        // class subobject yet.
+        PathDisplayStr += "\n    ";
+        for (CXXBasePath::const_reverse_iterator EI = PI->rbegin(),
+                                                 EE = PI->rend();
+             EI != EE; ++EI)
+          PathDisplayStr += EI->Base->getType().getAsString() + " -> ";
+        PathDisplayStr += QualType(DestType).getAsString();
+      }
+    }
+
+    Self.Diag(OpRange.getBegin(), diag::err_ambiguous_base_to_derived_cast)
+      << QualType(SrcType).getUnqualifiedType() 
+      << QualType(DestType).getUnqualifiedType()
+      << PathDisplayStr << OpRange;
+    msg = 0;
+    return TC_Failed;
+  }
+
+  if (Paths.getDetectedVirtual() != 0) {
+    QualType VirtualBase(Paths.getDetectedVirtual(), 0);
+    Self.Diag(OpRange.getBegin(), diag::err_static_downcast_via_virtual)
+      << OrigSrcType << OrigDestType << VirtualBase << OpRange;
+    msg = 0;
+    return TC_Failed;
+  }
+
+  if (!CStyle) {
+    switch (Self.CheckBaseClassAccess(OpRange.getBegin(),
+                                      SrcType, DestType,
+                                      Paths.front(),
+                                diag::err_downcast_from_inaccessible_base)) {
+    case Sema::AR_accessible:
+    case Sema::AR_delayed:     // be optimistic
+    case Sema::AR_dependent:   // be optimistic
+      break;
+
+    case Sema::AR_inaccessible:
+      msg = 0;
+      return TC_Failed;
+    }
+  }
+
+  Self.BuildBasePathArray(Paths, BasePath);
+  Kind = CK_BaseToDerived;
+  return TC_Success;
+}
+
+/// TryStaticMemberPointerUpcast - Tests whether a conversion according to
+/// C++ 5.2.9p9 is valid:
+///
+///   An rvalue of type "pointer to member of D of type cv1 T" can be
+///   converted to an rvalue of type "pointer to member of B of type cv2 T",
+///   where B is a base class of D [...].
+///
+TryCastResult
+TryStaticMemberPointerUpcast(Sema &Self, ExprResult &SrcExpr, QualType SrcType, 
+                             QualType DestType, bool CStyle, 
+                             const SourceRange &OpRange,
+                             unsigned &msg, CastKind &Kind,
+                             CXXCastPath &BasePath) {
+  const MemberPointerType *DestMemPtr = DestType->getAs<MemberPointerType>();
+  if (!DestMemPtr)
+    return TC_NotApplicable;
+
+  bool WasOverloadedFunction = false;
+  DeclAccessPair FoundOverload;
+  if (SrcExpr.get()->getType() == Self.Context.OverloadTy) {
+    if (FunctionDecl *Fn
+          = Self.ResolveAddressOfOverloadedFunction(SrcExpr.get(), DestType, false,
+                                                    FoundOverload)) {
+      CXXMethodDecl *M = cast<CXXMethodDecl>(Fn);
+      SrcType = Self.Context.getMemberPointerType(Fn->getType(),
+                      Self.Context.getTypeDeclType(M->getParent()).getTypePtr());
+      WasOverloadedFunction = true;
+    }
+  }
+  
+  const MemberPointerType *SrcMemPtr = SrcType->getAs<MemberPointerType>();
+  if (!SrcMemPtr) {
+    msg = diag::err_bad_static_cast_member_pointer_nonmp;
+    return TC_NotApplicable;
+  }
+
+  // T == T, modulo cv
+  if (!Self.Context.hasSameUnqualifiedType(SrcMemPtr->getPointeeType(),
+                                           DestMemPtr->getPointeeType()))
+    return TC_NotApplicable;
+
+  // B base of D
+  QualType SrcClass(SrcMemPtr->getClass(), 0);
+  QualType DestClass(DestMemPtr->getClass(), 0);
+  CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
+                  /*DetectVirtual=*/true);
+  if (!Self.IsDerivedFrom(SrcClass, DestClass, Paths)) {
+    return TC_NotApplicable;
+  }
+
+  // B is a base of D. But is it an allowed base? If not, it's a hard error.
+  if (Paths.isAmbiguous(Self.Context.getCanonicalType(DestClass))) {
+    Paths.clear();
+    Paths.setRecordingPaths(true);
+    bool StillOkay = Self.IsDerivedFrom(SrcClass, DestClass, Paths);
+    assert(StillOkay);
+    (void)StillOkay;
+    std::string PathDisplayStr = Self.getAmbiguousPathsDisplayString(Paths);
+    Self.Diag(OpRange.getBegin(), diag::err_ambiguous_memptr_conv)
+      << 1 << SrcClass << DestClass << PathDisplayStr << OpRange;
+    msg = 0;
+    return TC_Failed;
+  }
+
+  if (const RecordType *VBase = Paths.getDetectedVirtual()) {
+    Self.Diag(OpRange.getBegin(), diag::err_memptr_conv_via_virtual)
+      << SrcClass << DestClass << QualType(VBase, 0) << OpRange;
+    msg = 0;
+    return TC_Failed;
+  }
+
+  if (!CStyle) {
+    switch (Self.CheckBaseClassAccess(OpRange.getBegin(),
+                                      DestClass, SrcClass,
+                                      Paths.front(),
+                                      diag::err_upcast_to_inaccessible_base)) {
+    case Sema::AR_accessible:
+    case Sema::AR_delayed:
+    case Sema::AR_dependent:
+      // Optimistically assume that the delayed and dependent cases
+      // will work out.
+      break;
+
+    case Sema::AR_inaccessible:
+      msg = 0;
+      return TC_Failed;
+    }
+  }
+
+  if (WasOverloadedFunction) {
+    // Resolve the address of the overloaded function again, this time
+    // allowing complaints if something goes wrong.
+    FunctionDecl *Fn = Self.ResolveAddressOfOverloadedFunction(SrcExpr.get(), 
+                                                               DestType, 
+                                                               true,
+                                                               FoundOverload);
+    if (!Fn) {
+      msg = 0;
+      return TC_Failed;
+    }
+
+    SrcExpr = Self.FixOverloadedFunctionReference(SrcExpr, FoundOverload, Fn);
+    if (!SrcExpr.isUsable()) {
+      msg = 0;
+      return TC_Failed;
+    }
+  }
+
+  Self.BuildBasePathArray(Paths, BasePath);
+  Kind = CK_DerivedToBaseMemberPointer;
+  return TC_Success;
+}
+
+/// TryStaticImplicitCast - Tests whether a conversion according to C++ 5.2.9p2
+/// is valid:
+///
+///   An expression e can be explicitly converted to a type T using a
+///   @c static_cast if the declaration "T t(e);" is well-formed [...].
+TryCastResult
+TryStaticImplicitCast(Sema &Self, ExprResult &SrcExpr, QualType DestType,
+                      Sema::CheckedConversionKind CCK, 
+                      const SourceRange &OpRange, unsigned &msg,
+                      CastKind &Kind, bool ListInitialization) {
+  if (DestType->isRecordType()) {
+    if (Self.RequireCompleteType(OpRange.getBegin(), DestType,
+                                 diag::err_bad_dynamic_cast_incomplete)) {
+      msg = 0;
+      return TC_Failed;
+    }
+  }
+
+  InitializedEntity Entity = InitializedEntity::InitializeTemporary(DestType);
+  InitializationKind InitKind
+    = (CCK == Sema::CCK_CStyleCast)
+        ? InitializationKind::CreateCStyleCast(OpRange.getBegin(), OpRange,
+                                               ListInitialization)
+    : (CCK == Sema::CCK_FunctionalCast)
+        ? InitializationKind::CreateFunctionalCast(OpRange, ListInitialization)
+    : InitializationKind::CreateCast(OpRange);
+  Expr *SrcExprRaw = SrcExpr.get();
+  InitializationSequence InitSeq(Self, Entity, InitKind, &SrcExprRaw, 1);
+
+  // At this point of CheckStaticCast, if the destination is a reference,
+  // or the expression is an overload expression this has to work. 
+  // There is no other way that works.
+  // On the other hand, if we're checking a C-style cast, we've still got
+  // the reinterpret_cast way.
+  bool CStyle 
+    = (CCK == Sema::CCK_CStyleCast || CCK == Sema::CCK_FunctionalCast);
+  if (InitSeq.Failed() && (CStyle || !DestType->isReferenceType()))
+    return TC_NotApplicable;
+    
+  ExprResult Result
+    = InitSeq.Perform(Self, Entity, InitKind, MultiExprArg(Self, &SrcExprRaw, 1));
+  if (Result.isInvalid()) {
+    msg = 0;
+    return TC_Failed;
+  }
+  
+  if (InitSeq.isConstructorInitialization())
+    Kind = CK_ConstructorConversion;
+  else
+    Kind = CK_NoOp;
+  
+  SrcExpr = move(Result);
+  return TC_Success;
+}
+
+/// TryConstCast - See if a const_cast from source to destination is allowed,
+/// and perform it if it is.
+static TryCastResult TryConstCast(Sema &Self, Expr *SrcExpr, QualType DestType,
+                                  bool CStyle, unsigned &msg) {
+  DestType = Self.Context.getCanonicalType(DestType);
+  QualType SrcType = SrcExpr->getType();
+  if (const ReferenceType *DestTypeTmp =DestType->getAs<ReferenceType>()) {
+    if (DestTypeTmp->isLValueReferenceType() && !SrcExpr->isLValue()) {
+      // Cannot const_cast non-lvalue to lvalue reference type. But if this
+      // is C-style, static_cast might find a way, so we simply suggest a
+      // message and tell the parent to keep searching.
+      msg = diag::err_bad_cxx_cast_rvalue;
+      return TC_NotApplicable;
+    }
+
+    // C++ 5.2.11p4: An lvalue of type T1 can be [cast] to an lvalue of type T2
+    //   [...] if a pointer to T1 can be [cast] to the type pointer to T2.
+    DestType = Self.Context.getPointerType(DestTypeTmp->getPointeeType());
+    SrcType = Self.Context.getPointerType(SrcType);
+  }
+
+  // C++ 5.2.11p5: For a const_cast involving pointers to data members [...]
+  //   the rules for const_cast are the same as those used for pointers.
+
+  if (!DestType->isPointerType() &&
+      !DestType->isMemberPointerType() &&
+      !DestType->isObjCObjectPointerType()) {
+    // Cannot cast to non-pointer, non-reference type. Note that, if DestType
+    // was a reference type, we converted it to a pointer above.
+    // The status of rvalue references isn't entirely clear, but it looks like
+    // conversion to them is simply invalid.
+    // C++ 5.2.11p3: For two pointer types [...]
+    if (!CStyle)
+      msg = diag::err_bad_const_cast_dest;
+    return TC_NotApplicable;
+  }
+  if (DestType->isFunctionPointerType() ||
+      DestType->isMemberFunctionPointerType()) {
+    // Cannot cast direct function pointers.
+    // C++ 5.2.11p2: [...] where T is any object type or the void type [...]
+    // T is the ultimate pointee of source and target type.
+    if (!CStyle)
+      msg = diag::err_bad_const_cast_dest;
+    return TC_NotApplicable;
+  }
+  SrcType = Self.Context.getCanonicalType(SrcType);
+
+  // Unwrap the pointers. Ignore qualifiers. Terminate early if the types are
+  // completely equal.
+  // C++ 5.2.11p3 describes the core semantics of const_cast. All cv specifiers
+  // in multi-level pointers may change, but the level count must be the same,
+  // as must be the final pointee type.
+  while (SrcType != DestType &&
+         Self.Context.UnwrapSimilarPointerTypes(SrcType, DestType)) {
+    Qualifiers SrcQuals, DestQuals;
+    SrcType = Self.Context.getUnqualifiedArrayType(SrcType, SrcQuals);
+    DestType = Self.Context.getUnqualifiedArrayType(DestType, DestQuals);
+    
+    // const_cast is permitted to strip cvr-qualifiers, only. Make sure that
+    // the other qualifiers (e.g., address spaces) are identical.
+    SrcQuals.removeCVRQualifiers();
+    DestQuals.removeCVRQualifiers();
+    if (SrcQuals != DestQuals)
+      return TC_NotApplicable;
+  }
+
+  // Since we're dealing in canonical types, the remainder must be the same.
+  if (SrcType != DestType)
+    return TC_NotApplicable;
+
+  return TC_Success;
+}
+
+// Checks for undefined behavior in reinterpret_cast.
+// The cases that is checked for is:
+// *reinterpret_cast<T*>(&a)
+// reinterpret_cast<T&>(a)
+// where accessing 'a' as type 'T' will result in undefined behavior.
+void Sema::CheckCompatibleReinterpretCast(QualType SrcType, QualType DestType,
+                                          bool IsDereference,
+                                          SourceRange Range) {
+  unsigned DiagID = IsDereference ?
+                        diag::warn_pointer_indirection_from_incompatible_type :
+                        diag::warn_undefined_reinterpret_cast;
+
+  if (Diags.getDiagnosticLevel(DiagID, Range.getBegin()) ==
+          DiagnosticsEngine::Ignored) {
+    return;
+  }
+
+  QualType SrcTy, DestTy;
+  if (IsDereference) {
+    if (!SrcType->getAs<PointerType>() || !DestType->getAs<PointerType>()) {
+      return;
+    }
+    SrcTy = SrcType->getPointeeType();
+    DestTy = DestType->getPointeeType();
+  } else {
+    if (!DestType->getAs<ReferenceType>()) {
+      return;
+    }
+    SrcTy = SrcType;
+    DestTy = DestType->getPointeeType();
+  }
+
+  // Cast is compatible if the types are the same.
+  if (Context.hasSameUnqualifiedType(DestTy, SrcTy)) {
+    return;
+  }
+  // or one of the types is a char or void type
+  if (DestTy->isAnyCharacterType() || DestTy->isVoidType() ||
+      SrcTy->isAnyCharacterType() || SrcTy->isVoidType()) {
+    return;
+  }
+  // or one of the types is a tag type.
+  if (SrcTy->getAs<TagType>() || DestTy->getAs<TagType>()) {
+    return;
+  }
+
+  // FIXME: Scoped enums?
+  if ((SrcTy->isUnsignedIntegerType() && DestTy->isSignedIntegerType()) ||
+      (SrcTy->isSignedIntegerType() && DestTy->isUnsignedIntegerType())) {
+    if (Context.getTypeSize(DestTy) == Context.getTypeSize(SrcTy)) {
+      return;
+    }
+  }
+
+  Diag(Range.getBegin(), DiagID) << SrcType << DestType << Range;
+}
+
+static TryCastResult TryReinterpretCast(Sema &Self, ExprResult &SrcExpr,
+                                        QualType DestType, bool CStyle,
+                                        const SourceRange &OpRange,
+                                        unsigned &msg,
+                                        CastKind &Kind) {
+  bool IsLValueCast = false;
+  
+  DestType = Self.Context.getCanonicalType(DestType);
+  QualType SrcType = SrcExpr.get()->getType();
+
+  // Is the source an overloaded name? (i.e. &foo)
+  // If so, reinterpret_cast can not help us here (13.4, p1, bullet 5) ...
+  if (SrcType == Self.Context.OverloadTy) {
+    // ... unless foo<int> resolves to an lvalue unambiguously.
+    // TODO: what if this fails because of DiagnoseUseOfDecl or something
+    // like it?
+    ExprResult SingleFunctionExpr = SrcExpr;
+    if (Self.ResolveAndFixSingleFunctionTemplateSpecialization(
+          SingleFunctionExpr,
+          Expr::getValueKindForType(DestType) == VK_RValue // Convert Fun to Ptr 
+        ) && SingleFunctionExpr.isUsable()) {
+      SrcExpr = move(SingleFunctionExpr);
+      SrcType = SrcExpr.get()->getType();
+    } else {
+      return TC_NotApplicable;
+    }
+  }
+
+  if (const ReferenceType *DestTypeTmp = DestType->getAs<ReferenceType>()) {
+    bool LValue = DestTypeTmp->isLValueReferenceType();
+    if (LValue && !SrcExpr.get()->isLValue()) {
+      // Cannot cast non-lvalue to lvalue reference type. See the similar 
+      // comment in const_cast.
+      msg = diag::err_bad_cxx_cast_rvalue;
+      return TC_NotApplicable;
+    }
+
+    if (!CStyle) {
+      Self.CheckCompatibleReinterpretCast(SrcType, DestType,
+                                          /*isDereference=*/false, OpRange);
+    }
+
+    // C++ 5.2.10p10: [...] a reference cast reinterpret_cast<T&>(x) has the
+    //   same effect as the conversion *reinterpret_cast<T*>(&x) with the
+    //   built-in & and * operators.
+
+    const char *inappropriate = 0;
+    switch (SrcExpr.get()->getObjectKind()) {
+    case OK_Ordinary:
+      break;
+    case OK_BitField:        inappropriate = "bit-field";           break;
+    case OK_VectorComponent: inappropriate = "vector element";      break;
+    case OK_ObjCProperty:    inappropriate = "property expression"; break;
+    case OK_ObjCSubscript:   inappropriate = "container subscripting expression"; 
+                             break;
+    }
+    if (inappropriate) {
+      Self.Diag(OpRange.getBegin(), diag::err_bad_reinterpret_cast_reference)
+          << inappropriate << DestType
+          << OpRange << SrcExpr.get()->getSourceRange();
+      msg = 0; SrcExpr = ExprError();
+      return TC_NotApplicable;
+    }
+
+    // This code does this transformation for the checked types.
+    DestType = Self.Context.getPointerType(DestTypeTmp->getPointeeType());
+    SrcType = Self.Context.getPointerType(SrcType);
+    
+    IsLValueCast = true;
+  }
+
+  // Canonicalize source for comparison.
+  SrcType = Self.Context.getCanonicalType(SrcType);
+
+  const MemberPointerType *DestMemPtr = DestType->getAs<MemberPointerType>(),
+                          *SrcMemPtr = SrcType->getAs<MemberPointerType>();
+  if (DestMemPtr && SrcMemPtr) {
+    // C++ 5.2.10p9: An rvalue of type "pointer to member of X of type T1"
+    //   can be explicitly converted to an rvalue of type "pointer to member
+    //   of Y of type T2" if T1 and T2 are both function types or both object
+    //   types.
+    if (DestMemPtr->getPointeeType()->isFunctionType() !=
+        SrcMemPtr->getPointeeType()->isFunctionType())
+      return TC_NotApplicable;
+
+    // C++ 5.2.10p2: The reinterpret_cast operator shall not cast away
+    //   constness.
+    // A reinterpret_cast followed by a const_cast can, though, so in C-style,
+    // we accept it.
+    if (CastsAwayConstness(Self, SrcType, DestType, /*CheckCVR=*/!CStyle,
+                           /*CheckObjCLifetime=*/CStyle)) {
+      msg = diag::err_bad_cxx_cast_qualifiers_away;
+      return TC_Failed;
+    }
+
+    // Don't allow casting between member pointers of different sizes.
+    if (Self.Context.getTypeSize(DestMemPtr) !=
+        Self.Context.getTypeSize(SrcMemPtr)) {
+      msg = diag::err_bad_cxx_cast_member_pointer_size;
+      return TC_Failed;
+    }
+
+    // A valid member pointer cast.
+    assert(!IsLValueCast);
+    Kind = CK_ReinterpretMemberPointer;
+    return TC_Success;
+  }
+
+  // See below for the enumeral issue.
+  if (SrcType->isNullPtrType() && DestType->isIntegralType(Self.Context)) {
+    // C++0x 5.2.10p4: A pointer can be explicitly converted to any integral
+    //   type large enough to hold it. A value of std::nullptr_t can be
+    //   converted to an integral type; the conversion has the same meaning
+    //   and validity as a conversion of (void*)0 to the integral type.
+    if (Self.Context.getTypeSize(SrcType) >
+        Self.Context.getTypeSize(DestType)) {
+      msg = diag::err_bad_reinterpret_cast_small_int;
+      return TC_Failed;
+    }
+    Kind = CK_PointerToIntegral;
+    return TC_Success;
+  }
+
+  bool destIsVector = DestType->isVectorType();
+  bool srcIsVector = SrcType->isVectorType();
+  if (srcIsVector || destIsVector) {
+    // FIXME: Should this also apply to floating point types?
+    bool srcIsScalar = SrcType->isIntegralType(Self.Context);
+    bool destIsScalar = DestType->isIntegralType(Self.Context);
+    
+    // Check if this is a cast between a vector and something else.
+    if (!(srcIsScalar && destIsVector) && !(srcIsVector && destIsScalar) &&
+        !(srcIsVector && destIsVector))
+      return TC_NotApplicable;
+
+    // If both types have the same size, we can successfully cast.
+    if (Self.Context.getTypeSize(SrcType)
+          == Self.Context.getTypeSize(DestType)) {
+      Kind = CK_BitCast;
+      return TC_Success;
+    }
+    
+    if (destIsScalar)
+      msg = diag::err_bad_cxx_cast_vector_to_scalar_different_size;
+    else if (srcIsScalar)
+      msg = diag::err_bad_cxx_cast_scalar_to_vector_different_size;
+    else
+      msg = diag::err_bad_cxx_cast_vector_to_vector_different_size;
+    
+    return TC_Failed;
+  }
+
+  if (SrcType == DestType) {
+    // C++ 5.2.10p2 has a note that mentions that, subject to all other
+    // restrictions, a cast to the same type is allowed so long as it does not
+    // cast away constness. In C++98, the intent was not entirely clear here, 
+    // since all other paragraphs explicitly forbid casts to the same type.
+    // C++11 clarifies this case with p2.
+    //
+    // The only allowed types are: integral, enumeration, pointer, or 
+    // pointer-to-member types.  We also won't restrict Obj-C pointers either.
+    Kind = CK_NoOp;
+    TryCastResult Result = TC_NotApplicable;
+    if (SrcType->isIntegralOrEnumerationType() ||
+        SrcType->isAnyPointerType() ||
+        SrcType->isMemberPointerType() ||
+        SrcType->isBlockPointerType()) {
+      Result = TC_Success;
+    }
+    return Result;
+  }
+
+  bool destIsPtr = DestType->isAnyPointerType() ||
+                   DestType->isBlockPointerType();
+  bool srcIsPtr = SrcType->isAnyPointerType() ||
+                  SrcType->isBlockPointerType();
+  if (!destIsPtr && !srcIsPtr) {
+    // Except for std::nullptr_t->integer and lvalue->reference, which are
+    // handled above, at least one of the two arguments must be a pointer.
+    return TC_NotApplicable;
+  }
+
+  if (DestType->isIntegralType(Self.Context)) {
+    assert(srcIsPtr && "One type must be a pointer");
+    // C++ 5.2.10p4: A pointer can be explicitly converted to any integral
+    //   type large enough to hold it; except in Microsoft mode, where the
+    //   integral type size doesn't matter.
+    if ((Self.Context.getTypeSize(SrcType) >
+         Self.Context.getTypeSize(DestType)) &&
+         !Self.getLangOpts().MicrosoftExt) {
+      msg = diag::err_bad_reinterpret_cast_small_int;
+      return TC_Failed;
+    }
+    Kind = CK_PointerToIntegral;
+    return TC_Success;
+  }
+
+  if (SrcType->isIntegralOrEnumerationType()) {
+    assert(destIsPtr && "One type must be a pointer");
+    // C++ 5.2.10p5: A value of integral or enumeration type can be explicitly
+    //   converted to a pointer.
+    // C++ 5.2.10p9: [Note: ...a null pointer constant of integral type is not
+    //   necessarily converted to a null pointer value.]
+    Kind = CK_IntegralToPointer;
+    return TC_Success;
+  }
+
+  if (!destIsPtr || !srcIsPtr) {
+    // With the valid non-pointer conversions out of the way, we can be even
+    // more stringent.
+    return TC_NotApplicable;
+  }
+
+  // C++ 5.2.10p2: The reinterpret_cast operator shall not cast away constness.
+  // The C-style cast operator can.
+  if (CastsAwayConstness(Self, SrcType, DestType, /*CheckCVR=*/!CStyle,
+                         /*CheckObjCLifetime=*/CStyle)) {
+    msg = diag::err_bad_cxx_cast_qualifiers_away;
+    return TC_Failed;
+  }
+  
+  // Cannot convert between block pointers and Objective-C object pointers.
+  if ((SrcType->isBlockPointerType() && DestType->isObjCObjectPointerType()) ||
+      (DestType->isBlockPointerType() && SrcType->isObjCObjectPointerType()))
+    return TC_NotApplicable;
+
+  if (IsLValueCast) {
+    Kind = CK_LValueBitCast;
+  } else if (DestType->isObjCObjectPointerType()) {
+    Kind = Self.PrepareCastToObjCObjectPointer(SrcExpr);
+  } else if (DestType->isBlockPointerType()) {
+    if (!SrcType->isBlockPointerType()) {
+      Kind = CK_AnyPointerToBlockPointerCast;
+    } else {
+      Kind = CK_BitCast;
+    }
+  } else {
+    Kind = CK_BitCast;
+  }
+
+  // Any pointer can be cast to an Objective-C pointer type with a C-style
+  // cast.
+  if (CStyle && DestType->isObjCObjectPointerType()) {
+    return TC_Success;
+  }
+    
+  // Not casting away constness, so the only remaining check is for compatible
+  // pointer categories.
+
+  if (SrcType->isFunctionPointerType()) {
+    if (DestType->isFunctionPointerType()) {
+      // C++ 5.2.10p6: A pointer to a function can be explicitly converted to
+      // a pointer to a function of a different type.
+      return TC_Success;
+    }
+
+    // C++0x 5.2.10p8: Converting a pointer to a function into a pointer to
+    //   an object type or vice versa is conditionally-supported.
+    // Compilers support it in C++03 too, though, because it's necessary for
+    // casting the return value of dlsym() and GetProcAddress().
+    // FIXME: Conditionally-supported behavior should be configurable in the
+    // TargetInfo or similar.
+    Self.Diag(OpRange.getBegin(),
+              Self.getLangOpts().CPlusPlus0x ?
+                diag::warn_cxx98_compat_cast_fn_obj : diag::ext_cast_fn_obj)
+      << OpRange;
+    return TC_Success;
+  }
+
+  if (DestType->isFunctionPointerType()) {
+    // See above.
+    Self.Diag(OpRange.getBegin(),
+              Self.getLangOpts().CPlusPlus0x ?
+                diag::warn_cxx98_compat_cast_fn_obj : diag::ext_cast_fn_obj)
+      << OpRange;
+    return TC_Success;
+  }
+  
+  // C++ 5.2.10p7: A pointer to an object can be explicitly converted to
+  //   a pointer to an object of different type.
+  // Void pointers are not specified, but supported by every compiler out there.
+  // So we finish by allowing everything that remains - it's got to be two
+  // object pointers.
+  return TC_Success;
+}                                     
+
+void CastOperation::CheckCXXCStyleCast(bool FunctionalStyle,
+                                       bool ListInitialization) {
+  // Handle placeholders.
+  if (isPlaceholder()) {
+    // C-style casts can resolve __unknown_any types.
+    if (claimPlaceholder(BuiltinType::UnknownAny)) {
+      SrcExpr = Self.checkUnknownAnyCast(DestRange, DestType,
+                                         SrcExpr.get(), Kind,
+                                         ValueKind, BasePath);
+      return;
+    }
+
+    checkNonOverloadPlaceholders();
+    if (SrcExpr.isInvalid())
+      return;
+  }
+
+  // C++ 5.2.9p4: Any expression can be explicitly converted to type "cv void".
+  // This test is outside everything else because it's the only case where
+  // a non-lvalue-reference target type does not lead to decay.
+  if (DestType->isVoidType()) {
+    Kind = CK_ToVoid;
+
+    if (claimPlaceholder(BuiltinType::Overload)) {
+      Self.ResolveAndFixSingleFunctionTemplateSpecialization(
+                  SrcExpr, /* Decay Function to ptr */ false, 
+                  /* Complain */ true, DestRange, DestType,
+                  diag::err_bad_cstyle_cast_overload);
+      if (SrcExpr.isInvalid())
+        return;
+    }
+
+    SrcExpr = Self.IgnoredValueConversions(SrcExpr.take());
+    if (SrcExpr.isInvalid())
+      return;
+
+    return;
+  }
+
+  // If the type is dependent, we won't do any other semantic analysis now.
+  if (DestType->isDependentType() || SrcExpr.get()->isTypeDependent()) {
+    assert(Kind == CK_Dependent);
+    return;
+  }
+
+  if (ValueKind == VK_RValue && !DestType->isRecordType() &&
+      !isPlaceholder(BuiltinType::Overload)) {
+    SrcExpr = Self.DefaultFunctionArrayLvalueConversion(SrcExpr.take());
+    if (SrcExpr.isInvalid())
+      return;
+  }
+
+  // AltiVec vector initialization with a single literal.
+  if (const VectorType *vecTy = DestType->getAs<VectorType>())
+    if (vecTy->getVectorKind() == VectorType::AltiVecVector
+        && (SrcExpr.get()->getType()->isIntegerType()
+            || SrcExpr.get()->getType()->isFloatingType())) {
+      Kind = CK_VectorSplat;
+      return;
+    }
+
+  // C++ [expr.cast]p5: The conversions performed by
+  //   - a const_cast,
+  //   - a static_cast,
+  //   - a static_cast followed by a const_cast,
+  //   - a reinterpret_cast, or
+  //   - a reinterpret_cast followed by a const_cast,
+  //   can be performed using the cast notation of explicit type conversion.
+  //   [...] If a conversion can be interpreted in more than one of the ways
+  //   listed above, the interpretation that appears first in the list is used,
+  //   even if a cast resulting from that interpretation is ill-formed.
+  // In plain language, this means trying a const_cast ...
+  unsigned msg = diag::err_bad_cxx_cast_generic;
+  TryCastResult tcr = TryConstCast(Self, SrcExpr.get(), DestType,
+                                   /*CStyle*/true, msg);
+  if (tcr == TC_Success)
+    Kind = CK_NoOp;
+
+  Sema::CheckedConversionKind CCK
+    = FunctionalStyle? Sema::CCK_FunctionalCast
+                     : Sema::CCK_CStyleCast;
+  if (tcr == TC_NotApplicable) {
+    // ... or if that is not possible, a static_cast, ignoring const, ...
+    tcr = TryStaticCast(Self, SrcExpr, DestType, CCK, OpRange,
+                        msg, Kind, BasePath, ListInitialization);
+    if (SrcExpr.isInvalid())
+      return;
+
+    if (tcr == TC_NotApplicable) {
+      // ... and finally a reinterpret_cast, ignoring const.
+      tcr = TryReinterpretCast(Self, SrcExpr, DestType, /*CStyle*/true,
+                               OpRange, msg, Kind);
+      if (SrcExpr.isInvalid())
+        return;
+    }
+  }
+
+  if (Self.getLangOpts().ObjCAutoRefCount && tcr == TC_Success)
+    checkObjCARCConversion(CCK);
+
+  if (tcr != TC_Success && msg != 0) {
+    if (SrcExpr.get()->getType() == Self.Context.OverloadTy) {
+      DeclAccessPair Found;
+      FunctionDecl *Fn = Self.ResolveAddressOfOverloadedFunction(SrcExpr.get(),
+                                DestType,
+                                /*Complain*/ true,
+                                Found);
+      
+      assert(!Fn && "cast failed but able to resolve overload expression!!");
+      (void)Fn;
+
+    } else {
+      diagnoseBadCast(Self, msg, (FunctionalStyle ? CT_Functional : CT_CStyle),
+                      OpRange, SrcExpr.get(), DestType, ListInitialization);
+    }
+  } else if (Kind == CK_BitCast) {
+    checkCastAlign();
+  }
+
+  // Clear out SrcExpr if there was a fatal error.
+  if (tcr != TC_Success)
+    SrcExpr = ExprError();
+}
+
+/// Check the semantics of a C-style cast operation, in C.
+void CastOperation::CheckCStyleCast() {
+  assert(!Self.getLangOpts().CPlusPlus);
+
+  // C-style casts can resolve __unknown_any types.
+  if (claimPlaceholder(BuiltinType::UnknownAny)) {
+    SrcExpr = Self.checkUnknownAnyCast(DestRange, DestType,
+                                       SrcExpr.get(), Kind,
+                                       ValueKind, BasePath);
+    return;
+  }
+
+  // C99 6.5.4p2: the cast type needs to be void or scalar and the expression
+  // type needs to be scalar.
+  if (DestType->isVoidType()) {
+    // We don't necessarily do lvalue-to-rvalue conversions on this.
+    SrcExpr = Self.IgnoredValueConversions(SrcExpr.take());
+    if (SrcExpr.isInvalid())
+      return;
+
+    // Cast to void allows any expr type.
+    Kind = CK_ToVoid;
+    return;
+  }
+
+  SrcExpr = Self.DefaultFunctionArrayLvalueConversion(SrcExpr.take());
+  if (SrcExpr.isInvalid())
+    return;
+  QualType SrcType = SrcExpr.get()->getType();
+
+  // You can cast an _Atomic(T) to anything you can cast a T to.
+  if (const AtomicType *AtomicSrcType = SrcType->getAs<AtomicType>())
+    SrcType = AtomicSrcType->getValueType();
+
+  assert(!SrcType->isPlaceholderType());
+
+  if (Self.RequireCompleteType(OpRange.getBegin(), DestType,
+                               diag::err_typecheck_cast_to_incomplete)) {
+    SrcExpr = ExprError();
+    return;
+  }
+
+  if (!DestType->isScalarType() && !DestType->isVectorType()) {
+    const RecordType *DestRecordTy = DestType->getAs<RecordType>();
+
+    if (DestRecordTy && Self.Context.hasSameUnqualifiedType(DestType, SrcType)){
+      // GCC struct/union extension: allow cast to self.
+      Self.Diag(OpRange.getBegin(), diag::ext_typecheck_cast_nonscalar)
+        << DestType << SrcExpr.get()->getSourceRange();
+      Kind = CK_NoOp;
+      return;
+    }
+
+    // GCC's cast to union extension.
+    if (DestRecordTy && DestRecordTy->getDecl()->isUnion()) {
+      RecordDecl *RD = DestRecordTy->getDecl();
+      RecordDecl::field_iterator Field, FieldEnd;
+      for (Field = RD->field_begin(), FieldEnd = RD->field_end();
+           Field != FieldEnd; ++Field) {
+        if (Self.Context.hasSameUnqualifiedType(Field->getType(), SrcType) &&
+            !Field->isUnnamedBitfield()) {
+          Self.Diag(OpRange.getBegin(), diag::ext_typecheck_cast_to_union)
+            << SrcExpr.get()->getSourceRange();
+          break;
+        }
+      }
+      if (Field == FieldEnd) {
+        Self.Diag(OpRange.getBegin(), diag::err_typecheck_cast_to_union_no_type)
+          << SrcType << SrcExpr.get()->getSourceRange();
+        SrcExpr = ExprError();
+        return;
+      }
+      Kind = CK_ToUnion;
+      return;
+    }
+
+    // Reject any other conversions to non-scalar types.
+    Self.Diag(OpRange.getBegin(), diag::err_typecheck_cond_expect_scalar)
+      << DestType << SrcExpr.get()->getSourceRange();
+    SrcExpr = ExprError();
+    return;
+  }
+
+  // The type we're casting to is known to be a scalar or vector.
+
+  // Require the operand to be a scalar or vector.
+  if (!SrcType->isScalarType() && !SrcType->isVectorType()) {
+    Self.Diag(SrcExpr.get()->getExprLoc(),
+              diag::err_typecheck_expect_scalar_operand)
+      << SrcType << SrcExpr.get()->getSourceRange();
+    SrcExpr = ExprError();
+    return;
+  }
+
+  if (DestType->isExtVectorType()) {
+    SrcExpr = Self.CheckExtVectorCast(OpRange, DestType, SrcExpr.take(), Kind);
+    return;
+  }
+
+  if (const VectorType *DestVecTy = DestType->getAs<VectorType>()) {
+    if (DestVecTy->getVectorKind() == VectorType::AltiVecVector &&
+          (SrcType->isIntegerType() || SrcType->isFloatingType())) {
+      Kind = CK_VectorSplat;
+    } else if (Self.CheckVectorCast(OpRange, DestType, SrcType, Kind)) {
+      SrcExpr = ExprError();
+    }
+    return;
+  }
+
+  if (SrcType->isVectorType()) {
+    if (Self.CheckVectorCast(OpRange, SrcType, DestType, Kind))
+      SrcExpr = ExprError();
+    return;
+  }
+
+  // The source and target types are both scalars, i.e.
+  //   - arithmetic types (fundamental, enum, and complex)
+  //   - all kinds of pointers
+  // Note that member pointers were filtered out with C++, above.
+
+  if (isa<ObjCSelectorExpr>(SrcExpr.get())) {
+    Self.Diag(SrcExpr.get()->getExprLoc(), diag::err_cast_selector_expr);
+    SrcExpr = ExprError();
+    return;
+  }
+
+  // If either type is a pointer, the other type has to be either an
+  // integer or a pointer.
+  if (!DestType->isArithmeticType()) {
+    if (!SrcType->isIntegralType(Self.Context) && SrcType->isArithmeticType()) {
+      Self.Diag(SrcExpr.get()->getExprLoc(),
+                diag::err_cast_pointer_from_non_pointer_int)
+        << SrcType << SrcExpr.get()->getSourceRange();
+      SrcExpr = ExprError();
+      return;
+    }
+  } else if (!SrcType->isArithmeticType()) {
+    if (!DestType->isIntegralType(Self.Context) &&
+        DestType->isArithmeticType()) {
+      Self.Diag(SrcExpr.get()->getLocStart(),
+           diag::err_cast_pointer_to_non_pointer_int)
+        << DestType << SrcExpr.get()->getSourceRange();
+      SrcExpr = ExprError();
+      return;
+    }
+  }
+
+  // ARC imposes extra restrictions on casts.
+  if (Self.getLangOpts().ObjCAutoRefCount) {
+    checkObjCARCConversion(Sema::CCK_CStyleCast);
+    if (SrcExpr.isInvalid())
+      return;
+    
+    if (const PointerType *CastPtr = DestType->getAs<PointerType>()) {
+      if (const PointerType *ExprPtr = SrcType->getAs<PointerType>()) {
+        Qualifiers CastQuals = CastPtr->getPointeeType().getQualifiers();
+        Qualifiers ExprQuals = ExprPtr->getPointeeType().getQualifiers();
+        if (CastPtr->getPointeeType()->isObjCLifetimeType() && 
+            ExprPtr->getPointeeType()->isObjCLifetimeType() &&
+            !CastQuals.compatiblyIncludesObjCLifetime(ExprQuals)) {
+          Self.Diag(SrcExpr.get()->getLocStart(), 
+                    diag::err_typecheck_incompatible_ownership)
+            << SrcType << DestType << Sema::AA_Casting
+            << SrcExpr.get()->getSourceRange();
+          return;
+        }
+      }
+    } 
+    else if (!Self.CheckObjCARCUnavailableWeakConversion(DestType, SrcType)) {
+      Self.Diag(SrcExpr.get()->getLocStart(), 
+                diag::err_arc_convesion_of_weak_unavailable)
+        << 1 << SrcType << DestType << SrcExpr.get()->getSourceRange();
+      SrcExpr = ExprError();
+      return;
+    }
+  }
+  
+  Kind = Self.PrepareScalarCast(SrcExpr, DestType);
+  if (SrcExpr.isInvalid())
+    return;
+
+  if (Kind == CK_BitCast)
+    checkCastAlign();
+}
+
+ExprResult Sema::BuildCStyleCastExpr(SourceLocation LPLoc,
+                                     TypeSourceInfo *CastTypeInfo,
+                                     SourceLocation RPLoc,
+                                     Expr *CastExpr) {
+  CastOperation Op(*this, CastTypeInfo->getType(), CastExpr);  
+  Op.DestRange = CastTypeInfo->getTypeLoc().getSourceRange();
+  Op.OpRange = SourceRange(LPLoc, CastExpr->getLocEnd());
+
+  if (getLangOpts().CPlusPlus) {
+    Op.CheckCXXCStyleCast(/*FunctionalStyle=*/ false,
+                          isa<InitListExpr>(CastExpr));
+  } else {
+    Op.CheckCStyleCast();
+  }
+
+  if (Op.SrcExpr.isInvalid())
+    return ExprError();
+
+  return Op.complete(CStyleCastExpr::Create(Context, Op.ResultType,
+                              Op.ValueKind, Op.Kind, Op.SrcExpr.take(),
+                              &Op.BasePath, CastTypeInfo, LPLoc, RPLoc));
+}
+
+ExprResult Sema::BuildCXXFunctionalCastExpr(TypeSourceInfo *CastTypeInfo,
+                                            SourceLocation LPLoc,
+                                            Expr *CastExpr,
+                                            SourceLocation RPLoc) {
+  assert(LPLoc.isValid() && "List-initialization shouldn't get here.");
+  CastOperation Op(*this, CastTypeInfo->getType(), CastExpr);
+  Op.DestRange = CastTypeInfo->getTypeLoc().getSourceRange();
+  Op.OpRange = SourceRange(Op.DestRange.getBegin(), CastExpr->getLocEnd());
+
+  Op.CheckCXXCStyleCast(/*FunctionalStyle=*/true, /*ListInit=*/false);
+  if (Op.SrcExpr.isInvalid())
+    return ExprError();
+
+  return Op.complete(CXXFunctionalCastExpr::Create(Context, Op.ResultType,
+                         Op.ValueKind, CastTypeInfo, Op.DestRange.getBegin(),
+                         Op.Kind, Op.SrcExpr.take(), &Op.BasePath, RPLoc));
+}
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
new file mode 100644
index 0000000..0d15ce2
--- /dev/null
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -0,0 +1,5153 @@
+//===--- SemaChecking.cpp - Extra Semantic Checking -----------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+//  This file implements extra semantic analysis beyond what is enforced
+//  by the C type system.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Sema/Initialization.h"
+#include "clang/Sema/Sema.h"
+#include "clang/Sema/SemaInternal.h"
+#include "clang/Sema/Initialization.h"
+#include "clang/Sema/ScopeInfo.h"
+#include "clang/Analysis/Analyses/FormatString.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/CharUnits.h"
+#include "clang/AST/DeclCXX.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/AST/ExprCXX.h"
+#include "clang/AST/ExprObjC.h"
+#include "clang/AST/EvaluatedExprVisitor.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/AST/StmtCXX.h"
+#include "clang/AST/StmtObjC.h"
+#include "clang/Lex/Preprocessor.h"
+#include "llvm/ADT/BitVector.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/Support/raw_ostream.h"
+#include "clang/Basic/TargetBuiltins.h"
+#include "clang/Basic/TargetInfo.h"
+#include "clang/Basic/ConvertUTF.h"
+#include <limits>
+using namespace clang;
+using namespace sema;
+
+SourceLocation Sema::getLocationOfStringLiteralByte(const StringLiteral *SL,
+                                                    unsigned ByteNo) const {
+  return SL->getLocationOfByte(ByteNo, PP.getSourceManager(),
+                               PP.getLangOpts(), PP.getTargetInfo());
+}
+
+/// Checks that a call expression's argument count is the desired number.
+/// This is useful when doing custom type-checking.  Returns true on error.
+static bool checkArgCount(Sema &S, CallExpr *call, unsigned desiredArgCount) {
+  unsigned argCount = call->getNumArgs();
+  if (argCount == desiredArgCount) return false;
+
+  if (argCount < desiredArgCount)
+    return S.Diag(call->getLocEnd(), diag::err_typecheck_call_too_few_args)
+        << 0 /*function call*/ << desiredArgCount << argCount
+        << call->getSourceRange();
+
+  // Highlight all the excess arguments.
+  SourceRange range(call->getArg(desiredArgCount)->getLocStart(),
+                    call->getArg(argCount - 1)->getLocEnd());
+    
+  return S.Diag(range.getBegin(), diag::err_typecheck_call_too_many_args)
+    << 0 /*function call*/ << desiredArgCount << argCount
+    << call->getArg(1)->getSourceRange();
+}
+
+/// CheckBuiltinAnnotationString - Checks that string argument to the builtin
+/// annotation is a non wide string literal.
+static bool CheckBuiltinAnnotationString(Sema &S, Expr *Arg) {
+  Arg = Arg->IgnoreParenCasts();
+  StringLiteral *Literal = dyn_cast<StringLiteral>(Arg);
+  if (!Literal || !Literal->isAscii()) {
+    S.Diag(Arg->getLocStart(), diag::err_builtin_annotation_not_string_constant)
+      << Arg->getSourceRange();
+    return true;
+  }
+  return false;
+}
+
+ExprResult
+Sema::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
+  ExprResult TheCallResult(Owned(TheCall));
+
+  // Find out if any arguments are required to be integer constant expressions.
+  unsigned ICEArguments = 0;
+  ASTContext::GetBuiltinTypeError Error;
+  Context.GetBuiltinType(BuiltinID, Error, &ICEArguments);
+  if (Error != ASTContext::GE_None)
+    ICEArguments = 0;  // Don't diagnose previously diagnosed errors.
+  
+  // If any arguments are required to be ICE's, check and diagnose.
+  for (unsigned ArgNo = 0; ICEArguments != 0; ++ArgNo) {
+    // Skip arguments not required to be ICE's.
+    if ((ICEArguments & (1 << ArgNo)) == 0) continue;
+    
+    llvm::APSInt Result;
+    if (SemaBuiltinConstantArg(TheCall, ArgNo, Result))
+      return true;
+    ICEArguments &= ~(1 << ArgNo);
+  }
+  
+  switch (BuiltinID) {
+  case Builtin::BI__builtin___CFStringMakeConstantString:
+    assert(TheCall->getNumArgs() == 1 &&
+           "Wrong # arguments to builtin CFStringMakeConstantString");
+    if (CheckObjCString(TheCall->getArg(0)))
+      return ExprError();
+    break;
+  case Builtin::BI__builtin_stdarg_start:
+  case Builtin::BI__builtin_va_start:
+    if (SemaBuiltinVAStart(TheCall))
+      return ExprError();
+    break;
+  case Builtin::BI__builtin_isgreater:
+  case Builtin::BI__builtin_isgreaterequal:
+  case Builtin::BI__builtin_isless:
+  case Builtin::BI__builtin_islessequal:
+  case Builtin::BI__builtin_islessgreater:
+  case Builtin::BI__builtin_isunordered:
+    if (SemaBuiltinUnorderedCompare(TheCall))
+      return ExprError();
+    break;
+  case Builtin::BI__builtin_fpclassify:
+    if (SemaBuiltinFPClassification(TheCall, 6))
+      return ExprError();
+    break;
+  case Builtin::BI__builtin_isfinite:
+  case Builtin::BI__builtin_isinf:
+  case Builtin::BI__builtin_isinf_sign:
+  case Builtin::BI__builtin_isnan:
+  case Builtin::BI__builtin_isnormal:
+    if (SemaBuiltinFPClassification(TheCall, 1))
+      return ExprError();
+    break;
+  case Builtin::BI__builtin_shufflevector:
+    return SemaBuiltinShuffleVector(TheCall);
+    // TheCall will be freed by the smart pointer here, but that's fine, since
+    // SemaBuiltinShuffleVector guts it, but then doesn't release it.
+  case Builtin::BI__builtin_prefetch:
+    if (SemaBuiltinPrefetch(TheCall))
+      return ExprError();
+    break;
+  case Builtin::BI__builtin_object_size:
+    if (SemaBuiltinObjectSize(TheCall))
+      return ExprError();
+    break;
+  case Builtin::BI__builtin_longjmp:
+    if (SemaBuiltinLongjmp(TheCall))
+      return ExprError();
+    break;
+
+  case Builtin::BI__builtin_classify_type:
+    if (checkArgCount(*this, TheCall, 1)) return true;
+    TheCall->setType(Context.IntTy);
+    break;
+  case Builtin::BI__builtin_constant_p:
+    if (checkArgCount(*this, TheCall, 1)) return true;
+    TheCall->setType(Context.IntTy);
+    break;
+  case Builtin::BI__sync_fetch_and_add:
+  case Builtin::BI__sync_fetch_and_add_1:
+  case Builtin::BI__sync_fetch_and_add_2:
+  case Builtin::BI__sync_fetch_and_add_4:
+  case Builtin::BI__sync_fetch_and_add_8:
+  case Builtin::BI__sync_fetch_and_add_16:
+  case Builtin::BI__sync_fetch_and_sub:
+  case Builtin::BI__sync_fetch_and_sub_1:
+  case Builtin::BI__sync_fetch_and_sub_2:
+  case Builtin::BI__sync_fetch_and_sub_4:
+  case Builtin::BI__sync_fetch_and_sub_8:
+  case Builtin::BI__sync_fetch_and_sub_16:
+  case Builtin::BI__sync_fetch_and_or:
+  case Builtin::BI__sync_fetch_and_or_1:
+  case Builtin::BI__sync_fetch_and_or_2:
+  case Builtin::BI__sync_fetch_and_or_4:
+  case Builtin::BI__sync_fetch_and_or_8:
+  case Builtin::BI__sync_fetch_and_or_16:
+  case Builtin::BI__sync_fetch_and_and:
+  case Builtin::BI__sync_fetch_and_and_1:
+  case Builtin::BI__sync_fetch_and_and_2:
+  case Builtin::BI__sync_fetch_and_and_4:
+  case Builtin::BI__sync_fetch_and_and_8:
+  case Builtin::BI__sync_fetch_and_and_16:
+  case Builtin::BI__sync_fetch_and_xor:
+  case Builtin::BI__sync_fetch_and_xor_1:
+  case Builtin::BI__sync_fetch_and_xor_2:
+  case Builtin::BI__sync_fetch_and_xor_4:
+  case Builtin::BI__sync_fetch_and_xor_8:
+  case Builtin::BI__sync_fetch_and_xor_16:
+  case Builtin::BI__sync_add_and_fetch:
+  case Builtin::BI__sync_add_and_fetch_1:
+  case Builtin::BI__sync_add_and_fetch_2:
+  case Builtin::BI__sync_add_and_fetch_4:
+  case Builtin::BI__sync_add_and_fetch_8:
+  case Builtin::BI__sync_add_and_fetch_16:
+  case Builtin::BI__sync_sub_and_fetch:
+  case Builtin::BI__sync_sub_and_fetch_1:
+  case Builtin::BI__sync_sub_and_fetch_2:
+  case Builtin::BI__sync_sub_and_fetch_4:
+  case Builtin::BI__sync_sub_and_fetch_8:
+  case Builtin::BI__sync_sub_and_fetch_16:
+  case Builtin::BI__sync_and_and_fetch:
+  case Builtin::BI__sync_and_and_fetch_1:
+  case Builtin::BI__sync_and_and_fetch_2:
+  case Builtin::BI__sync_and_and_fetch_4:
+  case Builtin::BI__sync_and_and_fetch_8:
+  case Builtin::BI__sync_and_and_fetch_16:
+  case Builtin::BI__sync_or_and_fetch:
+  case Builtin::BI__sync_or_and_fetch_1:
+  case Builtin::BI__sync_or_and_fetch_2:
+  case Builtin::BI__sync_or_and_fetch_4:
+  case Builtin::BI__sync_or_and_fetch_8:
+  case Builtin::BI__sync_or_and_fetch_16:
+  case Builtin::BI__sync_xor_and_fetch:
+  case Builtin::BI__sync_xor_and_fetch_1:
+  case Builtin::BI__sync_xor_and_fetch_2:
+  case Builtin::BI__sync_xor_and_fetch_4:
+  case Builtin::BI__sync_xor_and_fetch_8:
+  case Builtin::BI__sync_xor_and_fetch_16:
+  case Builtin::BI__sync_val_compare_and_swap:
+  case Builtin::BI__sync_val_compare_and_swap_1:
+  case Builtin::BI__sync_val_compare_and_swap_2:
+  case Builtin::BI__sync_val_compare_and_swap_4:
+  case Builtin::BI__sync_val_compare_and_swap_8:
+  case Builtin::BI__sync_val_compare_and_swap_16:
+  case Builtin::BI__sync_bool_compare_and_swap:
+  case Builtin::BI__sync_bool_compare_and_swap_1:
+  case Builtin::BI__sync_bool_compare_and_swap_2:
+  case Builtin::BI__sync_bool_compare_and_swap_4:
+  case Builtin::BI__sync_bool_compare_and_swap_8:
+  case Builtin::BI__sync_bool_compare_and_swap_16:
+  case Builtin::BI__sync_lock_test_and_set:
+  case Builtin::BI__sync_lock_test_and_set_1:
+  case Builtin::BI__sync_lock_test_and_set_2:
+  case Builtin::BI__sync_lock_test_and_set_4:
+  case Builtin::BI__sync_lock_test_and_set_8:
+  case Builtin::BI__sync_lock_test_and_set_16:
+  case Builtin::BI__sync_lock_release:
+  case Builtin::BI__sync_lock_release_1:
+  case Builtin::BI__sync_lock_release_2:
+  case Builtin::BI__sync_lock_release_4:
+  case Builtin::BI__sync_lock_release_8:
+  case Builtin::BI__sync_lock_release_16:
+  case Builtin::BI__sync_swap:
+  case Builtin::BI__sync_swap_1:
+  case Builtin::BI__sync_swap_2:
+  case Builtin::BI__sync_swap_4:
+  case Builtin::BI__sync_swap_8:
+  case Builtin::BI__sync_swap_16:
+    return SemaBuiltinAtomicOverloaded(move(TheCallResult));
+#define BUILTIN(ID, TYPE, ATTRS)
+#define ATOMIC_BUILTIN(ID, TYPE, ATTRS) \
+  case Builtin::BI##ID: \
+    return SemaAtomicOpsOverloaded(move(TheCallResult), AtomicExpr::AO##ID);
+#include "clang/Basic/Builtins.def"
+  case Builtin::BI__builtin_annotation:
+    if (CheckBuiltinAnnotationString(*this, TheCall->getArg(1)))
+      return ExprError();
+    break;
+  }
+  
+  // Since the target specific builtins for each arch overlap, only check those
+  // of the arch we are compiling for.
+  if (BuiltinID >= Builtin::FirstTSBuiltin) {
+    switch (Context.getTargetInfo().getTriple().getArch()) {
+      case llvm::Triple::arm:
+      case llvm::Triple::thumb:
+        if (CheckARMBuiltinFunctionCall(BuiltinID, TheCall))
+          return ExprError();
+        break;
+      default:
+        break;
+    }
+  }
+
+  return move(TheCallResult);
+}
+
+// Get the valid immediate range for the specified NEON type code.
+static unsigned RFT(unsigned t, bool shift = false) {
+  NeonTypeFlags Type(t);
+  int IsQuad = Type.isQuad();
+  switch (Type.getEltType()) {
+  case NeonTypeFlags::Int8:
+  case NeonTypeFlags::Poly8:
+    return shift ? 7 : (8 << IsQuad) - 1;
+  case NeonTypeFlags::Int16:
+  case NeonTypeFlags::Poly16:
+    return shift ? 15 : (4 << IsQuad) - 1;
+  case NeonTypeFlags::Int32:
+    return shift ? 31 : (2 << IsQuad) - 1;
+  case NeonTypeFlags::Int64:
+    return shift ? 63 : (1 << IsQuad) - 1;
+  case NeonTypeFlags::Float16:
+    assert(!shift && "cannot shift float types!");
+    return (4 << IsQuad) - 1;
+  case NeonTypeFlags::Float32:
+    assert(!shift && "cannot shift float types!");
+    return (2 << IsQuad) - 1;
+  }
+  llvm_unreachable("Invalid NeonTypeFlag!");
+}
+
+/// getNeonEltType - Return the QualType corresponding to the elements of
+/// the vector type specified by the NeonTypeFlags.  This is used to check
+/// the pointer arguments for Neon load/store intrinsics.
+static QualType getNeonEltType(NeonTypeFlags Flags, ASTContext &Context) {
+  switch (Flags.getEltType()) {
+  case NeonTypeFlags::Int8:
+    return Flags.isUnsigned() ? Context.UnsignedCharTy : Context.SignedCharTy;
+  case NeonTypeFlags::Int16:
+    return Flags.isUnsigned() ? Context.UnsignedShortTy : Context.ShortTy;
+  case NeonTypeFlags::Int32:
+    return Flags.isUnsigned() ? Context.UnsignedIntTy : Context.IntTy;
+  case NeonTypeFlags::Int64:
+    return Flags.isUnsigned() ? Context.UnsignedLongLongTy : Context.LongLongTy;
+  case NeonTypeFlags::Poly8:
+    return Context.SignedCharTy;
+  case NeonTypeFlags::Poly16:
+    return Context.ShortTy;
+  case NeonTypeFlags::Float16:
+    return Context.UnsignedShortTy;
+  case NeonTypeFlags::Float32:
+    return Context.FloatTy;
+  }
+  llvm_unreachable("Invalid NeonTypeFlag!");
+}
+
+bool Sema::CheckARMBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
+  llvm::APSInt Result;
+
+  unsigned mask = 0;
+  unsigned TV = 0;
+  int PtrArgNum = -1;
+  bool HasConstPtr = false;
+  switch (BuiltinID) {
+#define GET_NEON_OVERLOAD_CHECK
+#include "clang/Basic/arm_neon.inc"
+#undef GET_NEON_OVERLOAD_CHECK
+  }
+  
+  // For NEON intrinsics which are overloaded on vector element type, validate
+  // the immediate which specifies which variant to emit.
+  unsigned ImmArg = TheCall->getNumArgs()-1;
+  if (mask) {
+    if (SemaBuiltinConstantArg(TheCall, ImmArg, Result))
+      return true;
+    
+    TV = Result.getLimitedValue(64);
+    if ((TV > 63) || (mask & (1 << TV)) == 0)
+      return Diag(TheCall->getLocStart(), diag::err_invalid_neon_type_code)
+        << TheCall->getArg(ImmArg)->getSourceRange();
+  }
+
+  if (PtrArgNum >= 0) {
+    // Check that pointer arguments have the specified type.
+    Expr *Arg = TheCall->getArg(PtrArgNum);
+    if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(Arg))
+      Arg = ICE->getSubExpr();
+    ExprResult RHS = DefaultFunctionArrayLvalueConversion(Arg);
+    QualType RHSTy = RHS.get()->getType();
+    QualType EltTy = getNeonEltType(NeonTypeFlags(TV), Context);
+    if (HasConstPtr)
+      EltTy = EltTy.withConst();
+    QualType LHSTy = Context.getPointerType(EltTy);
+    AssignConvertType ConvTy;
+    ConvTy = CheckSingleAssignmentConstraints(LHSTy, RHS);
+    if (RHS.isInvalid())
+      return true;
+    if (DiagnoseAssignmentResult(ConvTy, Arg->getLocStart(), LHSTy, RHSTy,
+                                 RHS.get(), AA_Assigning))
+      return true;
+  }
+  
+  // For NEON intrinsics which take an immediate value as part of the 
+  // instruction, range check them here.
+  unsigned i = 0, l = 0, u = 0;
+  switch (BuiltinID) {
+  default: return false;
+  case ARM::BI__builtin_arm_ssat: i = 1; l = 1; u = 31; break;
+  case ARM::BI__builtin_arm_usat: i = 1; u = 31; break;
+  case ARM::BI__builtin_arm_vcvtr_f:
+  case ARM::BI__builtin_arm_vcvtr_d: i = 1; u = 1; break;
+#define GET_NEON_IMMEDIATE_CHECK
+#include "clang/Basic/arm_neon.inc"
+#undef GET_NEON_IMMEDIATE_CHECK
+  };
+
+  // Check that the immediate argument is actually a constant.
+  if (SemaBuiltinConstantArg(TheCall, i, Result))
+    return true;
+
+  // Range check against the upper/lower values for this isntruction.
+  unsigned Val = Result.getZExtValue();
+  if (Val < l || Val > (u + l))
+    return Diag(TheCall->getLocStart(), diag::err_argument_invalid_range)
+      << l << u+l << TheCall->getArg(i)->getSourceRange();
+
+  // FIXME: VFP Intrinsics should error if VFP not present.
+  return false;
+}
+
+/// CheckFunctionCall - Check a direct function call for various correctness
+/// and safety properties not strictly enforced by the C type system.
+bool Sema::CheckFunctionCall(FunctionDecl *FDecl, CallExpr *TheCall) {
+  // Get the IdentifierInfo* for the called function.
+  IdentifierInfo *FnInfo = FDecl->getIdentifier();
+
+  // None of the checks below are needed for functions that don't have
+  // simple names (e.g., C++ conversion functions).
+  if (!FnInfo)
+    return false;
+
+  // FIXME: This mechanism should be abstracted to be less fragile and
+  // more efficient. For example, just map function ids to custom
+  // handlers.
+
+  // Printf and scanf checking.
+  for (specific_attr_iterator<FormatAttr>
+         i = FDecl->specific_attr_begin<FormatAttr>(),
+         e = FDecl->specific_attr_end<FormatAttr>(); i != e ; ++i) {
+    CheckFormatArguments(*i, TheCall);
+  }
+
+  for (specific_attr_iterator<NonNullAttr>
+         i = FDecl->specific_attr_begin<NonNullAttr>(),
+         e = FDecl->specific_attr_end<NonNullAttr>(); i != e; ++i) {
+    CheckNonNullArguments(*i, TheCall->getArgs(),
+                          TheCall->getCallee()->getLocStart());
+  }
+
+  unsigned CMId = FDecl->getMemoryFunctionKind();
+  if (CMId == 0)
+    return false;
+
+  // Handle memory setting and copying functions.
+  if (CMId == Builtin::BIstrlcpy || CMId == Builtin::BIstrlcat)
+    CheckStrlcpycatArguments(TheCall, FnInfo);
+  else if (CMId == Builtin::BIstrncat)
+    CheckStrncatArguments(TheCall, FnInfo);
+  else
+    CheckMemaccessArguments(TheCall, CMId, FnInfo);
+
+  return false;
+}
+
+bool Sema::CheckObjCMethodCall(ObjCMethodDecl *Method, SourceLocation lbrac, 
+                               Expr **Args, unsigned NumArgs) {
+  for (specific_attr_iterator<FormatAttr>
+       i = Method->specific_attr_begin<FormatAttr>(),
+       e = Method->specific_attr_end<FormatAttr>(); i != e ; ++i) {
+
+    CheckFormatArguments(*i, Args, NumArgs, false, lbrac, 
+                         Method->getSourceRange());
+  }
+
+  // diagnose nonnull arguments.
+  for (specific_attr_iterator<NonNullAttr>
+       i = Method->specific_attr_begin<NonNullAttr>(),
+       e = Method->specific_attr_end<NonNullAttr>(); i != e; ++i) {
+    CheckNonNullArguments(*i, Args, lbrac);
+  }
+
+  return false;
+}
+
+bool Sema::CheckBlockCall(NamedDecl *NDecl, CallExpr *TheCall) {
+  const VarDecl *V = dyn_cast<VarDecl>(NDecl);
+  if (!V)
+    return false;
+
+  QualType Ty = V->getType();
+  if (!Ty->isBlockPointerType())
+    return false;
+
+  // format string checking.
+  for (specific_attr_iterator<FormatAttr>
+       i = NDecl->specific_attr_begin<FormatAttr>(),
+       e = NDecl->specific_attr_end<FormatAttr>(); i != e ; ++i) {
+    CheckFormatArguments(*i, TheCall);
+  }
+
+  return false;
+}
+
+ExprResult Sema::SemaAtomicOpsOverloaded(ExprResult TheCallResult,
+                                         AtomicExpr::AtomicOp Op) {
+  CallExpr *TheCall = cast<CallExpr>(TheCallResult.get());
+  DeclRefExpr *DRE =cast<DeclRefExpr>(TheCall->getCallee()->IgnoreParenCasts());
+
+  // All these operations take one of the following forms:
+  enum {
+    // C    __c11_atomic_init(A *, C)
+    Init,
+    // C    __c11_atomic_load(A *, int)
+    Load,
+    // void __atomic_load(A *, CP, int)
+    Copy,
+    // C    __c11_atomic_add(A *, M, int)
+    Arithmetic,
+    // C    __atomic_exchange_n(A *, CP, int)
+    Xchg,
+    // void __atomic_exchange(A *, C *, CP, int)
+    GNUXchg,
+    // bool __c11_atomic_compare_exchange_strong(A *, C *, CP, int, int)
+    C11CmpXchg,
+    // bool __atomic_compare_exchange(A *, C *, CP, bool, int, int)
+    GNUCmpXchg
+  } Form = Init;
+  const unsigned NumArgs[] = { 2, 2, 3, 3, 3, 4, 5, 6 };
+  const unsigned NumVals[] = { 1, 0, 1, 1, 1, 2, 2, 3 };
+  // where:
+  //   C is an appropriate type,
+  //   A is volatile _Atomic(C) for __c11 builtins and is C for GNU builtins,
+  //   CP is C for __c11 builtins and GNU _n builtins and is C * otherwise,
+  //   M is C if C is an integer, and ptrdiff_t if C is a pointer, and
+  //   the int parameters are for orderings.
+
+  assert(AtomicExpr::AO__c11_atomic_init == 0 &&
+         AtomicExpr::AO__c11_atomic_fetch_xor + 1 == AtomicExpr::AO__atomic_load
+         && "need to update code for modified C11 atomics");
+  bool IsC11 = Op >= AtomicExpr::AO__c11_atomic_init &&
+               Op <= AtomicExpr::AO__c11_atomic_fetch_xor;
+  bool IsN = Op == AtomicExpr::AO__atomic_load_n ||
+             Op == AtomicExpr::AO__atomic_store_n ||
+             Op == AtomicExpr::AO__atomic_exchange_n ||
+             Op == AtomicExpr::AO__atomic_compare_exchange_n;
+  bool IsAddSub = false;
+
+  switch (Op) {
+  case AtomicExpr::AO__c11_atomic_init:
+    Form = Init;
+    break;
+
+  case AtomicExpr::AO__c11_atomic_load:
+  case AtomicExpr::AO__atomic_load_n:
+    Form = Load;
+    break;
+
+  case AtomicExpr::AO__c11_atomic_store:
+  case AtomicExpr::AO__atomic_load:
+  case AtomicExpr::AO__atomic_store:
+  case AtomicExpr::AO__atomic_store_n:
+    Form = Copy;
+    break;
+
+  case AtomicExpr::AO__c11_atomic_fetch_add:
+  case AtomicExpr::AO__c11_atomic_fetch_sub:
+  case AtomicExpr::AO__atomic_fetch_add:
+  case AtomicExpr::AO__atomic_fetch_sub:
+  case AtomicExpr::AO__atomic_add_fetch:
+  case AtomicExpr::AO__atomic_sub_fetch:
+    IsAddSub = true;
+    // Fall through.
+  case AtomicExpr::AO__c11_atomic_fetch_and:
+  case AtomicExpr::AO__c11_atomic_fetch_or:
+  case AtomicExpr::AO__c11_atomic_fetch_xor:
+  case AtomicExpr::AO__atomic_fetch_and:
+  case AtomicExpr::AO__atomic_fetch_or:
+  case AtomicExpr::AO__atomic_fetch_xor:
+  case AtomicExpr::AO__atomic_fetch_nand:
+  case AtomicExpr::AO__atomic_and_fetch:
+  case AtomicExpr::AO__atomic_or_fetch:
+  case AtomicExpr::AO__atomic_xor_fetch:
+  case AtomicExpr::AO__atomic_nand_fetch:
+    Form = Arithmetic;
+    break;
+
+  case AtomicExpr::AO__c11_atomic_exchange:
+  case AtomicExpr::AO__atomic_exchange_n:
+    Form = Xchg;
+    break;
+
+  case AtomicExpr::AO__atomic_exchange:
+    Form = GNUXchg;
+    break;
+
+  case AtomicExpr::AO__c11_atomic_compare_exchange_strong:
+  case AtomicExpr::AO__c11_atomic_compare_exchange_weak:
+    Form = C11CmpXchg;
+    break;
+
+  case AtomicExpr::AO__atomic_compare_exchange:
+  case AtomicExpr::AO__atomic_compare_exchange_n:
+    Form = GNUCmpXchg;
+    break;
+  }
+
+  // Check we have the right number of arguments.
+  if (TheCall->getNumArgs() < NumArgs[Form]) {
+    Diag(TheCall->getLocEnd(), diag::err_typecheck_call_too_few_args)
+      << 0 << NumArgs[Form] << TheCall->getNumArgs()
+      << TheCall->getCallee()->getSourceRange();
+    return ExprError();
+  } else if (TheCall->getNumArgs() > NumArgs[Form]) {
+    Diag(TheCall->getArg(NumArgs[Form])->getLocStart(),
+         diag::err_typecheck_call_too_many_args)
+      << 0 << NumArgs[Form] << TheCall->getNumArgs()
+      << TheCall->getCallee()->getSourceRange();
+    return ExprError();
+  }
+
+  // Inspect the first argument of the atomic operation.
+  Expr *Ptr = TheCall->getArg(0);
+  Ptr = DefaultFunctionArrayLvalueConversion(Ptr).get();
+  const PointerType *pointerType = Ptr->getType()->getAs<PointerType>();
+  if (!pointerType) {
+    Diag(DRE->getLocStart(), diag::err_atomic_builtin_must_be_pointer)
+      << Ptr->getType() << Ptr->getSourceRange();
+    return ExprError();
+  }
+
+  // For a __c11 builtin, this should be a pointer to an _Atomic type.
+  QualType AtomTy = pointerType->getPointeeType(); // 'A'
+  QualType ValType = AtomTy; // 'C'
+  if (IsC11) {
+    if (!AtomTy->isAtomicType()) {
+      Diag(DRE->getLocStart(), diag::err_atomic_op_needs_atomic)
+        << Ptr->getType() << Ptr->getSourceRange();
+      return ExprError();
+    }
+    ValType = AtomTy->getAs<AtomicType>()->getValueType();
+  }
+
+  // For an arithmetic operation, the implied arithmetic must be well-formed.
+  if (Form == Arithmetic) {
+    // gcc does not enforce these rules for GNU atomics, but we do so for sanity.
+    if (IsAddSub && !ValType->isIntegerType() && !ValType->isPointerType()) {
+      Diag(DRE->getLocStart(), diag::err_atomic_op_needs_atomic_int_or_ptr)
+        << IsC11 << Ptr->getType() << Ptr->getSourceRange();
+      return ExprError();
+    }
+    if (!IsAddSub && !ValType->isIntegerType()) {
+      Diag(DRE->getLocStart(), diag::err_atomic_op_bitwise_needs_atomic_int)
+        << IsC11 << Ptr->getType() << Ptr->getSourceRange();
+      return ExprError();
+    }
+  } else if (IsN && !ValType->isIntegerType() && !ValType->isPointerType()) {
+    // For __atomic_*_n operations, the value type must be a scalar integral or
+    // pointer type which is 1, 2, 4, 8 or 16 bytes in length.
+    Diag(DRE->getLocStart(), diag::err_atomic_op_needs_atomic_int_or_ptr)
+      << IsC11 << Ptr->getType() << Ptr->getSourceRange();
+    return ExprError();
+  }
+
+  if (!IsC11 && !AtomTy.isTriviallyCopyableType(Context)) {
+    // For GNU atomics, require a trivially-copyable type. This is not part of
+    // the GNU atomics specification, but we enforce it for sanity.
+    Diag(DRE->getLocStart(), diag::err_atomic_op_needs_trivial_copy)
+      << Ptr->getType() << Ptr->getSourceRange();
+    return ExprError();
+  }
+
+  // FIXME: For any builtin other than a load, the ValType must not be
+  // const-qualified.
+
+  switch (ValType.getObjCLifetime()) {
+  case Qualifiers::OCL_None:
+  case Qualifiers::OCL_ExplicitNone:
+    // okay
+    break;
+
+  case Qualifiers::OCL_Weak:
+  case Qualifiers::OCL_Strong:
+  case Qualifiers::OCL_Autoreleasing:
+    // FIXME: Can this happen? By this point, ValType should be known
+    // to be trivially copyable.
+    Diag(DRE->getLocStart(), diag::err_arc_atomic_ownership)
+      << ValType << Ptr->getSourceRange();
+    return ExprError();
+  }
+
+  QualType ResultType = ValType;
+  if (Form == Copy || Form == GNUXchg || Form == Init)
+    ResultType = Context.VoidTy;
+  else if (Form == C11CmpXchg || Form == GNUCmpXchg)
+    ResultType = Context.BoolTy;
+
+  // The type of a parameter passed 'by value'. In the GNU atomics, such
+  // arguments are actually passed as pointers.
+  QualType ByValType = ValType; // 'CP'
+  if (!IsC11 && !IsN)
+    ByValType = Ptr->getType();
+
+  // The first argument --- the pointer --- has a fixed type; we
+  // deduce the types of the rest of the arguments accordingly.  Walk
+  // the remaining arguments, converting them to the deduced value type.
+  for (unsigned i = 1; i != NumArgs[Form]; ++i) {
+    QualType Ty;
+    if (i < NumVals[Form] + 1) {
+      switch (i) {
+      case 1:
+        // The second argument is the non-atomic operand. For arithmetic, this
+        // is always passed by value, and for a compare_exchange it is always
+        // passed by address. For the rest, GNU uses by-address and C11 uses
+        // by-value.
+        assert(Form != Load);
+        if (Form == Init || (Form == Arithmetic && ValType->isIntegerType()))
+          Ty = ValType;
+        else if (Form == Copy || Form == Xchg)
+          Ty = ByValType;
+        else if (Form == Arithmetic)
+          Ty = Context.getPointerDiffType();
+        else
+          Ty = Context.getPointerType(ValType.getUnqualifiedType());
+        break;
+      case 2:
+        // The third argument to compare_exchange / GNU exchange is a
+        // (pointer to a) desired value.
+        Ty = ByValType;
+        break;
+      case 3:
+        // The fourth argument to GNU compare_exchange is a 'weak' flag.
+        Ty = Context.BoolTy;
+        break;
+      }
+    } else {
+      // The order(s) are always converted to int.
+      Ty = Context.IntTy;
+    }
+
+    InitializedEntity Entity =
+        InitializedEntity::InitializeParameter(Context, Ty, false);
+    ExprResult Arg = TheCall->getArg(i);
+    Arg = PerformCopyInitialization(Entity, SourceLocation(), Arg);
+    if (Arg.isInvalid())
+      return true;
+    TheCall->setArg(i, Arg.get());
+  }
+
+  // Permute the arguments into a 'consistent' order.
+  SmallVector<Expr*, 5> SubExprs;
+  SubExprs.push_back(Ptr);
+  switch (Form) {
+  case Init:
+    // Note, AtomicExpr::getVal1() has a special case for this atomic.
+    SubExprs.push_back(TheCall->getArg(1)); // Val1
+    break;
+  case Load:
+    SubExprs.push_back(TheCall->getArg(1)); // Order
+    break;
+  case Copy:
+  case Arithmetic:
+  case Xchg:
+    SubExprs.push_back(TheCall->getArg(2)); // Order
+    SubExprs.push_back(TheCall->getArg(1)); // Val1
+    break;
+  case GNUXchg:
+    // Note, AtomicExpr::getVal2() has a special case for this atomic.
+    SubExprs.push_back(TheCall->getArg(3)); // Order
+    SubExprs.push_back(TheCall->getArg(1)); // Val1
+    SubExprs.push_back(TheCall->getArg(2)); // Val2
+    break;
+  case C11CmpXchg:
+    SubExprs.push_back(TheCall->getArg(3)); // Order
+    SubExprs.push_back(TheCall->getArg(1)); // Val1
+    SubExprs.push_back(TheCall->getArg(4)); // OrderFail
+    SubExprs.push_back(TheCall->getArg(2)); // Val2
+    break;
+  case GNUCmpXchg:
+    SubExprs.push_back(TheCall->getArg(4)); // Order
+    SubExprs.push_back(TheCall->getArg(1)); // Val1
+    SubExprs.push_back(TheCall->getArg(5)); // OrderFail
+    SubExprs.push_back(TheCall->getArg(2)); // Val2
+    SubExprs.push_back(TheCall->getArg(3)); // Weak
+    break;
+  }
+
+  return Owned(new (Context) AtomicExpr(TheCall->getCallee()->getLocStart(),
+                                        SubExprs.data(), SubExprs.size(),
+                                        ResultType, Op,
+                                        TheCall->getRParenLoc()));
+}
+
+
+/// checkBuiltinArgument - Given a call to a builtin function, perform
+/// normal type-checking on the given argument, updating the call in
+/// place.  This is useful when a builtin function requires custom
+/// type-checking for some of its arguments but not necessarily all of
+/// them.
+///
+/// Returns true on error.
+static bool checkBuiltinArgument(Sema &S, CallExpr *E, unsigned ArgIndex) {
+  FunctionDecl *Fn = E->getDirectCallee();
+  assert(Fn && "builtin call without direct callee!");
+
+  ParmVarDecl *Param = Fn->getParamDecl(ArgIndex);
+  InitializedEntity Entity =
+    InitializedEntity::InitializeParameter(S.Context, Param);
+
+  ExprResult Arg = E->getArg(0);
+  Arg = S.PerformCopyInitialization(Entity, SourceLocation(), Arg);
+  if (Arg.isInvalid())
+    return true;
+
+  E->setArg(ArgIndex, Arg.take());
+  return false;
+}
+
+/// SemaBuiltinAtomicOverloaded - We have a call to a function like
+/// __sync_fetch_and_add, which is an overloaded function based on the pointer
+/// type of its first argument.  The main ActOnCallExpr routines have already
+/// promoted the types of arguments because all of these calls are prototyped as
+/// void(...).
+///
+/// This function goes through and does final semantic checking for these
+/// builtins,
+ExprResult
+Sema::SemaBuiltinAtomicOverloaded(ExprResult TheCallResult) {
+  CallExpr *TheCall = (CallExpr *)TheCallResult.get();
+  DeclRefExpr *DRE =cast<DeclRefExpr>(TheCall->getCallee()->IgnoreParenCasts());
+  FunctionDecl *FDecl = cast<FunctionDecl>(DRE->getDecl());
+
+  // Ensure that we have at least one argument to do type inference from.
+  if (TheCall->getNumArgs() < 1) {
+    Diag(TheCall->getLocEnd(), diag::err_typecheck_call_too_few_args_at_least)
+      << 0 << 1 << TheCall->getNumArgs()
+      << TheCall->getCallee()->getSourceRange();
+    return ExprError();
+  }
+
+  // Inspect the first argument of the atomic builtin.  This should always be
+  // a pointer type, whose element is an integral scalar or pointer type.
+  // Because it is a pointer type, we don't have to worry about any implicit
+  // casts here.
+  // FIXME: We don't allow floating point scalars as input.
+  Expr *FirstArg = TheCall->getArg(0);
+  ExprResult FirstArgResult = DefaultFunctionArrayLvalueConversion(FirstArg);
+  if (FirstArgResult.isInvalid())
+    return ExprError();
+  FirstArg = FirstArgResult.take();
+  TheCall->setArg(0, FirstArg);
+
+  const PointerType *pointerType = FirstArg->getType()->getAs<PointerType>();
+  if (!pointerType) {
+    Diag(DRE->getLocStart(), diag::err_atomic_builtin_must_be_pointer)
+      << FirstArg->getType() << FirstArg->getSourceRange();
+    return ExprError();
+  }
+
+  QualType ValType = pointerType->getPointeeType();
+  if (!ValType->isIntegerType() && !ValType->isAnyPointerType() &&
+      !ValType->isBlockPointerType()) {
+    Diag(DRE->getLocStart(), diag::err_atomic_builtin_must_be_pointer_intptr)
+      << FirstArg->getType() << FirstArg->getSourceRange();
+    return ExprError();
+  }
+
+  switch (ValType.getObjCLifetime()) {
+  case Qualifiers::OCL_None:
+  case Qualifiers::OCL_ExplicitNone:
+    // okay
+    break;
+
+  case Qualifiers::OCL_Weak:
+  case Qualifiers::OCL_Strong:
+  case Qualifiers::OCL_Autoreleasing:
+    Diag(DRE->getLocStart(), diag::err_arc_atomic_ownership)
+      << ValType << FirstArg->getSourceRange();
+    return ExprError();
+  }
+
+  // Strip any qualifiers off ValType.
+  ValType = ValType.getUnqualifiedType();
+
+  // The majority of builtins return a value, but a few have special return
+  // types, so allow them to override appropriately below.
+  QualType ResultType = ValType;
+
+  // We need to figure out which concrete builtin this maps onto.  For example,
+  // __sync_fetch_and_add with a 2 byte object turns into
+  // __sync_fetch_and_add_2.
+#define BUILTIN_ROW(x) \
+  { Builtin::BI##x##_1, Builtin::BI##x##_2, Builtin::BI##x##_4, \
+    Builtin::BI##x##_8, Builtin::BI##x##_16 }
+
+  static const unsigned BuiltinIndices[][5] = {
+    BUILTIN_ROW(__sync_fetch_and_add),
+    BUILTIN_ROW(__sync_fetch_and_sub),
+    BUILTIN_ROW(__sync_fetch_and_or),
+    BUILTIN_ROW(__sync_fetch_and_and),
+    BUILTIN_ROW(__sync_fetch_and_xor),
+
+    BUILTIN_ROW(__sync_add_and_fetch),
+    BUILTIN_ROW(__sync_sub_and_fetch),
+    BUILTIN_ROW(__sync_and_and_fetch),
+    BUILTIN_ROW(__sync_or_and_fetch),
+    BUILTIN_ROW(__sync_xor_and_fetch),
+
+    BUILTIN_ROW(__sync_val_compare_and_swap),
+    BUILTIN_ROW(__sync_bool_compare_and_swap),
+    BUILTIN_ROW(__sync_lock_test_and_set),
+    BUILTIN_ROW(__sync_lock_release),
+    BUILTIN_ROW(__sync_swap)
+  };
+#undef BUILTIN_ROW
+
+  // Determine the index of the size.
+  unsigned SizeIndex;
+  switch (Context.getTypeSizeInChars(ValType).getQuantity()) {
+  case 1: SizeIndex = 0; break;
+  case 2: SizeIndex = 1; break;
+  case 4: SizeIndex = 2; break;
+  case 8: SizeIndex = 3; break;
+  case 16: SizeIndex = 4; break;
+  default:
+    Diag(DRE->getLocStart(), diag::err_atomic_builtin_pointer_size)
+      << FirstArg->getType() << FirstArg->getSourceRange();
+    return ExprError();
+  }
+
+  // Each of these builtins has one pointer argument, followed by some number of
+  // values (0, 1 or 2) followed by a potentially empty varags list of stuff
+  // that we ignore.  Find out which row of BuiltinIndices to read from as well
+  // as the number of fixed args.
+  unsigned BuiltinID = FDecl->getBuiltinID();
+  unsigned BuiltinIndex, NumFixed = 1;
+  switch (BuiltinID) {
+  default: llvm_unreachable("Unknown overloaded atomic builtin!");
+  case Builtin::BI__sync_fetch_and_add: 
+  case Builtin::BI__sync_fetch_and_add_1:
+  case Builtin::BI__sync_fetch_and_add_2:
+  case Builtin::BI__sync_fetch_and_add_4:
+  case Builtin::BI__sync_fetch_and_add_8:
+  case Builtin::BI__sync_fetch_and_add_16:
+    BuiltinIndex = 0; 
+    break;
+      
+  case Builtin::BI__sync_fetch_and_sub: 
+  case Builtin::BI__sync_fetch_and_sub_1:
+  case Builtin::BI__sync_fetch_and_sub_2:
+  case Builtin::BI__sync_fetch_and_sub_4:
+  case Builtin::BI__sync_fetch_and_sub_8:
+  case Builtin::BI__sync_fetch_and_sub_16:
+    BuiltinIndex = 1; 
+    break;
+      
+  case Builtin::BI__sync_fetch_and_or:  
+  case Builtin::BI__sync_fetch_and_or_1:
+  case Builtin::BI__sync_fetch_and_or_2:
+  case Builtin::BI__sync_fetch_and_or_4:
+  case Builtin::BI__sync_fetch_and_or_8:
+  case Builtin::BI__sync_fetch_and_or_16:
+    BuiltinIndex = 2; 
+    break;
+      
+  case Builtin::BI__sync_fetch_and_and: 
+  case Builtin::BI__sync_fetch_and_and_1:
+  case Builtin::BI__sync_fetch_and_and_2:
+  case Builtin::BI__sync_fetch_and_and_4:
+  case Builtin::BI__sync_fetch_and_and_8:
+  case Builtin::BI__sync_fetch_and_and_16:
+    BuiltinIndex = 3; 
+    break;
+
+  case Builtin::BI__sync_fetch_and_xor: 
+  case Builtin::BI__sync_fetch_and_xor_1:
+  case Builtin::BI__sync_fetch_and_xor_2:
+  case Builtin::BI__sync_fetch_and_xor_4:
+  case Builtin::BI__sync_fetch_and_xor_8:
+  case Builtin::BI__sync_fetch_and_xor_16:
+    BuiltinIndex = 4; 
+    break;
+
+  case Builtin::BI__sync_add_and_fetch: 
+  case Builtin::BI__sync_add_and_fetch_1:
+  case Builtin::BI__sync_add_and_fetch_2:
+  case Builtin::BI__sync_add_and_fetch_4:
+  case Builtin::BI__sync_add_and_fetch_8:
+  case Builtin::BI__sync_add_and_fetch_16:
+    BuiltinIndex = 5; 
+    break;
+      
+  case Builtin::BI__sync_sub_and_fetch: 
+  case Builtin::BI__sync_sub_and_fetch_1:
+  case Builtin::BI__sync_sub_and_fetch_2:
+  case Builtin::BI__sync_sub_and_fetch_4:
+  case Builtin::BI__sync_sub_and_fetch_8:
+  case Builtin::BI__sync_sub_and_fetch_16:
+    BuiltinIndex = 6; 
+    break;
+      
+  case Builtin::BI__sync_and_and_fetch: 
+  case Builtin::BI__sync_and_and_fetch_1:
+  case Builtin::BI__sync_and_and_fetch_2:
+  case Builtin::BI__sync_and_and_fetch_4:
+  case Builtin::BI__sync_and_and_fetch_8:
+  case Builtin::BI__sync_and_and_fetch_16:
+    BuiltinIndex = 7; 
+    break;
+      
+  case Builtin::BI__sync_or_and_fetch:  
+  case Builtin::BI__sync_or_and_fetch_1:
+  case Builtin::BI__sync_or_and_fetch_2:
+  case Builtin::BI__sync_or_and_fetch_4:
+  case Builtin::BI__sync_or_and_fetch_8:
+  case Builtin::BI__sync_or_and_fetch_16:
+    BuiltinIndex = 8; 
+    break;
+      
+  case Builtin::BI__sync_xor_and_fetch: 
+  case Builtin::BI__sync_xor_and_fetch_1:
+  case Builtin::BI__sync_xor_and_fetch_2:
+  case Builtin::BI__sync_xor_and_fetch_4:
+  case Builtin::BI__sync_xor_and_fetch_8:
+  case Builtin::BI__sync_xor_and_fetch_16:
+    BuiltinIndex = 9; 
+    break;
+
+  case Builtin::BI__sync_val_compare_and_swap:
+  case Builtin::BI__sync_val_compare_and_swap_1:
+  case Builtin::BI__sync_val_compare_and_swap_2:
+  case Builtin::BI__sync_val_compare_and_swap_4:
+  case Builtin::BI__sync_val_compare_and_swap_8:
+  case Builtin::BI__sync_val_compare_and_swap_16:
+    BuiltinIndex = 10;
+    NumFixed = 2;
+    break;
+      
+  case Builtin::BI__sync_bool_compare_and_swap:
+  case Builtin::BI__sync_bool_compare_and_swap_1:
+  case Builtin::BI__sync_bool_compare_and_swap_2:
+  case Builtin::BI__sync_bool_compare_and_swap_4:
+  case Builtin::BI__sync_bool_compare_and_swap_8:
+  case Builtin::BI__sync_bool_compare_and_swap_16:
+    BuiltinIndex = 11;
+    NumFixed = 2;
+    ResultType = Context.BoolTy;
+    break;
+      
+  case Builtin::BI__sync_lock_test_and_set: 
+  case Builtin::BI__sync_lock_test_and_set_1:
+  case Builtin::BI__sync_lock_test_and_set_2:
+  case Builtin::BI__sync_lock_test_and_set_4:
+  case Builtin::BI__sync_lock_test_and_set_8:
+  case Builtin::BI__sync_lock_test_and_set_16:
+    BuiltinIndex = 12; 
+    break;
+      
+  case Builtin::BI__sync_lock_release:
+  case Builtin::BI__sync_lock_release_1:
+  case Builtin::BI__sync_lock_release_2:
+  case Builtin::BI__sync_lock_release_4:
+  case Builtin::BI__sync_lock_release_8:
+  case Builtin::BI__sync_lock_release_16:
+    BuiltinIndex = 13;
+    NumFixed = 0;
+    ResultType = Context.VoidTy;
+    break;
+      
+  case Builtin::BI__sync_swap: 
+  case Builtin::BI__sync_swap_1:
+  case Builtin::BI__sync_swap_2:
+  case Builtin::BI__sync_swap_4:
+  case Builtin::BI__sync_swap_8:
+  case Builtin::BI__sync_swap_16:
+    BuiltinIndex = 14; 
+    break;
+  }
+
+  // Now that we know how many fixed arguments we expect, first check that we
+  // have at least that many.
+  if (TheCall->getNumArgs() < 1+NumFixed) {
+    Diag(TheCall->getLocEnd(), diag::err_typecheck_call_too_few_args_at_least)
+      << 0 << 1+NumFixed << TheCall->getNumArgs()
+      << TheCall->getCallee()->getSourceRange();
+    return ExprError();
+  }
+
+  // Get the decl for the concrete builtin from this, we can tell what the
+  // concrete integer type we should convert to is.
+  unsigned NewBuiltinID = BuiltinIndices[BuiltinIndex][SizeIndex];
+  const char *NewBuiltinName = Context.BuiltinInfo.GetName(NewBuiltinID);
+  IdentifierInfo *NewBuiltinII = PP.getIdentifierInfo(NewBuiltinName);
+  FunctionDecl *NewBuiltinDecl =
+    cast<FunctionDecl>(LazilyCreateBuiltin(NewBuiltinII, NewBuiltinID,
+                                           TUScope, false, DRE->getLocStart()));
+
+  // The first argument --- the pointer --- has a fixed type; we
+  // deduce the types of the rest of the arguments accordingly.  Walk
+  // the remaining arguments, converting them to the deduced value type.
+  for (unsigned i = 0; i != NumFixed; ++i) {
+    ExprResult Arg = TheCall->getArg(i+1);
+
+    // GCC does an implicit conversion to the pointer or integer ValType.  This
+    // can fail in some cases (1i -> int**), check for this error case now.
+    // Initialize the argument.
+    InitializedEntity Entity = InitializedEntity::InitializeParameter(Context,
+                                                   ValType, /*consume*/ false);
+    Arg = PerformCopyInitialization(Entity, SourceLocation(), Arg);
+    if (Arg.isInvalid())
+      return ExprError();
+
+    // Okay, we have something that *can* be converted to the right type.  Check
+    // to see if there is a potentially weird extension going on here.  This can
+    // happen when you do an atomic operation on something like an char* and
+    // pass in 42.  The 42 gets converted to char.  This is even more strange
+    // for things like 45.123 -> char, etc.
+    // FIXME: Do this check.
+    TheCall->setArg(i+1, Arg.take());
+  }
+
+  ASTContext& Context = this->getASTContext();
+
+  // Create a new DeclRefExpr to refer to the new decl.
+  DeclRefExpr* NewDRE = DeclRefExpr::Create(
+      Context,
+      DRE->getQualifierLoc(),
+      SourceLocation(),
+      NewBuiltinDecl,
+      /*enclosing*/ false,
+      DRE->getLocation(),
+      NewBuiltinDecl->getType(),
+      DRE->getValueKind());
+
+  // Set the callee in the CallExpr.
+  // FIXME: This leaks the original parens and implicit casts.
+  ExprResult PromotedCall = UsualUnaryConversions(NewDRE);
+  if (PromotedCall.isInvalid())
+    return ExprError();
+  TheCall->setCallee(PromotedCall.take());
+
+  // Change the result type of the call to match the original value type. This
+  // is arbitrary, but the codegen for these builtins ins design to handle it
+  // gracefully.
+  TheCall->setType(ResultType);
+
+  return move(TheCallResult);
+}
+
+/// CheckObjCString - Checks that the argument to the builtin
+/// CFString constructor is correct
+/// Note: It might also make sense to do the UTF-16 conversion here (would
+/// simplify the backend).
+bool Sema::CheckObjCString(Expr *Arg) {
+  Arg = Arg->IgnoreParenCasts();
+  StringLiteral *Literal = dyn_cast<StringLiteral>(Arg);
+
+  if (!Literal || !Literal->isAscii()) {
+    Diag(Arg->getLocStart(), diag::err_cfstring_literal_not_string_constant)
+      << Arg->getSourceRange();
+    return true;
+  }
+
+  if (Literal->containsNonAsciiOrNull()) {
+    StringRef String = Literal->getString();
+    unsigned NumBytes = String.size();
+    SmallVector<UTF16, 128> ToBuf(NumBytes);
+    const UTF8 *FromPtr = (UTF8 *)String.data();
+    UTF16 *ToPtr = &ToBuf[0];
+    
+    ConversionResult Result = ConvertUTF8toUTF16(&FromPtr, FromPtr + NumBytes,
+                                                 &ToPtr, ToPtr + NumBytes,
+                                                 strictConversion);
+    // Check for conversion failure.
+    if (Result != conversionOK)
+      Diag(Arg->getLocStart(),
+           diag::warn_cfstring_truncated) << Arg->getSourceRange();
+  }
+  return false;
+}
+
+/// SemaBuiltinVAStart - Check the arguments to __builtin_va_start for validity.
+/// Emit an error and return true on failure, return false on success.
+bool Sema::SemaBuiltinVAStart(CallExpr *TheCall) {
+  Expr *Fn = TheCall->getCallee();
+  if (TheCall->getNumArgs() > 2) {
+    Diag(TheCall->getArg(2)->getLocStart(),
+         diag::err_typecheck_call_too_many_args)
+      << 0 /*function call*/ << 2 << TheCall->getNumArgs()
+      << Fn->getSourceRange()
+      << SourceRange(TheCall->getArg(2)->getLocStart(),
+                     (*(TheCall->arg_end()-1))->getLocEnd());
+    return true;
+  }
+
+  if (TheCall->getNumArgs() < 2) {
+    return Diag(TheCall->getLocEnd(),
+      diag::err_typecheck_call_too_few_args_at_least)
+      << 0 /*function call*/ << 2 << TheCall->getNumArgs();
+  }
+
+  // Type-check the first argument normally.
+  if (checkBuiltinArgument(*this, TheCall, 0))
+    return true;
+
+  // Determine whether the current function is variadic or not.
+  BlockScopeInfo *CurBlock = getCurBlock();
+  bool isVariadic;
+  if (CurBlock)
+    isVariadic = CurBlock->TheDecl->isVariadic();
+  else if (FunctionDecl *FD = getCurFunctionDecl())
+    isVariadic = FD->isVariadic();
+  else
+    isVariadic = getCurMethodDecl()->isVariadic();
+
+  if (!isVariadic) {
+    Diag(Fn->getLocStart(), diag::err_va_start_used_in_non_variadic_function);
+    return true;
+  }
+
+  // Verify that the second argument to the builtin is the last argument of the
+  // current function or method.
+  bool SecondArgIsLastNamedArgument = false;
+  const Expr *Arg = TheCall->getArg(1)->IgnoreParenCasts();
+
+  if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(Arg)) {
+    if (const ParmVarDecl *PV = dyn_cast<ParmVarDecl>(DR->getDecl())) {
+      // FIXME: This isn't correct for methods (results in bogus warning).
+      // Get the last formal in the current function.
+      const ParmVarDecl *LastArg;
+      if (CurBlock)
+        LastArg = *(CurBlock->TheDecl->param_end()-1);
+      else if (FunctionDecl *FD = getCurFunctionDecl())
+        LastArg = *(FD->param_end()-1);
+      else
+        LastArg = *(getCurMethodDecl()->param_end()-1);
+      SecondArgIsLastNamedArgument = PV == LastArg;
+    }
+  }
+
+  if (!SecondArgIsLastNamedArgument)
+    Diag(TheCall->getArg(1)->getLocStart(),
+         diag::warn_second_parameter_of_va_start_not_last_named_argument);
+  return false;
+}
+
+/// SemaBuiltinUnorderedCompare - Handle functions like __builtin_isgreater and
+/// friends.  This is declared to take (...), so we have to check everything.
+bool Sema::SemaBuiltinUnorderedCompare(CallExpr *TheCall) {
+  if (TheCall->getNumArgs() < 2)
+    return Diag(TheCall->getLocEnd(), diag::err_typecheck_call_too_few_args)
+      << 0 << 2 << TheCall->getNumArgs()/*function call*/;
+  if (TheCall->getNumArgs() > 2)
+    return Diag(TheCall->getArg(2)->getLocStart(),
+                diag::err_typecheck_call_too_many_args)
+      << 0 /*function call*/ << 2 << TheCall->getNumArgs()
+      << SourceRange(TheCall->getArg(2)->getLocStart(),
+                     (*(TheCall->arg_end()-1))->getLocEnd());
+
+  ExprResult OrigArg0 = TheCall->getArg(0);
+  ExprResult OrigArg1 = TheCall->getArg(1);
+
+  // Do standard promotions between the two arguments, returning their common
+  // type.
+  QualType Res = UsualArithmeticConversions(OrigArg0, OrigArg1, false);
+  if (OrigArg0.isInvalid() || OrigArg1.isInvalid())
+    return true;
+
+  // Make sure any conversions are pushed back into the call; this is
+  // type safe since unordered compare builtins are declared as "_Bool
+  // foo(...)".
+  TheCall->setArg(0, OrigArg0.get());
+  TheCall->setArg(1, OrigArg1.get());
+
+  if (OrigArg0.get()->isTypeDependent() || OrigArg1.get()->isTypeDependent())
+    return false;
+
+  // If the common type isn't a real floating type, then the arguments were
+  // invalid for this operation.
+  if (!Res->isRealFloatingType())
+    return Diag(OrigArg0.get()->getLocStart(),
+                diag::err_typecheck_call_invalid_ordered_compare)
+      << OrigArg0.get()->getType() << OrigArg1.get()->getType()
+      << SourceRange(OrigArg0.get()->getLocStart(), OrigArg1.get()->getLocEnd());
+
+  return false;
+}
+
+/// SemaBuiltinSemaBuiltinFPClassification - Handle functions like
+/// __builtin_isnan and friends.  This is declared to take (...), so we have
+/// to check everything. We expect the last argument to be a floating point
+/// value.
+bool Sema::SemaBuiltinFPClassification(CallExpr *TheCall, unsigned NumArgs) {
+  if (TheCall->getNumArgs() < NumArgs)
+    return Diag(TheCall->getLocEnd(), diag::err_typecheck_call_too_few_args)
+      << 0 << NumArgs << TheCall->getNumArgs()/*function call*/;
+  if (TheCall->getNumArgs() > NumArgs)
+    return Diag(TheCall->getArg(NumArgs)->getLocStart(),
+                diag::err_typecheck_call_too_many_args)
+      << 0 /*function call*/ << NumArgs << TheCall->getNumArgs()
+      << SourceRange(TheCall->getArg(NumArgs)->getLocStart(),
+                     (*(TheCall->arg_end()-1))->getLocEnd());
+
+  Expr *OrigArg = TheCall->getArg(NumArgs-1);
+
+  if (OrigArg->isTypeDependent())
+    return false;
+
+  // This operation requires a non-_Complex floating-point number.
+  if (!OrigArg->getType()->isRealFloatingType())
+    return Diag(OrigArg->getLocStart(),
+                diag::err_typecheck_call_invalid_unary_fp)
+      << OrigArg->getType() << OrigArg->getSourceRange();
+
+  // If this is an implicit conversion from float -> double, remove it.
+  if (ImplicitCastExpr *Cast = dyn_cast<ImplicitCastExpr>(OrigArg)) {
+    Expr *CastArg = Cast->getSubExpr();
+    if (CastArg->getType()->isSpecificBuiltinType(BuiltinType::Float)) {
+      assert(Cast->getType()->isSpecificBuiltinType(BuiltinType::Double) &&
+             "promotion from float to double is the only expected cast here");
+      Cast->setSubExpr(0);
+      TheCall->setArg(NumArgs-1, CastArg);
+    }
+  }
+  
+  return false;
+}
+
+/// SemaBuiltinShuffleVector - Handle __builtin_shufflevector.
+// This is declared to take (...), so we have to check everything.
+ExprResult Sema::SemaBuiltinShuffleVector(CallExpr *TheCall) {
+  if (TheCall->getNumArgs() < 2)
+    return ExprError(Diag(TheCall->getLocEnd(),
+                          diag::err_typecheck_call_too_few_args_at_least)
+      << 0 /*function call*/ << 2 << TheCall->getNumArgs()
+      << TheCall->getSourceRange());
+
+  // Determine which of the following types of shufflevector we're checking:
+  // 1) unary, vector mask: (lhs, mask)
+  // 2) binary, vector mask: (lhs, rhs, mask)
+  // 3) binary, scalar mask: (lhs, rhs, index, ..., index)
+  QualType resType = TheCall->getArg(0)->getType();
+  unsigned numElements = 0;
+  
+  if (!TheCall->getArg(0)->isTypeDependent() &&
+      !TheCall->getArg(1)->isTypeDependent()) {
+    QualType LHSType = TheCall->getArg(0)->getType();
+    QualType RHSType = TheCall->getArg(1)->getType();
+    
+    if (!LHSType->isVectorType() || !RHSType->isVectorType()) {
+      Diag(TheCall->getLocStart(), diag::err_shufflevector_non_vector)
+        << SourceRange(TheCall->getArg(0)->getLocStart(),
+                       TheCall->getArg(1)->getLocEnd());
+      return ExprError();
+    }
+    
+    numElements = LHSType->getAs<VectorType>()->getNumElements();
+    unsigned numResElements = TheCall->getNumArgs() - 2;
+
+    // Check to see if we have a call with 2 vector arguments, the unary shuffle
+    // with mask.  If so, verify that RHS is an integer vector type with the
+    // same number of elts as lhs.
+    if (TheCall->getNumArgs() == 2) {
+      if (!RHSType->hasIntegerRepresentation() || 
+          RHSType->getAs<VectorType>()->getNumElements() != numElements)
+        Diag(TheCall->getLocStart(), diag::err_shufflevector_incompatible_vector)
+          << SourceRange(TheCall->getArg(1)->getLocStart(),
+                         TheCall->getArg(1)->getLocEnd());
+      numResElements = numElements;
+    }
+    else if (!Context.hasSameUnqualifiedType(LHSType, RHSType)) {
+      Diag(TheCall->getLocStart(), diag::err_shufflevector_incompatible_vector)
+        << SourceRange(TheCall->getArg(0)->getLocStart(),
+                       TheCall->getArg(1)->getLocEnd());
+      return ExprError();
+    } else if (numElements != numResElements) {
+      QualType eltType = LHSType->getAs<VectorType>()->getElementType();
+      resType = Context.getVectorType(eltType, numResElements,
+                                      VectorType::GenericVector);
+    }
+  }
+
+  for (unsigned i = 2; i < TheCall->getNumArgs(); i++) {
+    if (TheCall->getArg(i)->isTypeDependent() ||
+        TheCall->getArg(i)->isValueDependent())
+      continue;
+
+    llvm::APSInt Result(32);
+    if (!TheCall->getArg(i)->isIntegerConstantExpr(Result, Context))
+      return ExprError(Diag(TheCall->getLocStart(),
+                  diag::err_shufflevector_nonconstant_argument)
+                << TheCall->getArg(i)->getSourceRange());
+
+    if (Result.getActiveBits() > 64 || Result.getZExtValue() >= numElements*2)
+      return ExprError(Diag(TheCall->getLocStart(),
+                  diag::err_shufflevector_argument_too_large)
+               << TheCall->getArg(i)->getSourceRange());
+  }
+
+  SmallVector<Expr*, 32> exprs;
+
+  for (unsigned i = 0, e = TheCall->getNumArgs(); i != e; i++) {
+    exprs.push_back(TheCall->getArg(i));
+    TheCall->setArg(i, 0);
+  }
+
+  return Owned(new (Context) ShuffleVectorExpr(Context, exprs.begin(),
+                                            exprs.size(), resType,
+                                            TheCall->getCallee()->getLocStart(),
+                                            TheCall->getRParenLoc()));
+}
+
+/// SemaBuiltinPrefetch - Handle __builtin_prefetch.
+// This is declared to take (const void*, ...) and can take two
+// optional constant int args.
+bool Sema::SemaBuiltinPrefetch(CallExpr *TheCall) {
+  unsigned NumArgs = TheCall->getNumArgs();
+
+  if (NumArgs > 3)
+    return Diag(TheCall->getLocEnd(),
+             diag::err_typecheck_call_too_many_args_at_most)
+             << 0 /*function call*/ << 3 << NumArgs
+             << TheCall->getSourceRange();
+
+  // Argument 0 is checked for us and the remaining arguments must be
+  // constant integers.
+  for (unsigned i = 1; i != NumArgs; ++i) {
+    Expr *Arg = TheCall->getArg(i);
+    
+    llvm::APSInt Result;
+    if (SemaBuiltinConstantArg(TheCall, i, Result))
+      return true;
+
+    // FIXME: gcc issues a warning and rewrites these to 0. These
+    // seems especially odd for the third argument since the default
+    // is 3.
+    if (i == 1) {
+      if (Result.getLimitedValue() > 1)
+        return Diag(TheCall->getLocStart(), diag::err_argument_invalid_range)
+             << "0" << "1" << Arg->getSourceRange();
+    } else {
+      if (Result.getLimitedValue() > 3)
+        return Diag(TheCall->getLocStart(), diag::err_argument_invalid_range)
+            << "0" << "3" << Arg->getSourceRange();
+    }
+  }
+
+  return false;
+}
+
+/// SemaBuiltinConstantArg - Handle a check if argument ArgNum of CallExpr
+/// TheCall is a constant expression.
+bool Sema::SemaBuiltinConstantArg(CallExpr *TheCall, int ArgNum,
+                                  llvm::APSInt &Result) {
+  Expr *Arg = TheCall->getArg(ArgNum);
+  DeclRefExpr *DRE =cast<DeclRefExpr>(TheCall->getCallee()->IgnoreParenCasts());
+  FunctionDecl *FDecl = cast<FunctionDecl>(DRE->getDecl());
+  
+  if (Arg->isTypeDependent() || Arg->isValueDependent()) return false;
+  
+  if (!Arg->isIntegerConstantExpr(Result, Context))
+    return Diag(TheCall->getLocStart(), diag::err_constant_integer_arg_type)
+                << FDecl->getDeclName() <<  Arg->getSourceRange();
+  
+  return false;
+}
+
+/// SemaBuiltinObjectSize - Handle __builtin_object_size(void *ptr,
+/// int type). This simply type checks that type is one of the defined
+/// constants (0-3).
+// For compatibility check 0-3, llvm only handles 0 and 2.
+bool Sema::SemaBuiltinObjectSize(CallExpr *TheCall) {
+  llvm::APSInt Result;
+  
+  // Check constant-ness first.
+  if (SemaBuiltinConstantArg(TheCall, 1, Result))
+    return true;
+
+  Expr *Arg = TheCall->getArg(1);
+  if (Result.getSExtValue() < 0 || Result.getSExtValue() > 3) {
+    return Diag(TheCall->getLocStart(), diag::err_argument_invalid_range)
+             << "0" << "3" << SourceRange(Arg->getLocStart(), Arg->getLocEnd());
+  }
+
+  return false;
+}
+
+/// SemaBuiltinLongjmp - Handle __builtin_longjmp(void *env[5], int val).
+/// This checks that val is a constant 1.
+bool Sema::SemaBuiltinLongjmp(CallExpr *TheCall) {
+  Expr *Arg = TheCall->getArg(1);
+  llvm::APSInt Result;
+
+  // TODO: This is less than ideal. Overload this to take a value.
+  if (SemaBuiltinConstantArg(TheCall, 1, Result))
+    return true;
+  
+  if (Result != 1)
+    return Diag(TheCall->getLocStart(), diag::err_builtin_longjmp_invalid_val)
+             << SourceRange(Arg->getLocStart(), Arg->getLocEnd());
+
+  return false;
+}
+
+// Handle i > 1 ? "x" : "y", recursively.
+bool Sema::SemaCheckStringLiteral(const Expr *E, Expr **Args,
+                                  unsigned NumArgs, bool HasVAListArg,
+                                  unsigned format_idx, unsigned firstDataArg,
+                                  FormatStringType Type, bool inFunctionCall) {
+ tryAgain:
+  if (E->isTypeDependent() || E->isValueDependent())
+    return false;
+
+  E = E->IgnoreParenCasts();
+
+  if (E->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNotNull))
+    // Technically -Wformat-nonliteral does not warn about this case.
+    // The behavior of printf and friends in this case is implementation
+    // dependent.  Ideally if the format string cannot be null then
+    // it should have a 'nonnull' attribute in the function prototype.
+    return true;
+
+  switch (E->getStmtClass()) {
+  case Stmt::BinaryConditionalOperatorClass:
+  case Stmt::ConditionalOperatorClass: {
+    const AbstractConditionalOperator *C = cast<AbstractConditionalOperator>(E);
+    return SemaCheckStringLiteral(C->getTrueExpr(), Args, NumArgs, HasVAListArg,
+                                  format_idx, firstDataArg, Type,
+                                  inFunctionCall)
+       && SemaCheckStringLiteral(C->getFalseExpr(), Args, NumArgs, HasVAListArg,
+                                 format_idx, firstDataArg, Type,
+                                 inFunctionCall);
+  }
+
+  case Stmt::ImplicitCastExprClass: {
+    E = cast<ImplicitCastExpr>(E)->getSubExpr();
+    goto tryAgain;
+  }
+
+  case Stmt::OpaqueValueExprClass:
+    if (const Expr *src = cast<OpaqueValueExpr>(E)->getSourceExpr()) {
+      E = src;
+      goto tryAgain;
+    }
+    return false;
+
+  case Stmt::PredefinedExprClass:
+    // While __func__, etc., are technically not string literals, they
+    // cannot contain format specifiers and thus are not a security
+    // liability.
+    return true;
+      
+  case Stmt::DeclRefExprClass: {
+    const DeclRefExpr *DR = cast<DeclRefExpr>(E);
+
+    // As an exception, do not flag errors for variables binding to
+    // const string literals.
+    if (const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl())) {
+      bool isConstant = false;
+      QualType T = DR->getType();
+
+      if (const ArrayType *AT = Context.getAsArrayType(T)) {
+        isConstant = AT->getElementType().isConstant(Context);
+      } else if (const PointerType *PT = T->getAs<PointerType>()) {
+        isConstant = T.isConstant(Context) &&
+                     PT->getPointeeType().isConstant(Context);
+      } else if (T->isObjCObjectPointerType()) {
+        // In ObjC, there is usually no "const ObjectPointer" type,
+        // so don't check if the pointee type is constant.
+        isConstant = T.isConstant(Context);
+      }
+
+      if (isConstant) {
+        if (const Expr *Init = VD->getAnyInitializer())
+          return SemaCheckStringLiteral(Init, Args, NumArgs,
+                                        HasVAListArg, format_idx, firstDataArg,
+                                        Type, /*inFunctionCall*/false);
+      }
+
+      // For vprintf* functions (i.e., HasVAListArg==true), we add a
+      // special check to see if the format string is a function parameter
+      // of the function calling the printf function.  If the function
+      // has an attribute indicating it is a printf-like function, then we
+      // should suppress warnings concerning non-literals being used in a call
+      // to a vprintf function.  For example:
+      //
+      // void
+      // logmessage(char const *fmt __attribute__ (format (printf, 1, 2)), ...){
+      //      va_list ap;
+      //      va_start(ap, fmt);
+      //      vprintf(fmt, ap);  // Do NOT emit a warning about "fmt".
+      //      ...
+      //
+      if (HasVAListArg) {
+        if (const ParmVarDecl *PV = dyn_cast<ParmVarDecl>(VD)) {
+          if (const NamedDecl *ND = dyn_cast<NamedDecl>(PV->getDeclContext())) {
+            int PVIndex = PV->getFunctionScopeIndex() + 1;
+            for (specific_attr_iterator<FormatAttr>
+                 i = ND->specific_attr_begin<FormatAttr>(),
+                 e = ND->specific_attr_end<FormatAttr>(); i != e ; ++i) {
+              FormatAttr *PVFormat = *i;
+              // adjust for implicit parameter
+              if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(ND))
+                if (MD->isInstance())
+                  ++PVIndex;
+              // We also check if the formats are compatible.
+              // We can't pass a 'scanf' string to a 'printf' function.
+              if (PVIndex == PVFormat->getFormatIdx() &&
+                  Type == GetFormatStringType(PVFormat))
+                return true;
+            }
+          }
+        }
+      }
+    }
+
+    return false;
+  }
+
+  case Stmt::CallExprClass:
+  case Stmt::CXXMemberCallExprClass: {
+    const CallExpr *CE = cast<CallExpr>(E);
+    if (const NamedDecl *ND = dyn_cast_or_null<NamedDecl>(CE->getCalleeDecl())) {
+      if (const FormatArgAttr *FA = ND->getAttr<FormatArgAttr>()) {
+        unsigned ArgIndex = FA->getFormatIdx();
+        if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(ND))
+          if (MD->isInstance())
+            --ArgIndex;
+        const Expr *Arg = CE->getArg(ArgIndex - 1);
+
+        return SemaCheckStringLiteral(Arg, Args, NumArgs, HasVAListArg,
+                                      format_idx, firstDataArg, Type,
+                                      inFunctionCall);
+      }
+    }
+
+    return false;
+  }
+  case Stmt::ObjCStringLiteralClass:
+  case Stmt::StringLiteralClass: {
+    const StringLiteral *StrE = NULL;
+
+    if (const ObjCStringLiteral *ObjCFExpr = dyn_cast<ObjCStringLiteral>(E))
+      StrE = ObjCFExpr->getString();
+    else
+      StrE = cast<StringLiteral>(E);
+
+    if (StrE) {
+      CheckFormatString(StrE, E, Args, NumArgs, HasVAListArg, format_idx,
+                        firstDataArg, Type, inFunctionCall);
+      return true;
+    }
+
+    return false;
+  }
+
+  default:
+    return false;
+  }
+}
+
+void
+Sema::CheckNonNullArguments(const NonNullAttr *NonNull,
+                            const Expr * const *ExprArgs,
+                            SourceLocation CallSiteLoc) {
+  for (NonNullAttr::args_iterator i = NonNull->args_begin(),
+                                  e = NonNull->args_end();
+       i != e; ++i) {
+    const Expr *ArgExpr = ExprArgs[*i];
+    if (ArgExpr->isNullPointerConstant(Context,
+                                       Expr::NPC_ValueDependentIsNotNull))
+      Diag(CallSiteLoc, diag::warn_null_arg) << ArgExpr->getSourceRange();
+  }
+}
+
+Sema::FormatStringType Sema::GetFormatStringType(const FormatAttr *Format) {
+  return llvm::StringSwitch<FormatStringType>(Format->getType())
+  .Case("scanf", FST_Scanf)
+  .Cases("printf", "printf0", FST_Printf)
+  .Cases("NSString", "CFString", FST_NSString)
+  .Case("strftime", FST_Strftime)
+  .Case("strfmon", FST_Strfmon)
+  .Cases("kprintf", "cmn_err", "vcmn_err", "zcmn_err", FST_Kprintf)
+  .Default(FST_Unknown);
+}
+
+/// CheckPrintfScanfArguments - Check calls to printf and scanf (and similar
+/// functions) for correct use of format strings.
+void Sema::CheckFormatArguments(const FormatAttr *Format, CallExpr *TheCall) {
+  bool IsCXXMember = false;
+  // The way the format attribute works in GCC, the implicit this argument
+  // of member functions is counted. However, it doesn't appear in our own
+  // lists, so decrement format_idx in that case.
+  IsCXXMember = isa<CXXMemberCallExpr>(TheCall);
+  CheckFormatArguments(Format, TheCall->getArgs(), TheCall->getNumArgs(),
+                       IsCXXMember, TheCall->getRParenLoc(), 
+                       TheCall->getCallee()->getSourceRange());
+}
+
+void Sema::CheckFormatArguments(const FormatAttr *Format, Expr **Args,
+                                unsigned NumArgs, bool IsCXXMember,
+                                SourceLocation Loc, SourceRange Range) {
+  bool HasVAListArg = Format->getFirstArg() == 0;
+  unsigned format_idx = Format->getFormatIdx() - 1;
+  unsigned firstDataArg = HasVAListArg ? 0 : Format->getFirstArg() - 1;
+  if (IsCXXMember) {
+    if (format_idx == 0)
+      return;
+    --format_idx;
+    if(firstDataArg != 0)
+      --firstDataArg;
+  }
+  CheckFormatArguments(Args, NumArgs, HasVAListArg, format_idx,
+                       firstDataArg, GetFormatStringType(Format), Loc, Range);
+}
+
+void Sema::CheckFormatArguments(Expr **Args, unsigned NumArgs,
+                                bool HasVAListArg, unsigned format_idx,
+                                unsigned firstDataArg, FormatStringType Type,
+                                SourceLocation Loc, SourceRange Range) {
+  // CHECK: printf/scanf-like function is called with no format string.
+  if (format_idx >= NumArgs) {
+    Diag(Loc, diag::warn_missing_format_string) << Range;
+    return;
+  }
+
+  const Expr *OrigFormatExpr = Args[format_idx]->IgnoreParenCasts();
+
+  // CHECK: format string is not a string literal.
+  //
+  // Dynamically generated format strings are difficult to
+  // automatically vet at compile time.  Requiring that format strings
+  // are string literals: (1) permits the checking of format strings by
+  // the compiler and thereby (2) can practically remove the source of
+  // many format string exploits.
+
+  // Format string can be either ObjC string (e.g. @"%d") or
+  // C string (e.g. "%d")
+  // ObjC string uses the same format specifiers as C string, so we can use
+  // the same format string checking logic for both ObjC and C strings.
+  if (SemaCheckStringLiteral(OrigFormatExpr, Args, NumArgs, HasVAListArg,
+                             format_idx, firstDataArg, Type))
+    return;  // Literal format string found, check done!
+
+  // Strftime is particular as it always uses a single 'time' argument,
+  // so it is safe to pass a non-literal string.
+  if (Type == FST_Strftime)
+    return;
+
+  // Do not emit diag when the string param is a macro expansion and the
+  // format is either NSString or CFString. This is a hack to prevent
+  // diag when using the NSLocalizedString and CFCopyLocalizedString macros
+  // which are usually used in place of NS and CF string literals.
+  if (Type == FST_NSString && Args[format_idx]->getLocStart().isMacroID())
+    return;
+
+  // If there are no arguments specified, warn with -Wformat-security, otherwise
+  // warn only with -Wformat-nonliteral.
+  if (NumArgs == format_idx+1)
+    Diag(Args[format_idx]->getLocStart(),
+         diag::warn_format_nonliteral_noargs)
+      << OrigFormatExpr->getSourceRange();
+  else
+    Diag(Args[format_idx]->getLocStart(),
+         diag::warn_format_nonliteral)
+           << OrigFormatExpr->getSourceRange();
+}
+
+namespace {
+class CheckFormatHandler : public analyze_format_string::FormatStringHandler {
+protected:
+  Sema &S;
+  const StringLiteral *FExpr;
+  const Expr *OrigFormatExpr;
+  const unsigned FirstDataArg;
+  const unsigned NumDataArgs;
+  const bool IsObjCLiteral;
+  const char *Beg; // Start of format string.
+  const bool HasVAListArg;
+  const Expr * const *Args;
+  const unsigned NumArgs;
+  unsigned FormatIdx;
+  llvm::BitVector CoveredArgs;
+  bool usesPositionalArgs;
+  bool atFirstArg;
+  bool inFunctionCall;
+public:
+  CheckFormatHandler(Sema &s, const StringLiteral *fexpr,
+                     const Expr *origFormatExpr, unsigned firstDataArg,
+                     unsigned numDataArgs, bool isObjCLiteral,
+                     const char *beg, bool hasVAListArg,
+                     Expr **args, unsigned numArgs,
+                     unsigned formatIdx, bool inFunctionCall)
+    : S(s), FExpr(fexpr), OrigFormatExpr(origFormatExpr),
+      FirstDataArg(firstDataArg),
+      NumDataArgs(numDataArgs),
+      IsObjCLiteral(isObjCLiteral), Beg(beg),
+      HasVAListArg(hasVAListArg),
+      Args(args), NumArgs(numArgs), FormatIdx(formatIdx),
+      usesPositionalArgs(false), atFirstArg(true),
+      inFunctionCall(inFunctionCall) {
+        CoveredArgs.resize(numDataArgs);
+        CoveredArgs.reset();
+      }
+
+  void DoneProcessing();
+
+  void HandleIncompleteSpecifier(const char *startSpecifier,
+                                 unsigned specifierLen);
+
+  void HandleNonStandardLengthModifier(
+      const analyze_format_string::LengthModifier &LM,
+      const char *startSpecifier, unsigned specifierLen);
+
+  void HandleNonStandardConversionSpecifier(
+      const analyze_format_string::ConversionSpecifier &CS,
+      const char *startSpecifier, unsigned specifierLen);
+
+  void HandleNonStandardConversionSpecification(
+      const analyze_format_string::LengthModifier &LM,
+      const analyze_format_string::ConversionSpecifier &CS,
+      const char *startSpecifier, unsigned specifierLen);
+
+  virtual void HandlePosition(const char *startPos, unsigned posLen);
+
+  virtual void HandleInvalidPosition(const char *startSpecifier,
+                                     unsigned specifierLen,
+                                     analyze_format_string::PositionContext p);
+
+  virtual void HandleZeroPosition(const char *startPos, unsigned posLen);
+
+  void HandleNullChar(const char *nullCharacter);
+
+  template <typename Range>
+  static void EmitFormatDiagnostic(Sema &S, bool inFunctionCall,
+                                   const Expr *ArgumentExpr,
+                                   PartialDiagnostic PDiag,
+                                   SourceLocation StringLoc,
+                                   bool IsStringLocation, Range StringRange,
+                                   FixItHint Fixit = FixItHint());
+
+protected:
+  bool HandleInvalidConversionSpecifier(unsigned argIndex, SourceLocation Loc,
+                                        const char *startSpec,
+                                        unsigned specifierLen,
+                                        const char *csStart, unsigned csLen);
+
+  void HandlePositionalNonpositionalArgs(SourceLocation Loc,
+                                         const char *startSpec,
+                                         unsigned specifierLen);
+  
+  SourceRange getFormatStringRange();
+  CharSourceRange getSpecifierRange(const char *startSpecifier,
+                                    unsigned specifierLen);
+  SourceLocation getLocationOfByte(const char *x);
+
+  const Expr *getDataArg(unsigned i) const;
+  
+  bool CheckNumArgs(const analyze_format_string::FormatSpecifier &FS,
+                    const analyze_format_string::ConversionSpecifier &CS,
+                    const char *startSpecifier, unsigned specifierLen,
+                    unsigned argIndex);
+
+  template <typename Range>
+  void EmitFormatDiagnostic(PartialDiagnostic PDiag, SourceLocation StringLoc,
+                            bool IsStringLocation, Range StringRange,
+                            FixItHint Fixit = FixItHint());
+
+  void CheckPositionalAndNonpositionalArgs(
+      const analyze_format_string::FormatSpecifier *FS);
+};
+}
+
+SourceRange CheckFormatHandler::getFormatStringRange() {
+  return OrigFormatExpr->getSourceRange();
+}
+
+CharSourceRange CheckFormatHandler::
+getSpecifierRange(const char *startSpecifier, unsigned specifierLen) {
+  SourceLocation Start = getLocationOfByte(startSpecifier);
+  SourceLocation End   = getLocationOfByte(startSpecifier + specifierLen - 1);
+
+  // Advance the end SourceLocation by one due to half-open ranges.
+  End = End.getLocWithOffset(1);
+
+  return CharSourceRange::getCharRange(Start, End);
+}
+
+SourceLocation CheckFormatHandler::getLocationOfByte(const char *x) {
+  return S.getLocationOfStringLiteralByte(FExpr, x - Beg);
+}
+
+void CheckFormatHandler::HandleIncompleteSpecifier(const char *startSpecifier,
+                                                   unsigned specifierLen){
+  EmitFormatDiagnostic(S.PDiag(diag::warn_printf_incomplete_specifier),
+                       getLocationOfByte(startSpecifier),
+                       /*IsStringLocation*/true,
+                       getSpecifierRange(startSpecifier, specifierLen));
+}
+
+void CheckFormatHandler::HandleNonStandardLengthModifier(
+    const analyze_format_string::LengthModifier &LM,
+    const char *startSpecifier, unsigned specifierLen) {
+  EmitFormatDiagnostic(S.PDiag(diag::warn_format_non_standard) << LM.toString()
+                       << 0,
+                       getLocationOfByte(LM.getStart()),
+                       /*IsStringLocation*/true,
+                       getSpecifierRange(startSpecifier, specifierLen));
+}
+
+void CheckFormatHandler::HandleNonStandardConversionSpecifier(
+    const analyze_format_string::ConversionSpecifier &CS,
+    const char *startSpecifier, unsigned specifierLen) {
+  EmitFormatDiagnostic(S.PDiag(diag::warn_format_non_standard) << CS.toString()
+                       << 1,
+                       getLocationOfByte(CS.getStart()),
+                       /*IsStringLocation*/true,
+                       getSpecifierRange(startSpecifier, specifierLen));
+}
+
+void CheckFormatHandler::HandleNonStandardConversionSpecification(
+    const analyze_format_string::LengthModifier &LM,
+    const analyze_format_string::ConversionSpecifier &CS,
+    const char *startSpecifier, unsigned specifierLen) {
+  EmitFormatDiagnostic(S.PDiag(diag::warn_format_non_standard_conversion_spec)
+                       << LM.toString() << CS.toString(),
+                       getLocationOfByte(LM.getStart()),
+                       /*IsStringLocation*/true,
+                       getSpecifierRange(startSpecifier, specifierLen));
+}
+
+void CheckFormatHandler::HandlePosition(const char *startPos,
+                                        unsigned posLen) {
+  EmitFormatDiagnostic(S.PDiag(diag::warn_format_non_standard_positional_arg),
+                               getLocationOfByte(startPos),
+                               /*IsStringLocation*/true,
+                               getSpecifierRange(startPos, posLen));
+}
+
+void
+CheckFormatHandler::HandleInvalidPosition(const char *startPos, unsigned posLen,
+                                     analyze_format_string::PositionContext p) {
+  EmitFormatDiagnostic(S.PDiag(diag::warn_format_invalid_positional_specifier)
+                         << (unsigned) p,
+                       getLocationOfByte(startPos), /*IsStringLocation*/true,
+                       getSpecifierRange(startPos, posLen));
+}
+
+void CheckFormatHandler::HandleZeroPosition(const char *startPos,
+                                            unsigned posLen) {
+  EmitFormatDiagnostic(S.PDiag(diag::warn_format_zero_positional_specifier),
+                               getLocationOfByte(startPos),
+                               /*IsStringLocation*/true,
+                               getSpecifierRange(startPos, posLen));
+}
+
+void CheckFormatHandler::HandleNullChar(const char *nullCharacter) {
+  if (!IsObjCLiteral) {
+    // The presence of a null character is likely an error.
+    EmitFormatDiagnostic(
+      S.PDiag(diag::warn_printf_format_string_contains_null_char),
+      getLocationOfByte(nullCharacter), /*IsStringLocation*/true,
+      getFormatStringRange());
+  }
+}
+
+const Expr *CheckFormatHandler::getDataArg(unsigned i) const {
+  return Args[FirstDataArg + i];
+}
+
+void CheckFormatHandler::DoneProcessing() {
+    // Does the number of data arguments exceed the number of
+    // format conversions in the format string?
+  if (!HasVAListArg) {
+      // Find any arguments that weren't covered.
+    CoveredArgs.flip();
+    signed notCoveredArg = CoveredArgs.find_first();
+    if (notCoveredArg >= 0) {
+      assert((unsigned)notCoveredArg < NumDataArgs);
+      EmitFormatDiagnostic(S.PDiag(diag::warn_printf_data_arg_not_used),
+                           getDataArg((unsigned) notCoveredArg)->getLocStart(),
+                           /*IsStringLocation*/false, getFormatStringRange());
+    }
+  }
+}
+
+bool
+CheckFormatHandler::HandleInvalidConversionSpecifier(unsigned argIndex,
+                                                     SourceLocation Loc,
+                                                     const char *startSpec,
+                                                     unsigned specifierLen,
+                                                     const char *csStart,
+                                                     unsigned csLen) {
+  
+  bool keepGoing = true;
+  if (argIndex < NumDataArgs) {
+    // Consider the argument coverered, even though the specifier doesn't
+    // make sense.
+    CoveredArgs.set(argIndex);
+  }
+  else {
+    // If argIndex exceeds the number of data arguments we
+    // don't issue a warning because that is just a cascade of warnings (and
+    // they may have intended '%%' anyway). We don't want to continue processing
+    // the format string after this point, however, as we will like just get
+    // gibberish when trying to match arguments.
+    keepGoing = false;
+  }
+  
+  EmitFormatDiagnostic(S.PDiag(diag::warn_format_invalid_conversion)
+                         << StringRef(csStart, csLen),
+                       Loc, /*IsStringLocation*/true,
+                       getSpecifierRange(startSpec, specifierLen));
+  
+  return keepGoing;
+}
+
+void
+CheckFormatHandler::HandlePositionalNonpositionalArgs(SourceLocation Loc,
+                                                      const char *startSpec,
+                                                      unsigned specifierLen) {
+  EmitFormatDiagnostic(
+    S.PDiag(diag::warn_format_mix_positional_nonpositional_args),
+    Loc, /*isStringLoc*/true, getSpecifierRange(startSpec, specifierLen));
+}
+
+bool
+CheckFormatHandler::CheckNumArgs(
+  const analyze_format_string::FormatSpecifier &FS,
+  const analyze_format_string::ConversionSpecifier &CS,
+  const char *startSpecifier, unsigned specifierLen, unsigned argIndex) {
+
+  if (argIndex >= NumDataArgs) {
+    PartialDiagnostic PDiag = FS.usesPositionalArg()
+      ? (S.PDiag(diag::warn_printf_positional_arg_exceeds_data_args)
+           << (argIndex+1) << NumDataArgs)
+      : S.PDiag(diag::warn_printf_insufficient_data_args);
+    EmitFormatDiagnostic(
+      PDiag, getLocationOfByte(CS.getStart()), /*IsStringLocation*/true,
+      getSpecifierRange(startSpecifier, specifierLen));
+    return false;
+  }
+  return true;
+}
+
+template<typename Range>
+void CheckFormatHandler::EmitFormatDiagnostic(PartialDiagnostic PDiag,
+                                              SourceLocation Loc,
+                                              bool IsStringLocation,
+                                              Range StringRange,
+                                              FixItHint FixIt) {
+  EmitFormatDiagnostic(S, inFunctionCall, Args[FormatIdx], PDiag,
+                       Loc, IsStringLocation, StringRange, FixIt);
+}
+
+/// \brief If the format string is not within the funcion call, emit a note
+/// so that the function call and string are in diagnostic messages.
+///
+/// \param inFunctionCall if true, the format string is within the function
+/// call and only one diagnostic message will be produced.  Otherwise, an
+/// extra note will be emitted pointing to location of the format string.
+///
+/// \param ArgumentExpr the expression that is passed as the format string
+/// argument in the function call.  Used for getting locations when two
+/// diagnostics are emitted.
+///
+/// \param PDiag the callee should already have provided any strings for the
+/// diagnostic message.  This function only adds locations and fixits
+/// to diagnostics.
+///
+/// \param Loc primary location for diagnostic.  If two diagnostics are
+/// required, one will be at Loc and a new SourceLocation will be created for
+/// the other one.
+///
+/// \param IsStringLocation if true, Loc points to the format string should be
+/// used for the note.  Otherwise, Loc points to the argument list and will
+/// be used with PDiag.
+///
+/// \param StringRange some or all of the string to highlight.  This is
+/// templated so it can accept either a CharSourceRange or a SourceRange.
+///
+/// \param Fixit optional fix it hint for the format string.
+template<typename Range>
+void CheckFormatHandler::EmitFormatDiagnostic(Sema &S, bool InFunctionCall,
+                                              const Expr *ArgumentExpr,
+                                              PartialDiagnostic PDiag,
+                                              SourceLocation Loc,
+                                              bool IsStringLocation,
+                                              Range StringRange,
+                                              FixItHint FixIt) {
+  if (InFunctionCall)
+    S.Diag(Loc, PDiag) << StringRange << FixIt;
+  else {
+    S.Diag(IsStringLocation ? ArgumentExpr->getExprLoc() : Loc, PDiag)
+      << ArgumentExpr->getSourceRange();
+    S.Diag(IsStringLocation ? Loc : StringRange.getBegin(),
+           diag::note_format_string_defined)
+      << StringRange << FixIt;
+  }
+}
+
+//===--- CHECK: Printf format string checking ------------------------------===//
+
+namespace {
+class CheckPrintfHandler : public CheckFormatHandler {
+public:
+  CheckPrintfHandler(Sema &s, const StringLiteral *fexpr,
+                     const Expr *origFormatExpr, unsigned firstDataArg,
+                     unsigned numDataArgs, bool isObjCLiteral,
+                     const char *beg, bool hasVAListArg,
+                     Expr **Args, unsigned NumArgs,
+                     unsigned formatIdx, bool inFunctionCall)
+  : CheckFormatHandler(s, fexpr, origFormatExpr, firstDataArg,
+                       numDataArgs, isObjCLiteral, beg, hasVAListArg,
+                       Args, NumArgs, formatIdx, inFunctionCall) {}
+  
+  
+  bool HandleInvalidPrintfConversionSpecifier(
+                                      const analyze_printf::PrintfSpecifier &FS,
+                                      const char *startSpecifier,
+                                      unsigned specifierLen);
+  
+  bool HandlePrintfSpecifier(const analyze_printf::PrintfSpecifier &FS,
+                             const char *startSpecifier,
+                             unsigned specifierLen);
+  
+  bool HandleAmount(const analyze_format_string::OptionalAmount &Amt, unsigned k,
+                    const char *startSpecifier, unsigned specifierLen);
+  void HandleInvalidAmount(const analyze_printf::PrintfSpecifier &FS,
+                           const analyze_printf::OptionalAmount &Amt,
+                           unsigned type,
+                           const char *startSpecifier, unsigned specifierLen);
+  void HandleFlag(const analyze_printf::PrintfSpecifier &FS,
+                  const analyze_printf::OptionalFlag &flag,
+                  const char *startSpecifier, unsigned specifierLen);
+  void HandleIgnoredFlag(const analyze_printf::PrintfSpecifier &FS,
+                         const analyze_printf::OptionalFlag &ignoredFlag,
+                         const analyze_printf::OptionalFlag &flag,
+                         const char *startSpecifier, unsigned specifierLen);
+};  
+}
+
+bool CheckPrintfHandler::HandleInvalidPrintfConversionSpecifier(
+                                      const analyze_printf::PrintfSpecifier &FS,
+                                      const char *startSpecifier,
+                                      unsigned specifierLen) {
+  const analyze_printf::PrintfConversionSpecifier &CS =
+    FS.getConversionSpecifier();
+  
+  return HandleInvalidConversionSpecifier(FS.getArgIndex(),
+                                          getLocationOfByte(CS.getStart()),
+                                          startSpecifier, specifierLen,
+                                          CS.getStart(), CS.getLength());
+}
+
+bool CheckPrintfHandler::HandleAmount(
+                               const analyze_format_string::OptionalAmount &Amt,
+                               unsigned k, const char *startSpecifier,
+                               unsigned specifierLen) {
+
+  if (Amt.hasDataArgument()) {
+    if (!HasVAListArg) {
+      unsigned argIndex = Amt.getArgIndex();
+      if (argIndex >= NumDataArgs) {
+        EmitFormatDiagnostic(S.PDiag(diag::warn_printf_asterisk_missing_arg)
+                               << k,
+                             getLocationOfByte(Amt.getStart()),
+                             /*IsStringLocation*/true,
+                             getSpecifierRange(startSpecifier, specifierLen));
+        // Don't do any more checking.  We will just emit
+        // spurious errors.
+        return false;
+      }
+
+      // Type check the data argument.  It should be an 'int'.
+      // Although not in conformance with C99, we also allow the argument to be
+      // an 'unsigned int' as that is a reasonably safe case.  GCC also
+      // doesn't emit a warning for that case.
+      CoveredArgs.set(argIndex);
+      const Expr *Arg = getDataArg(argIndex);
+      QualType T = Arg->getType();
+
+      const analyze_printf::ArgTypeResult &ATR = Amt.getArgType(S.Context);
+      assert(ATR.isValid());
+
+      if (!ATR.matchesType(S.Context, T)) {
+        EmitFormatDiagnostic(S.PDiag(diag::warn_printf_asterisk_wrong_type)
+                               << k << ATR.getRepresentativeTypeName(S.Context)
+                               << T << Arg->getSourceRange(),
+                             getLocationOfByte(Amt.getStart()),
+                             /*IsStringLocation*/true,
+                             getSpecifierRange(startSpecifier, specifierLen));
+        // Don't do any more checking.  We will just emit
+        // spurious errors.
+        return false;
+      }
+    }
+  }
+  return true;
+}
+
+void CheckPrintfHandler::HandleInvalidAmount(
+                                      const analyze_printf::PrintfSpecifier &FS,
+                                      const analyze_printf::OptionalAmount &Amt,
+                                      unsigned type,
+                                      const char *startSpecifier,
+                                      unsigned specifierLen) {
+  const analyze_printf::PrintfConversionSpecifier &CS =
+    FS.getConversionSpecifier();
+
+  FixItHint fixit =
+    Amt.getHowSpecified() == analyze_printf::OptionalAmount::Constant
+      ? FixItHint::CreateRemoval(getSpecifierRange(Amt.getStart(),
+                                 Amt.getConstantLength()))
+      : FixItHint();
+
+  EmitFormatDiagnostic(S.PDiag(diag::warn_printf_nonsensical_optional_amount)
+                         << type << CS.toString(),
+                       getLocationOfByte(Amt.getStart()),
+                       /*IsStringLocation*/true,
+                       getSpecifierRange(startSpecifier, specifierLen),
+                       fixit);
+}
+
+void CheckPrintfHandler::HandleFlag(const analyze_printf::PrintfSpecifier &FS,
+                                    const analyze_printf::OptionalFlag &flag,
+                                    const char *startSpecifier,
+                                    unsigned specifierLen) {
+  // Warn about pointless flag with a fixit removal.
+  const analyze_printf::PrintfConversionSpecifier &CS =
+    FS.getConversionSpecifier();
+  EmitFormatDiagnostic(S.PDiag(diag::warn_printf_nonsensical_flag)
+                         << flag.toString() << CS.toString(),
+                       getLocationOfByte(flag.getPosition()),
+                       /*IsStringLocation*/true,
+                       getSpecifierRange(startSpecifier, specifierLen),
+                       FixItHint::CreateRemoval(
+                         getSpecifierRange(flag.getPosition(), 1)));
+}
+
+void CheckPrintfHandler::HandleIgnoredFlag(
+                                const analyze_printf::PrintfSpecifier &FS,
+                                const analyze_printf::OptionalFlag &ignoredFlag,
+                                const analyze_printf::OptionalFlag &flag,
+                                const char *startSpecifier,
+                                unsigned specifierLen) {
+  // Warn about ignored flag with a fixit removal.
+  EmitFormatDiagnostic(S.PDiag(diag::warn_printf_ignored_flag)
+                         << ignoredFlag.toString() << flag.toString(),
+                       getLocationOfByte(ignoredFlag.getPosition()),
+                       /*IsStringLocation*/true,
+                       getSpecifierRange(startSpecifier, specifierLen),
+                       FixItHint::CreateRemoval(
+                         getSpecifierRange(ignoredFlag.getPosition(), 1)));
+}
+
+bool
+CheckPrintfHandler::HandlePrintfSpecifier(const analyze_printf::PrintfSpecifier
+                                            &FS,
+                                          const char *startSpecifier,
+                                          unsigned specifierLen) {
+
+  using namespace analyze_format_string;
+  using namespace analyze_printf;  
+  const PrintfConversionSpecifier &CS = FS.getConversionSpecifier();
+
+  if (FS.consumesDataArgument()) {
+    if (atFirstArg) {
+        atFirstArg = false;
+        usesPositionalArgs = FS.usesPositionalArg();
+    }
+    else if (usesPositionalArgs != FS.usesPositionalArg()) {
+      HandlePositionalNonpositionalArgs(getLocationOfByte(CS.getStart()),
+                                        startSpecifier, specifierLen);
+      return false;
+    }
+  }
+
+  // First check if the field width, precision, and conversion specifier
+  // have matching data arguments.
+  if (!HandleAmount(FS.getFieldWidth(), /* field width */ 0,
+                    startSpecifier, specifierLen)) {
+    return false;
+  }
+
+  if (!HandleAmount(FS.getPrecision(), /* precision */ 1,
+                    startSpecifier, specifierLen)) {
+    return false;
+  }
+
+  if (!CS.consumesDataArgument()) {
+    // FIXME: Technically specifying a precision or field width here
+    // makes no sense.  Worth issuing a warning at some point.
+    return true;
+  }
+
+  // Consume the argument.
+  unsigned argIndex = FS.getArgIndex();
+  if (argIndex < NumDataArgs) {
+    // The check to see if the argIndex is valid will come later.
+    // We set the bit here because we may exit early from this
+    // function if we encounter some other error.
+    CoveredArgs.set(argIndex);
+  }
+
+  // Check for using an Objective-C specific conversion specifier
+  // in a non-ObjC literal.
+  if (!IsObjCLiteral && CS.isObjCArg()) {
+    return HandleInvalidPrintfConversionSpecifier(FS, startSpecifier,
+                                                  specifierLen);
+  }
+
+  // Check for invalid use of field width
+  if (!FS.hasValidFieldWidth()) {
+    HandleInvalidAmount(FS, FS.getFieldWidth(), /* field width */ 0,
+        startSpecifier, specifierLen);
+  }
+
+  // Check for invalid use of precision
+  if (!FS.hasValidPrecision()) {
+    HandleInvalidAmount(FS, FS.getPrecision(), /* precision */ 1,
+        startSpecifier, specifierLen);
+  }
+
+  // Check each flag does not conflict with any other component.
+  if (!FS.hasValidThousandsGroupingPrefix())
+    HandleFlag(FS, FS.hasThousandsGrouping(), startSpecifier, specifierLen);
+  if (!FS.hasValidLeadingZeros())
+    HandleFlag(FS, FS.hasLeadingZeros(), startSpecifier, specifierLen);
+  if (!FS.hasValidPlusPrefix())
+    HandleFlag(FS, FS.hasPlusPrefix(), startSpecifier, specifierLen);
+  if (!FS.hasValidSpacePrefix())
+    HandleFlag(FS, FS.hasSpacePrefix(), startSpecifier, specifierLen);
+  if (!FS.hasValidAlternativeForm())
+    HandleFlag(FS, FS.hasAlternativeForm(), startSpecifier, specifierLen);
+  if (!FS.hasValidLeftJustified())
+    HandleFlag(FS, FS.isLeftJustified(), startSpecifier, specifierLen);
+
+  // Check that flags are not ignored by another flag
+  if (FS.hasSpacePrefix() && FS.hasPlusPrefix()) // ' ' ignored by '+'
+    HandleIgnoredFlag(FS, FS.hasSpacePrefix(), FS.hasPlusPrefix(),
+        startSpecifier, specifierLen);
+  if (FS.hasLeadingZeros() && FS.isLeftJustified()) // '0' ignored by '-'
+    HandleIgnoredFlag(FS, FS.hasLeadingZeros(), FS.isLeftJustified(),
+            startSpecifier, specifierLen);
+
+  // Check the length modifier is valid with the given conversion specifier.
+  const LengthModifier &LM = FS.getLengthModifier();
+  if (!FS.hasValidLengthModifier())
+    EmitFormatDiagnostic(S.PDiag(diag::warn_format_nonsensical_length)
+                           << LM.toString() << CS.toString(),
+                         getLocationOfByte(LM.getStart()),
+                         /*IsStringLocation*/true,
+                         getSpecifierRange(startSpecifier, specifierLen),
+                         FixItHint::CreateRemoval(
+                           getSpecifierRange(LM.getStart(),
+                                             LM.getLength())));
+  if (!FS.hasStandardLengthModifier())
+    HandleNonStandardLengthModifier(LM, startSpecifier, specifierLen);
+  if (!FS.hasStandardConversionSpecifier(S.getLangOpts()))
+    HandleNonStandardConversionSpecifier(CS, startSpecifier, specifierLen);
+  if (!FS.hasStandardLengthConversionCombination())
+    HandleNonStandardConversionSpecification(LM, CS, startSpecifier,
+                                             specifierLen);
+
+  // Are we using '%n'?
+  if (CS.getKind() == ConversionSpecifier::nArg) {
+    // Issue a warning about this being a possible security issue.
+    EmitFormatDiagnostic(S.PDiag(diag::warn_printf_write_back),
+                         getLocationOfByte(CS.getStart()),
+                         /*IsStringLocation*/true,
+                         getSpecifierRange(startSpecifier, specifierLen));
+    // Continue checking the other format specifiers.
+    return true;
+  }
+
+  // The remaining checks depend on the data arguments.
+  if (HasVAListArg)
+    return true;
+
+  if (!CheckNumArgs(FS, CS, startSpecifier, specifierLen, argIndex))
+    return false;
+
+  // Now type check the data expression that matches the
+  // format specifier.
+  const Expr *Ex = getDataArg(argIndex);
+  const analyze_printf::ArgTypeResult &ATR = FS.getArgType(S.Context,
+                                                           IsObjCLiteral);
+  if (ATR.isValid() && !ATR.matchesType(S.Context, Ex->getType())) {
+    // Check if we didn't match because of an implicit cast from a 'char'
+    // or 'short' to an 'int'.  This is done because printf is a varargs
+    // function.
+    if (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(Ex))
+      if (ICE->getType() == S.Context.IntTy) {
+        // All further checking is done on the subexpression.
+        Ex = ICE->getSubExpr();
+        if (ATR.matchesType(S.Context, Ex->getType()))
+          return true;
+      }
+
+    // We may be able to offer a FixItHint if it is a supported type.
+    PrintfSpecifier fixedFS = FS;
+    bool success = fixedFS.fixType(Ex->getType(), S.getLangOpts(),
+                                   S.Context, IsObjCLiteral);
+
+    if (success) {
+      // Get the fix string from the fixed format specifier
+      SmallString<128> buf;
+      llvm::raw_svector_ostream os(buf);
+      fixedFS.toString(os);
+
+      EmitFormatDiagnostic(
+        S.PDiag(diag::warn_printf_conversion_argument_type_mismatch)
+          << ATR.getRepresentativeTypeName(S.Context) << Ex->getType()
+          << Ex->getSourceRange(),
+        getLocationOfByte(CS.getStart()),
+        /*IsStringLocation*/true,
+        getSpecifierRange(startSpecifier, specifierLen),
+        FixItHint::CreateReplacement(
+          getSpecifierRange(startSpecifier, specifierLen),
+          os.str()));
+    }
+    else {
+      EmitFormatDiagnostic(
+        S.PDiag(diag::warn_printf_conversion_argument_type_mismatch)
+          << ATR.getRepresentativeTypeName(S.Context) << Ex->getType()
+          << getSpecifierRange(startSpecifier, specifierLen)
+          << Ex->getSourceRange(),
+        getLocationOfByte(CS.getStart()),
+        true,
+        getSpecifierRange(startSpecifier, specifierLen));
+    }
+  }
+
+  return true;
+}
+
+//===--- CHECK: Scanf format string checking ------------------------------===//
+
+namespace {  
+class CheckScanfHandler : public CheckFormatHandler {
+public:
+  CheckScanfHandler(Sema &s, const StringLiteral *fexpr,
+                    const Expr *origFormatExpr, unsigned firstDataArg,
+                    unsigned numDataArgs, bool isObjCLiteral,
+                    const char *beg, bool hasVAListArg,
+                    Expr **Args, unsigned NumArgs,
+                    unsigned formatIdx, bool inFunctionCall)
+  : CheckFormatHandler(s, fexpr, origFormatExpr, firstDataArg,
+                       numDataArgs, isObjCLiteral, beg, hasVAListArg,
+                       Args, NumArgs, formatIdx, inFunctionCall) {}
+  
+  bool HandleScanfSpecifier(const analyze_scanf::ScanfSpecifier &FS,
+                            const char *startSpecifier,
+                            unsigned specifierLen);
+  
+  bool HandleInvalidScanfConversionSpecifier(
+          const analyze_scanf::ScanfSpecifier &FS,
+          const char *startSpecifier,
+          unsigned specifierLen);
+
+  void HandleIncompleteScanList(const char *start, const char *end);
+};
+}
+
+void CheckScanfHandler::HandleIncompleteScanList(const char *start,
+                                                 const char *end) {
+  EmitFormatDiagnostic(S.PDiag(diag::warn_scanf_scanlist_incomplete),
+                       getLocationOfByte(end), /*IsStringLocation*/true,
+                       getSpecifierRange(start, end - start));
+}
+
+bool CheckScanfHandler::HandleInvalidScanfConversionSpecifier(
+                                        const analyze_scanf::ScanfSpecifier &FS,
+                                        const char *startSpecifier,
+                                        unsigned specifierLen) {
+
+  const analyze_scanf::ScanfConversionSpecifier &CS =
+    FS.getConversionSpecifier();
+
+  return HandleInvalidConversionSpecifier(FS.getArgIndex(),
+                                          getLocationOfByte(CS.getStart()),
+                                          startSpecifier, specifierLen,
+                                          CS.getStart(), CS.getLength());
+}
+
+bool CheckScanfHandler::HandleScanfSpecifier(
+                                       const analyze_scanf::ScanfSpecifier &FS,
+                                       const char *startSpecifier,
+                                       unsigned specifierLen) {
+  
+  using namespace analyze_scanf;
+  using namespace analyze_format_string;  
+
+  const ScanfConversionSpecifier &CS = FS.getConversionSpecifier();
+
+  // Handle case where '%' and '*' don't consume an argument.  These shouldn't
+  // be used to decide if we are using positional arguments consistently.
+  if (FS.consumesDataArgument()) {
+    if (atFirstArg) {
+      atFirstArg = false;
+      usesPositionalArgs = FS.usesPositionalArg();
+    }
+    else if (usesPositionalArgs != FS.usesPositionalArg()) {
+      HandlePositionalNonpositionalArgs(getLocationOfByte(CS.getStart()),
+                                        startSpecifier, specifierLen);
+      return false;
+    }
+  }
+  
+  // Check if the field with is non-zero.
+  const OptionalAmount &Amt = FS.getFieldWidth();
+  if (Amt.getHowSpecified() == OptionalAmount::Constant) {
+    if (Amt.getConstantAmount() == 0) {
+      const CharSourceRange &R = getSpecifierRange(Amt.getStart(),
+                                                   Amt.getConstantLength());
+      EmitFormatDiagnostic(S.PDiag(diag::warn_scanf_nonzero_width),
+                           getLocationOfByte(Amt.getStart()),
+                           /*IsStringLocation*/true, R,
+                           FixItHint::CreateRemoval(R));
+    }
+  }
+  
+  if (!FS.consumesDataArgument()) {
+    // FIXME: Technically specifying a precision or field width here
+    // makes no sense.  Worth issuing a warning at some point.
+    return true;
+  }
+  
+  // Consume the argument.
+  unsigned argIndex = FS.getArgIndex();
+  if (argIndex < NumDataArgs) {
+      // The check to see if the argIndex is valid will come later.
+      // We set the bit here because we may exit early from this
+      // function if we encounter some other error.
+    CoveredArgs.set(argIndex);
+  }
+  
+  // Check the length modifier is valid with the given conversion specifier.
+  const LengthModifier &LM = FS.getLengthModifier();
+  if (!FS.hasValidLengthModifier()) {
+    const CharSourceRange &R = getSpecifierRange(LM.getStart(), LM.getLength());
+    EmitFormatDiagnostic(S.PDiag(diag::warn_format_nonsensical_length)
+                         << LM.toString() << CS.toString()
+                         << getSpecifierRange(startSpecifier, specifierLen),
+                         getLocationOfByte(LM.getStart()),
+                         /*IsStringLocation*/true, R,
+                         FixItHint::CreateRemoval(R));
+  }
+
+  if (!FS.hasStandardLengthModifier())
+    HandleNonStandardLengthModifier(LM, startSpecifier, specifierLen);
+  if (!FS.hasStandardConversionSpecifier(S.getLangOpts()))
+    HandleNonStandardConversionSpecifier(CS, startSpecifier, specifierLen);
+  if (!FS.hasStandardLengthConversionCombination())
+    HandleNonStandardConversionSpecification(LM, CS, startSpecifier,
+                                             specifierLen);
+
+  // The remaining checks depend on the data arguments.
+  if (HasVAListArg)
+    return true;
+  
+  if (!CheckNumArgs(FS, CS, startSpecifier, specifierLen, argIndex))
+    return false;
+  
+  // Check that the argument type matches the format specifier.
+  const Expr *Ex = getDataArg(argIndex);
+  const analyze_scanf::ScanfArgTypeResult &ATR = FS.getArgType(S.Context);
+  if (ATR.isValid() && !ATR.matchesType(S.Context, Ex->getType())) {
+    ScanfSpecifier fixedFS = FS;
+    bool success = fixedFS.fixType(Ex->getType(), S.getLangOpts(),
+                                   S.Context);
+
+    if (success) {
+      // Get the fix string from the fixed format specifier.
+      SmallString<128> buf;
+      llvm::raw_svector_ostream os(buf);
+      fixedFS.toString(os);
+
+      EmitFormatDiagnostic(
+        S.PDiag(diag::warn_printf_conversion_argument_type_mismatch)
+          << ATR.getRepresentativeTypeName(S.Context) << Ex->getType()
+          << Ex->getSourceRange(),
+        getLocationOfByte(CS.getStart()),
+        /*IsStringLocation*/true,
+        getSpecifierRange(startSpecifier, specifierLen),
+        FixItHint::CreateReplacement(
+          getSpecifierRange(startSpecifier, specifierLen),
+          os.str()));
+    } else {
+      EmitFormatDiagnostic(
+        S.PDiag(diag::warn_printf_conversion_argument_type_mismatch)
+          << ATR.getRepresentativeTypeName(S.Context) << Ex->getType()
+          << Ex->getSourceRange(),
+        getLocationOfByte(CS.getStart()),
+        /*IsStringLocation*/true,
+        getSpecifierRange(startSpecifier, specifierLen));
+    }
+  }
+
+  return true;
+}
+
+void Sema::CheckFormatString(const StringLiteral *FExpr,
+                             const Expr *OrigFormatExpr,
+                             Expr **Args, unsigned NumArgs,
+                             bool HasVAListArg, unsigned format_idx,
+                             unsigned firstDataArg, FormatStringType Type,
+                             bool inFunctionCall) {
+  
+  // CHECK: is the format string a wide literal?
+  if (!FExpr->isAscii()) {
+    CheckFormatHandler::EmitFormatDiagnostic(
+      *this, inFunctionCall, Args[format_idx],
+      PDiag(diag::warn_format_string_is_wide_literal), FExpr->getLocStart(),
+      /*IsStringLocation*/true, OrigFormatExpr->getSourceRange());
+    return;
+  }
+  
+  // Str - The format string.  NOTE: this is NOT null-terminated!
+  StringRef StrRef = FExpr->getString();
+  const char *Str = StrRef.data();
+  unsigned StrLen = StrRef.size();
+  const unsigned numDataArgs = NumArgs - firstDataArg;
+  
+  // CHECK: empty format string?
+  if (StrLen == 0 && numDataArgs > 0) {
+    CheckFormatHandler::EmitFormatDiagnostic(
+      *this, inFunctionCall, Args[format_idx],
+      PDiag(diag::warn_empty_format_string), FExpr->getLocStart(),
+      /*IsStringLocation*/true, OrigFormatExpr->getSourceRange());
+    return;
+  }
+  
+  if (Type == FST_Printf || Type == FST_NSString) {
+    CheckPrintfHandler H(*this, FExpr, OrigFormatExpr, firstDataArg,
+                         numDataArgs, isa<ObjCStringLiteral>(OrigFormatExpr),
+                         Str, HasVAListArg, Args, NumArgs, format_idx,
+                         inFunctionCall);
+  
+    if (!analyze_format_string::ParsePrintfString(H, Str, Str + StrLen,
+                                                  getLangOpts()))
+      H.DoneProcessing();
+  } else if (Type == FST_Scanf) {
+    CheckScanfHandler H(*this, FExpr, OrigFormatExpr, firstDataArg,
+                        numDataArgs, isa<ObjCStringLiteral>(OrigFormatExpr),
+                        Str, HasVAListArg, Args, NumArgs, format_idx,
+                        inFunctionCall);
+    
+    if (!analyze_format_string::ParseScanfString(H, Str, Str + StrLen,
+                                                 getLangOpts()))
+      H.DoneProcessing();
+  } // TODO: handle other formats
+}
+
+//===--- CHECK: Standard memory functions ---------------------------------===//
+
+/// \brief Determine whether the given type is a dynamic class type (e.g.,
+/// whether it has a vtable).
+static bool isDynamicClassType(QualType T) {
+  if (CXXRecordDecl *Record = T->getAsCXXRecordDecl())
+    if (CXXRecordDecl *Definition = Record->getDefinition())
+      if (Definition->isDynamicClass())
+        return true;
+  
+  return false;
+}
+
+/// \brief If E is a sizeof expression, returns its argument expression,
+/// otherwise returns NULL.
+static const Expr *getSizeOfExprArg(const Expr* E) {
+  if (const UnaryExprOrTypeTraitExpr *SizeOf =
+      dyn_cast<UnaryExprOrTypeTraitExpr>(E))
+    if (SizeOf->getKind() == clang::UETT_SizeOf && !SizeOf->isArgumentType())
+      return SizeOf->getArgumentExpr()->IgnoreParenImpCasts();
+
+  return 0;
+}
+
+/// \brief If E is a sizeof expression, returns its argument type.
+static QualType getSizeOfArgType(const Expr* E) {
+  if (const UnaryExprOrTypeTraitExpr *SizeOf =
+      dyn_cast<UnaryExprOrTypeTraitExpr>(E))
+    if (SizeOf->getKind() == clang::UETT_SizeOf)
+      return SizeOf->getTypeOfArgument();
+
+  return QualType();
+}
+
+/// \brief Check for dangerous or invalid arguments to memset().
+///
+/// This issues warnings on known problematic, dangerous or unspecified
+/// arguments to the standard 'memset', 'memcpy', 'memmove', and 'memcmp'
+/// function calls.
+///
+/// \param Call The call expression to diagnose.
+void Sema::CheckMemaccessArguments(const CallExpr *Call,
+                                   unsigned BId,
+                                   IdentifierInfo *FnName) {
+  assert(BId != 0);
+
+  // It is possible to have a non-standard definition of memset.  Validate
+  // we have enough arguments, and if not, abort further checking.
+  unsigned ExpectedNumArgs = (BId == Builtin::BIstrndup ? 2 : 3);
+  if (Call->getNumArgs() < ExpectedNumArgs)
+    return;
+
+  unsigned LastArg = (BId == Builtin::BImemset ||
+                      BId == Builtin::BIstrndup ? 1 : 2);
+  unsigned LenArg = (BId == Builtin::BIstrndup ? 1 : 2);
+  const Expr *LenExpr = Call->getArg(LenArg)->IgnoreParenImpCasts();
+
+  // We have special checking when the length is a sizeof expression.
+  QualType SizeOfArgTy = getSizeOfArgType(LenExpr);
+  const Expr *SizeOfArg = getSizeOfExprArg(LenExpr);
+  llvm::FoldingSetNodeID SizeOfArgID;
+
+  for (unsigned ArgIdx = 0; ArgIdx != LastArg; ++ArgIdx) {
+    const Expr *Dest = Call->getArg(ArgIdx)->IgnoreParenImpCasts();
+    SourceRange ArgRange = Call->getArg(ArgIdx)->getSourceRange();
+
+    QualType DestTy = Dest->getType();
+    if (const PointerType *DestPtrTy = DestTy->getAs<PointerType>()) {
+      QualType PointeeTy = DestPtrTy->getPointeeType();
+
+      // Never warn about void type pointers. This can be used to suppress
+      // false positives.
+      if (PointeeTy->isVoidType())
+        continue;
+
+      // Catch "memset(p, 0, sizeof(p))" -- needs to be sizeof(*p). Do this by
+      // actually comparing the expressions for equality. Because computing the
+      // expression IDs can be expensive, we only do this if the diagnostic is
+      // enabled.
+      if (SizeOfArg &&
+          Diags.getDiagnosticLevel(diag::warn_sizeof_pointer_expr_memaccess,
+                                   SizeOfArg->getExprLoc())) {
+        // We only compute IDs for expressions if the warning is enabled, and
+        // cache the sizeof arg's ID.
+        if (SizeOfArgID == llvm::FoldingSetNodeID())
+          SizeOfArg->Profile(SizeOfArgID, Context, true);
+        llvm::FoldingSetNodeID DestID;
+        Dest->Profile(DestID, Context, true);
+        if (DestID == SizeOfArgID) {
+          // TODO: For strncpy() and friends, this could suggest sizeof(dst)
+          //       over sizeof(src) as well.
+          unsigned ActionIdx = 0; // Default is to suggest dereferencing.
+          if (const UnaryOperator *UnaryOp = dyn_cast<UnaryOperator>(Dest))
+            if (UnaryOp->getOpcode() == UO_AddrOf)
+              ActionIdx = 1; // If its an address-of operator, just remove it.
+          if (Context.getTypeSize(PointeeTy) == Context.getCharWidth())
+            ActionIdx = 2; // If the pointee's size is sizeof(char),
+                           // suggest an explicit length.
+          unsigned DestSrcSelect =
+            (BId == Builtin::BIstrndup ? 1 : ArgIdx);
+          DiagRuntimeBehavior(SizeOfArg->getExprLoc(), Dest,
+                              PDiag(diag::warn_sizeof_pointer_expr_memaccess)
+                                << FnName << DestSrcSelect << ActionIdx
+                                << Dest->getSourceRange()
+                                << SizeOfArg->getSourceRange());
+          break;
+        }
+      }
+
+      // Also check for cases where the sizeof argument is the exact same
+      // type as the memory argument, and where it points to a user-defined
+      // record type.
+      if (SizeOfArgTy != QualType()) {
+        if (PointeeTy->isRecordType() &&
+            Context.typesAreCompatible(SizeOfArgTy, DestTy)) {
+          DiagRuntimeBehavior(LenExpr->getExprLoc(), Dest,
+                              PDiag(diag::warn_sizeof_pointer_type_memaccess)
+                                << FnName << SizeOfArgTy << ArgIdx
+                                << PointeeTy << Dest->getSourceRange()
+                                << LenExpr->getSourceRange());
+          break;
+        }
+      }
+
+      // Always complain about dynamic classes.
+      if (isDynamicClassType(PointeeTy)) {
+
+        unsigned OperationType = 0;
+        // "overwritten" if we're warning about the destination for any call
+        // but memcmp; otherwise a verb appropriate to the call.
+        if (ArgIdx != 0 || BId == Builtin::BImemcmp) {
+          if (BId == Builtin::BImemcpy)
+            OperationType = 1;
+          else if(BId == Builtin::BImemmove)
+            OperationType = 2;
+          else if (BId == Builtin::BImemcmp)
+            OperationType = 3;
+        }
+          
+        DiagRuntimeBehavior(
+          Dest->getExprLoc(), Dest,
+          PDiag(diag::warn_dyn_class_memaccess)
+            << (BId == Builtin::BImemcmp ? ArgIdx + 2 : ArgIdx)
+            << FnName << PointeeTy
+            << OperationType
+            << Call->getCallee()->getSourceRange());
+      } else if (PointeeTy.hasNonTrivialObjCLifetime() &&
+               BId != Builtin::BImemset)
+        DiagRuntimeBehavior(
+          Dest->getExprLoc(), Dest,
+          PDiag(diag::warn_arc_object_memaccess)
+            << ArgIdx << FnName << PointeeTy
+            << Call->getCallee()->getSourceRange());
+      else
+        continue;
+
+      DiagRuntimeBehavior(
+        Dest->getExprLoc(), Dest,
+        PDiag(diag::note_bad_memaccess_silence)
+          << FixItHint::CreateInsertion(ArgRange.getBegin(), "(void*)"));
+      break;
+    }
+  }
+}
+
+// A little helper routine: ignore addition and subtraction of integer literals.
+// This intentionally does not ignore all integer constant expressions because
+// we don't want to remove sizeof().
+static const Expr *ignoreLiteralAdditions(const Expr *Ex, ASTContext &Ctx) {
+  Ex = Ex->IgnoreParenCasts();
+
+  for (;;) {
+    const BinaryOperator * BO = dyn_cast<BinaryOperator>(Ex);
+    if (!BO || !BO->isAdditiveOp())
+      break;
+
+    const Expr *RHS = BO->getRHS()->IgnoreParenCasts();
+    const Expr *LHS = BO->getLHS()->IgnoreParenCasts();
+    
+    if (isa<IntegerLiteral>(RHS))
+      Ex = LHS;
+    else if (isa<IntegerLiteral>(LHS))
+      Ex = RHS;
+    else
+      break;
+  }
+
+  return Ex;
+}
+
+// Warn if the user has made the 'size' argument to strlcpy or strlcat
+// be the size of the source, instead of the destination.
+void Sema::CheckStrlcpycatArguments(const CallExpr *Call,
+                                    IdentifierInfo *FnName) {
+
+  // Don't crash if the user has the wrong number of arguments
+  if (Call->getNumArgs() != 3)
+    return;
+
+  const Expr *SrcArg = ignoreLiteralAdditions(Call->getArg(1), Context);
+  const Expr *SizeArg = ignoreLiteralAdditions(Call->getArg(2), Context);
+  const Expr *CompareWithSrc = NULL;
+  
+  // Look for 'strlcpy(dst, x, sizeof(x))'
+  if (const Expr *Ex = getSizeOfExprArg(SizeArg))
+    CompareWithSrc = Ex;
+  else {
+    // Look for 'strlcpy(dst, x, strlen(x))'
+    if (const CallExpr *SizeCall = dyn_cast<CallExpr>(SizeArg)) {
+      if (SizeCall->isBuiltinCall() == Builtin::BIstrlen
+          && SizeCall->getNumArgs() == 1)
+        CompareWithSrc = ignoreLiteralAdditions(SizeCall->getArg(0), Context);
+    }
+  }
+
+  if (!CompareWithSrc)
+    return;
+
+  // Determine if the argument to sizeof/strlen is equal to the source
+  // argument.  In principle there's all kinds of things you could do
+  // here, for instance creating an == expression and evaluating it with
+  // EvaluateAsBooleanCondition, but this uses a more direct technique:
+  const DeclRefExpr *SrcArgDRE = dyn_cast<DeclRefExpr>(SrcArg);
+  if (!SrcArgDRE)
+    return;
+  
+  const DeclRefExpr *CompareWithSrcDRE = dyn_cast<DeclRefExpr>(CompareWithSrc);
+  if (!CompareWithSrcDRE || 
+      SrcArgDRE->getDecl() != CompareWithSrcDRE->getDecl())
+    return;
+  
+  const Expr *OriginalSizeArg = Call->getArg(2);
+  Diag(CompareWithSrcDRE->getLocStart(), diag::warn_strlcpycat_wrong_size)
+    << OriginalSizeArg->getSourceRange() << FnName;
+  
+  // Output a FIXIT hint if the destination is an array (rather than a
+  // pointer to an array).  This could be enhanced to handle some
+  // pointers if we know the actual size, like if DstArg is 'array+2'
+  // we could say 'sizeof(array)-2'.
+  const Expr *DstArg = Call->getArg(0)->IgnoreParenImpCasts();
+  QualType DstArgTy = DstArg->getType();
+  
+  // Only handle constant-sized or VLAs, but not flexible members.
+  if (const ConstantArrayType *CAT = Context.getAsConstantArrayType(DstArgTy)) {
+    // Only issue the FIXIT for arrays of size > 1.
+    if (CAT->getSize().getSExtValue() <= 1)
+      return;
+  } else if (!DstArgTy->isVariableArrayType()) {
+    return;
+  }
+
+  SmallString<128> sizeString;
+  llvm::raw_svector_ostream OS(sizeString);
+  OS << "sizeof(";
+  DstArg->printPretty(OS, Context, 0, getPrintingPolicy());
+  OS << ")";
+  
+  Diag(OriginalSizeArg->getLocStart(), diag::note_strlcpycat_wrong_size)
+    << FixItHint::CreateReplacement(OriginalSizeArg->getSourceRange(),
+                                    OS.str());
+}
+
+/// Check if two expressions refer to the same declaration.
+static bool referToTheSameDecl(const Expr *E1, const Expr *E2) {
+  if (const DeclRefExpr *D1 = dyn_cast_or_null<DeclRefExpr>(E1))
+    if (const DeclRefExpr *D2 = dyn_cast_or_null<DeclRefExpr>(E2))
+      return D1->getDecl() == D2->getDecl();
+  return false;
+}
+
+static const Expr *getStrlenExprArg(const Expr *E) {
+  if (const CallExpr *CE = dyn_cast<CallExpr>(E)) {
+    const FunctionDecl *FD = CE->getDirectCallee();
+    if (!FD || FD->getMemoryFunctionKind() != Builtin::BIstrlen)
+      return 0;
+    return CE->getArg(0)->IgnoreParenCasts();
+  }
+  return 0;
+}
+
+// Warn on anti-patterns as the 'size' argument to strncat.
+// The correct size argument should look like following:
+//   strncat(dst, src, sizeof(dst) - strlen(dest) - 1);
+void Sema::CheckStrncatArguments(const CallExpr *CE,
+                                 IdentifierInfo *FnName) {
+  // Don't crash if the user has the wrong number of arguments.
+  if (CE->getNumArgs() < 3)
+    return;
+  const Expr *DstArg = CE->getArg(0)->IgnoreParenCasts();
+  const Expr *SrcArg = CE->getArg(1)->IgnoreParenCasts();
+  const Expr *LenArg = CE->getArg(2)->IgnoreParenCasts();
+
+  // Identify common expressions, which are wrongly used as the size argument
+  // to strncat and may lead to buffer overflows.
+  unsigned PatternType = 0;
+  if (const Expr *SizeOfArg = getSizeOfExprArg(LenArg)) {
+    // - sizeof(dst)
+    if (referToTheSameDecl(SizeOfArg, DstArg))
+      PatternType = 1;
+    // - sizeof(src)
+    else if (referToTheSameDecl(SizeOfArg, SrcArg))
+      PatternType = 2;
+  } else if (const BinaryOperator *BE = dyn_cast<BinaryOperator>(LenArg)) {
+    if (BE->getOpcode() == BO_Sub) {
+      const Expr *L = BE->getLHS()->IgnoreParenCasts();
+      const Expr *R = BE->getRHS()->IgnoreParenCasts();
+      // - sizeof(dst) - strlen(dst)
+      if (referToTheSameDecl(DstArg, getSizeOfExprArg(L)) &&
+          referToTheSameDecl(DstArg, getStrlenExprArg(R)))
+        PatternType = 1;
+      // - sizeof(src) - (anything)
+      else if (referToTheSameDecl(SrcArg, getSizeOfExprArg(L)))
+        PatternType = 2;
+    }
+  }
+
+  if (PatternType == 0)
+    return;
+
+  // Generate the diagnostic.
+  SourceLocation SL = LenArg->getLocStart();
+  SourceRange SR = LenArg->getSourceRange();
+  SourceManager &SM  = PP.getSourceManager();
+
+  // If the function is defined as a builtin macro, do not show macro expansion.
+  if (SM.isMacroArgExpansion(SL)) {
+    SL = SM.getSpellingLoc(SL);
+    SR = SourceRange(SM.getSpellingLoc(SR.getBegin()),
+                     SM.getSpellingLoc(SR.getEnd()));
+  }
+
+  if (PatternType == 1)
+    Diag(SL, diag::warn_strncat_large_size) << SR;
+  else
+    Diag(SL, diag::warn_strncat_src_size) << SR;
+
+  // Output a FIXIT hint if the destination is an array (rather than a
+  // pointer to an array).  This could be enhanced to handle some
+  // pointers if we know the actual size, like if DstArg is 'array+2'
+  // we could say 'sizeof(array)-2'.
+  QualType DstArgTy = DstArg->getType();
+
+  // Only handle constant-sized or VLAs, but not flexible members.
+  if (const ConstantArrayType *CAT = Context.getAsConstantArrayType(DstArgTy)) {
+    // Only issue the FIXIT for arrays of size > 1.
+    if (CAT->getSize().getSExtValue() <= 1)
+      return;
+  } else if (!DstArgTy->isVariableArrayType()) {
+    return;
+  }
+
+  SmallString<128> sizeString;
+  llvm::raw_svector_ostream OS(sizeString);
+  OS << "sizeof(";
+  DstArg->printPretty(OS, Context, 0, getPrintingPolicy());
+  OS << ") - ";
+  OS << "strlen(";
+  DstArg->printPretty(OS, Context, 0, getPrintingPolicy());
+  OS << ") - 1";
+
+  Diag(SL, diag::note_strncat_wrong_size)
+    << FixItHint::CreateReplacement(SR, OS.str());
+}
+
+//===--- CHECK: Return Address of Stack Variable --------------------------===//
+
+static Expr *EvalVal(Expr *E, SmallVectorImpl<DeclRefExpr *> &refVars);
+static Expr *EvalAddr(Expr* E, SmallVectorImpl<DeclRefExpr *> &refVars);
+
+/// CheckReturnStackAddr - Check if a return statement returns the address
+///   of a stack variable.
+void
+Sema::CheckReturnStackAddr(Expr *RetValExp, QualType lhsType,
+                           SourceLocation ReturnLoc) {
+
+  Expr *stackE = 0;
+  SmallVector<DeclRefExpr *, 8> refVars;
+
+  // Perform checking for returned stack addresses, local blocks,
+  // label addresses or references to temporaries.
+  if (lhsType->isPointerType() ||
+      (!getLangOpts().ObjCAutoRefCount && lhsType->isBlockPointerType())) {
+    stackE = EvalAddr(RetValExp, refVars);
+  } else if (lhsType->isReferenceType()) {
+    stackE = EvalVal(RetValExp, refVars);
+  }
+
+  if (stackE == 0)
+    return; // Nothing suspicious was found.
+
+  SourceLocation diagLoc;
+  SourceRange diagRange;
+  if (refVars.empty()) {
+    diagLoc = stackE->getLocStart();
+    diagRange = stackE->getSourceRange();
+  } else {
+    // We followed through a reference variable. 'stackE' contains the
+    // problematic expression but we will warn at the return statement pointing
+    // at the reference variable. We will later display the "trail" of
+    // reference variables using notes.
+    diagLoc = refVars[0]->getLocStart();
+    diagRange = refVars[0]->getSourceRange();
+  }
+
+  if (DeclRefExpr *DR = dyn_cast<DeclRefExpr>(stackE)) { //address of local var.
+    Diag(diagLoc, lhsType->isReferenceType() ? diag::warn_ret_stack_ref
+                                             : diag::warn_ret_stack_addr)
+     << DR->getDecl()->getDeclName() << diagRange;
+  } else if (isa<BlockExpr>(stackE)) { // local block.
+    Diag(diagLoc, diag::err_ret_local_block) << diagRange;
+  } else if (isa<AddrLabelExpr>(stackE)) { // address of label.
+    Diag(diagLoc, diag::warn_ret_addr_label) << diagRange;
+  } else { // local temporary.
+    Diag(diagLoc, lhsType->isReferenceType() ? diag::warn_ret_local_temp_ref
+                                             : diag::warn_ret_local_temp_addr)
+     << diagRange;
+  }
+
+  // Display the "trail" of reference variables that we followed until we
+  // found the problematic expression using notes.
+  for (unsigned i = 0, e = refVars.size(); i != e; ++i) {
+    VarDecl *VD = cast<VarDecl>(refVars[i]->getDecl());
+    // If this var binds to another reference var, show the range of the next
+    // var, otherwise the var binds to the problematic expression, in which case
+    // show the range of the expression.
+    SourceRange range = (i < e-1) ? refVars[i+1]->getSourceRange()
+                                  : stackE->getSourceRange();
+    Diag(VD->getLocation(), diag::note_ref_var_local_bind)
+      << VD->getDeclName() << range;
+  }
+}
+
+/// EvalAddr - EvalAddr and EvalVal are mutually recursive functions that
+///  check if the expression in a return statement evaluates to an address
+///  to a location on the stack, a local block, an address of a label, or a
+///  reference to local temporary. The recursion is used to traverse the
+///  AST of the return expression, with recursion backtracking when we
+///  encounter a subexpression that (1) clearly does not lead to one of the
+///  above problematic expressions (2) is something we cannot determine leads to
+///  a problematic expression based on such local checking.
+///
+///  Both EvalAddr and EvalVal follow through reference variables to evaluate
+///  the expression that they point to. Such variables are added to the
+///  'refVars' vector so that we know what the reference variable "trail" was.
+///
+///  EvalAddr processes expressions that are pointers that are used as
+///  references (and not L-values).  EvalVal handles all other values.
+///  At the base case of the recursion is a check for the above problematic
+///  expressions.
+///
+///  This implementation handles:
+///
+///   * pointer-to-pointer casts
+///   * implicit conversions from array references to pointers
+///   * taking the address of fields
+///   * arbitrary interplay between "&" and "*" operators
+///   * pointer arithmetic from an address of a stack variable
+///   * taking the address of an array element where the array is on the stack
+static Expr *EvalAddr(Expr *E, SmallVectorImpl<DeclRefExpr *> &refVars) {
+  if (E->isTypeDependent())
+      return NULL;
+
+  // We should only be called for evaluating pointer expressions.
+  assert((E->getType()->isAnyPointerType() ||
+          E->getType()->isBlockPointerType() ||
+          E->getType()->isObjCQualifiedIdType()) &&
+         "EvalAddr only works on pointers");
+
+  E = E->IgnoreParens();
+
+  // Our "symbolic interpreter" is just a dispatch off the currently
+  // viewed AST node.  We then recursively traverse the AST by calling
+  // EvalAddr and EvalVal appropriately.
+  switch (E->getStmtClass()) {
+  case Stmt::DeclRefExprClass: {
+    DeclRefExpr *DR = cast<DeclRefExpr>(E);
+
+    if (VarDecl *V = dyn_cast<VarDecl>(DR->getDecl()))
+      // If this is a reference variable, follow through to the expression that
+      // it points to.
+      if (V->hasLocalStorage() &&
+          V->getType()->isReferenceType() && V->hasInit()) {
+        // Add the reference variable to the "trail".
+        refVars.push_back(DR);
+        return EvalAddr(V->getInit(), refVars);
+      }
+
+    return NULL;
+  }
+
+  case Stmt::UnaryOperatorClass: {
+    // The only unary operator that make sense to handle here
+    // is AddrOf.  All others don't make sense as pointers.
+    UnaryOperator *U = cast<UnaryOperator>(E);
+
+    if (U->getOpcode() == UO_AddrOf)
+      return EvalVal(U->getSubExpr(), refVars);
+    else
+      return NULL;
+  }
+
+  case Stmt::BinaryOperatorClass: {
+    // Handle pointer arithmetic.  All other binary operators are not valid
+    // in this context.
+    BinaryOperator *B = cast<BinaryOperator>(E);
+    BinaryOperatorKind op = B->getOpcode();
+
+    if (op != BO_Add && op != BO_Sub)
+      return NULL;
+
+    Expr *Base = B->getLHS();
+
+    // Determine which argument is the real pointer base.  It could be
+    // the RHS argument instead of the LHS.
+    if (!Base->getType()->isPointerType()) Base = B->getRHS();
+
+    assert (Base->getType()->isPointerType());
+    return EvalAddr(Base, refVars);
+  }
+
+  // For conditional operators we need to see if either the LHS or RHS are
+  // valid DeclRefExpr*s.  If one of them is valid, we return it.
+  case Stmt::ConditionalOperatorClass: {
+    ConditionalOperator *C = cast<ConditionalOperator>(E);
+
+    // Handle the GNU extension for missing LHS.
+    if (Expr *lhsExpr = C->getLHS()) {
+    // In C++, we can have a throw-expression, which has 'void' type.
+      if (!lhsExpr->getType()->isVoidType())
+        if (Expr* LHS = EvalAddr(lhsExpr, refVars))
+          return LHS;
+    }
+
+    // In C++, we can have a throw-expression, which has 'void' type.
+    if (C->getRHS()->getType()->isVoidType())
+      return NULL;
+
+    return EvalAddr(C->getRHS(), refVars);
+  }
+  
+  case Stmt::BlockExprClass:
+    if (cast<BlockExpr>(E)->getBlockDecl()->hasCaptures())
+      return E; // local block.
+    return NULL;
+
+  case Stmt::AddrLabelExprClass:
+    return E; // address of label.
+
+  case Stmt::ExprWithCleanupsClass:
+    return EvalAddr(cast<ExprWithCleanups>(E)->getSubExpr(), refVars);
+
+  // For casts, we need to handle conversions from arrays to
+  // pointer values, and pointer-to-pointer conversions.
+  case Stmt::ImplicitCastExprClass:
+  case Stmt::CStyleCastExprClass:
+  case Stmt::CXXFunctionalCastExprClass:
+  case Stmt::ObjCBridgedCastExprClass:
+  case Stmt::CXXStaticCastExprClass:
+  case Stmt::CXXDynamicCastExprClass:
+  case Stmt::CXXConstCastExprClass:
+  case Stmt::CXXReinterpretCastExprClass: {
+    Expr* SubExpr = cast<CastExpr>(E)->getSubExpr();
+    switch (cast<CastExpr>(E)->getCastKind()) {
+    case CK_BitCast:
+    case CK_LValueToRValue:
+    case CK_NoOp:
+    case CK_BaseToDerived:
+    case CK_DerivedToBase:
+    case CK_UncheckedDerivedToBase:
+    case CK_Dynamic:
+    case CK_CPointerToObjCPointerCast:
+    case CK_BlockPointerToObjCPointerCast:
+    case CK_AnyPointerToBlockPointerCast:
+      return EvalAddr(SubExpr, refVars);
+
+    case CK_ArrayToPointerDecay:
+      return EvalVal(SubExpr, refVars);
+
+    default:
+      return 0;
+    }
+  }
+
+  case Stmt::MaterializeTemporaryExprClass:
+    if (Expr *Result = EvalAddr(
+                         cast<MaterializeTemporaryExpr>(E)->GetTemporaryExpr(),
+                                refVars))
+      return Result;
+      
+    return E;
+      
+  // Everything else: we simply don't reason about them.
+  default:
+    return NULL;
+  }
+}
+
+
+///  EvalVal - This function is complements EvalAddr in the mutual recursion.
+///   See the comments for EvalAddr for more details.
+static Expr *EvalVal(Expr *E, SmallVectorImpl<DeclRefExpr *> &refVars) {
+do {
+  // We should only be called for evaluating non-pointer expressions, or
+  // expressions with a pointer type that are not used as references but instead
+  // are l-values (e.g., DeclRefExpr with a pointer type).
+
+  // Our "symbolic interpreter" is just a dispatch off the currently
+  // viewed AST node.  We then recursively traverse the AST by calling
+  // EvalAddr and EvalVal appropriately.
+
+  E = E->IgnoreParens();
+  switch (E->getStmtClass()) {
+  case Stmt::ImplicitCastExprClass: {
+    ImplicitCastExpr *IE = cast<ImplicitCastExpr>(E);
+    if (IE->getValueKind() == VK_LValue) {
+      E = IE->getSubExpr();
+      continue;
+    }
+    return NULL;
+  }
+
+  case Stmt::ExprWithCleanupsClass:
+    return EvalVal(cast<ExprWithCleanups>(E)->getSubExpr(), refVars);
+
+  case Stmt::DeclRefExprClass: {
+    // When we hit a DeclRefExpr we are looking at code that refers to a
+    // variable's name. If it's not a reference variable we check if it has
+    // local storage within the function, and if so, return the expression.
+    DeclRefExpr *DR = cast<DeclRefExpr>(E);
+
+    if (VarDecl *V = dyn_cast<VarDecl>(DR->getDecl()))
+      if (V->hasLocalStorage()) {
+        if (!V->getType()->isReferenceType())
+          return DR;
+
+        // Reference variable, follow through to the expression that
+        // it points to.
+        if (V->hasInit()) {
+          // Add the reference variable to the "trail".
+          refVars.push_back(DR);
+          return EvalVal(V->getInit(), refVars);
+        }
+      }
+
+    return NULL;
+  }
+
+  case Stmt::UnaryOperatorClass: {
+    // The only unary operator that make sense to handle here
+    // is Deref.  All others don't resolve to a "name."  This includes
+    // handling all sorts of rvalues passed to a unary operator.
+    UnaryOperator *U = cast<UnaryOperator>(E);
+
+    if (U->getOpcode() == UO_Deref)
+      return EvalAddr(U->getSubExpr(), refVars);
+
+    return NULL;
+  }
+
+  case Stmt::ArraySubscriptExprClass: {
+    // Array subscripts are potential references to data on the stack.  We
+    // retrieve the DeclRefExpr* for the array variable if it indeed
+    // has local storage.
+    return EvalAddr(cast<ArraySubscriptExpr>(E)->getBase(), refVars);
+  }
+
+  case Stmt::ConditionalOperatorClass: {
+    // For conditional operators we need to see if either the LHS or RHS are
+    // non-NULL Expr's.  If one is non-NULL, we return it.
+    ConditionalOperator *C = cast<ConditionalOperator>(E);
+
+    // Handle the GNU extension for missing LHS.
+    if (Expr *lhsExpr = C->getLHS())
+      if (Expr *LHS = EvalVal(lhsExpr, refVars))
+        return LHS;
+
+    return EvalVal(C->getRHS(), refVars);
+  }
+
+  // Accesses to members are potential references to data on the stack.
+  case Stmt::MemberExprClass: {
+    MemberExpr *M = cast<MemberExpr>(E);
+
+    // Check for indirect access.  We only want direct field accesses.
+    if (M->isArrow())
+      return NULL;
+
+    // Check whether the member type is itself a reference, in which case
+    // we're not going to refer to the member, but to what the member refers to.
+    if (M->getMemberDecl()->getType()->isReferenceType())
+      return NULL;
+
+    return EvalVal(M->getBase(), refVars);
+  }
+
+  case Stmt::MaterializeTemporaryExprClass:
+    if (Expr *Result = EvalVal(
+                          cast<MaterializeTemporaryExpr>(E)->GetTemporaryExpr(),
+                               refVars))
+      return Result;
+      
+    return E;
+
+  default:
+    // Check that we don't return or take the address of a reference to a
+    // temporary. This is only useful in C++.
+    if (!E->isTypeDependent() && E->isRValue())
+      return E;
+
+    // Everything else: we simply don't reason about them.
+    return NULL;
+  }
+} while (true);
+}
+
+//===--- CHECK: Floating-Point comparisons (-Wfloat-equal) ---------------===//
+
+/// Check for comparisons of floating point operands using != and ==.
+/// Issue a warning if these are no self-comparisons, as they are not likely
+/// to do what the programmer intended.
+void Sema::CheckFloatComparison(SourceLocation Loc, Expr* LHS, Expr *RHS) {
+  bool EmitWarning = true;
+
+  Expr* LeftExprSansParen = LHS->IgnoreParenImpCasts();
+  Expr* RightExprSansParen = RHS->IgnoreParenImpCasts();
+
+  // Special case: check for x == x (which is OK).
+  // Do not emit warnings for such cases.
+  if (DeclRefExpr* DRL = dyn_cast<DeclRefExpr>(LeftExprSansParen))
+    if (DeclRefExpr* DRR = dyn_cast<DeclRefExpr>(RightExprSansParen))
+      if (DRL->getDecl() == DRR->getDecl())
+        EmitWarning = false;
+
+
+  // Special case: check for comparisons against literals that can be exactly
+  //  represented by APFloat.  In such cases, do not emit a warning.  This
+  //  is a heuristic: often comparison against such literals are used to
+  //  detect if a value in a variable has not changed.  This clearly can
+  //  lead to false negatives.
+  if (EmitWarning) {
+    if (FloatingLiteral* FLL = dyn_cast<FloatingLiteral>(LeftExprSansParen)) {
+      if (FLL->isExact())
+        EmitWarning = false;
+    } else
+      if (FloatingLiteral* FLR = dyn_cast<FloatingLiteral>(RightExprSansParen)){
+        if (FLR->isExact())
+          EmitWarning = false;
+    }
+  }
+
+  // Check for comparisons with builtin types.
+  if (EmitWarning)
+    if (CallExpr* CL = dyn_cast<CallExpr>(LeftExprSansParen))
+      if (CL->isBuiltinCall())
+        EmitWarning = false;
+
+  if (EmitWarning)
+    if (CallExpr* CR = dyn_cast<CallExpr>(RightExprSansParen))
+      if (CR->isBuiltinCall())
+        EmitWarning = false;
+
+  // Emit the diagnostic.
+  if (EmitWarning)
+    Diag(Loc, diag::warn_floatingpoint_eq)
+      << LHS->getSourceRange() << RHS->getSourceRange();
+}
+
+//===--- CHECK: Integer mixed-sign comparisons (-Wsign-compare) --------===//
+//===--- CHECK: Lossy implicit conversions (-Wconversion) --------------===//
+
+namespace {
+
+/// Structure recording the 'active' range of an integer-valued
+/// expression.
+struct IntRange {
+  /// The number of bits active in the int.
+  unsigned Width;
+
+  /// True if the int is known not to have negative values.
+  bool NonNegative;
+
+  IntRange(unsigned Width, bool NonNegative)
+    : Width(Width), NonNegative(NonNegative)
+  {}
+
+  /// Returns the range of the bool type.
+  static IntRange forBoolType() {
+    return IntRange(1, true);
+  }
+
+  /// Returns the range of an opaque value of the given integral type.
+  static IntRange forValueOfType(ASTContext &C, QualType T) {
+    return forValueOfCanonicalType(C,
+                          T->getCanonicalTypeInternal().getTypePtr());
+  }
+
+  /// Returns the range of an opaque value of a canonical integral type.
+  static IntRange forValueOfCanonicalType(ASTContext &C, const Type *T) {
+    assert(T->isCanonicalUnqualified());
+
+    if (const VectorType *VT = dyn_cast<VectorType>(T))
+      T = VT->getElementType().getTypePtr();
+    if (const ComplexType *CT = dyn_cast<ComplexType>(T))
+      T = CT->getElementType().getTypePtr();
+
+    // For enum types, use the known bit width of the enumerators.
+    if (const EnumType *ET = dyn_cast<EnumType>(T)) {
+      EnumDecl *Enum = ET->getDecl();
+      if (!Enum->isCompleteDefinition())
+        return IntRange(C.getIntWidth(QualType(T, 0)), false);
+
+      unsigned NumPositive = Enum->getNumPositiveBits();
+      unsigned NumNegative = Enum->getNumNegativeBits();
+
+      return IntRange(std::max(NumPositive, NumNegative), NumNegative == 0);
+    }
+
+    const BuiltinType *BT = cast<BuiltinType>(T);
+    assert(BT->isInteger());
+
+    return IntRange(C.getIntWidth(QualType(T, 0)), BT->isUnsignedInteger());
+  }
+
+  /// Returns the "target" range of a canonical integral type, i.e.
+  /// the range of values expressible in the type.
+  ///
+  /// This matches forValueOfCanonicalType except that enums have the
+  /// full range of their type, not the range of their enumerators.
+  static IntRange forTargetOfCanonicalType(ASTContext &C, const Type *T) {
+    assert(T->isCanonicalUnqualified());
+
+    if (const VectorType *VT = dyn_cast<VectorType>(T))
+      T = VT->getElementType().getTypePtr();
+    if (const ComplexType *CT = dyn_cast<ComplexType>(T))
+      T = CT->getElementType().getTypePtr();
+    if (const EnumType *ET = dyn_cast<EnumType>(T))
+      T = C.getCanonicalType(ET->getDecl()->getIntegerType()).getTypePtr();
+
+    const BuiltinType *BT = cast<BuiltinType>(T);
+    assert(BT->isInteger());
+
+    return IntRange(C.getIntWidth(QualType(T, 0)), BT->isUnsignedInteger());
+  }
+
+  /// Returns the supremum of two ranges: i.e. their conservative merge.
+  static IntRange join(IntRange L, IntRange R) {
+    return IntRange(std::max(L.Width, R.Width),
+                    L.NonNegative && R.NonNegative);
+  }
+
+  /// Returns the infinum of two ranges: i.e. their aggressive merge.
+  static IntRange meet(IntRange L, IntRange R) {
+    return IntRange(std::min(L.Width, R.Width),
+                    L.NonNegative || R.NonNegative);
+  }
+};
+
+static IntRange GetValueRange(ASTContext &C, llvm::APSInt &value,
+                              unsigned MaxWidth) {
+  if (value.isSigned() && value.isNegative())
+    return IntRange(value.getMinSignedBits(), false);
+
+  if (value.getBitWidth() > MaxWidth)
+    value = value.trunc(MaxWidth);
+
+  // isNonNegative() just checks the sign bit without considering
+  // signedness.
+  return IntRange(value.getActiveBits(), true);
+}
+
+static IntRange GetValueRange(ASTContext &C, APValue &result, QualType Ty,
+                              unsigned MaxWidth) {
+  if (result.isInt())
+    return GetValueRange(C, result.getInt(), MaxWidth);
+
+  if (result.isVector()) {
+    IntRange R = GetValueRange(C, result.getVectorElt(0), Ty, MaxWidth);
+    for (unsigned i = 1, e = result.getVectorLength(); i != e; ++i) {
+      IntRange El = GetValueRange(C, result.getVectorElt(i), Ty, MaxWidth);
+      R = IntRange::join(R, El);
+    }
+    return R;
+  }
+
+  if (result.isComplexInt()) {
+    IntRange R = GetValueRange(C, result.getComplexIntReal(), MaxWidth);
+    IntRange I = GetValueRange(C, result.getComplexIntImag(), MaxWidth);
+    return IntRange::join(R, I);
+  }
+
+  // This can happen with lossless casts to intptr_t of "based" lvalues.
+  // Assume it might use arbitrary bits.
+  // FIXME: The only reason we need to pass the type in here is to get
+  // the sign right on this one case.  It would be nice if APValue
+  // preserved this.
+  assert(result.isLValue() || result.isAddrLabelDiff());
+  return IntRange(MaxWidth, Ty->isUnsignedIntegerOrEnumerationType());
+}
+
+/// Pseudo-evaluate the given integer expression, estimating the
+/// range of values it might take.
+///
+/// \param MaxWidth - the width to which the value will be truncated
+static IntRange GetExprRange(ASTContext &C, Expr *E, unsigned MaxWidth) {
+  E = E->IgnoreParens();
+
+  // Try a full evaluation first.
+  Expr::EvalResult result;
+  if (E->EvaluateAsRValue(result, C))
+    return GetValueRange(C, result.Val, E->getType(), MaxWidth);
+
+  // I think we only want to look through implicit casts here; if the
+  // user has an explicit widening cast, we should treat the value as
+  // being of the new, wider type.
+  if (ImplicitCastExpr *CE = dyn_cast<ImplicitCastExpr>(E)) {
+    if (CE->getCastKind() == CK_NoOp || CE->getCastKind() == CK_LValueToRValue)
+      return GetExprRange(C, CE->getSubExpr(), MaxWidth);
+
+    IntRange OutputTypeRange = IntRange::forValueOfType(C, CE->getType());
+
+    bool isIntegerCast = (CE->getCastKind() == CK_IntegralCast);
+
+    // Assume that non-integer casts can span the full range of the type.
+    if (!isIntegerCast)
+      return OutputTypeRange;
+
+    IntRange SubRange
+      = GetExprRange(C, CE->getSubExpr(),
+                     std::min(MaxWidth, OutputTypeRange.Width));
+
+    // Bail out if the subexpr's range is as wide as the cast type.
+    if (SubRange.Width >= OutputTypeRange.Width)
+      return OutputTypeRange;
+
+    // Otherwise, we take the smaller width, and we're non-negative if
+    // either the output type or the subexpr is.
+    return IntRange(SubRange.Width,
+                    SubRange.NonNegative || OutputTypeRange.NonNegative);
+  }
+
+  if (ConditionalOperator *CO = dyn_cast<ConditionalOperator>(E)) {
+    // If we can fold the condition, just take that operand.
+    bool CondResult;
+    if (CO->getCond()->EvaluateAsBooleanCondition(CondResult, C))
+      return GetExprRange(C, CondResult ? CO->getTrueExpr()
+                                        : CO->getFalseExpr(),
+                          MaxWidth);
+
+    // Otherwise, conservatively merge.
+    IntRange L = GetExprRange(C, CO->getTrueExpr(), MaxWidth);
+    IntRange R = GetExprRange(C, CO->getFalseExpr(), MaxWidth);
+    return IntRange::join(L, R);
+  }
+
+  if (BinaryOperator *BO = dyn_cast<BinaryOperator>(E)) {
+    switch (BO->getOpcode()) {
+
+    // Boolean-valued operations are single-bit and positive.
+    case BO_LAnd:
+    case BO_LOr:
+    case BO_LT:
+    case BO_GT:
+    case BO_LE:
+    case BO_GE:
+    case BO_EQ:
+    case BO_NE:
+      return IntRange::forBoolType();
+
+    // The type of the assignments is the type of the LHS, so the RHS
+    // is not necessarily the same type.
+    case BO_MulAssign:
+    case BO_DivAssign:
+    case BO_RemAssign:
+    case BO_AddAssign:
+    case BO_SubAssign:
+    case BO_XorAssign:
+    case BO_OrAssign:
+      // TODO: bitfields?
+      return IntRange::forValueOfType(C, E->getType());
+
+    // Simple assignments just pass through the RHS, which will have
+    // been coerced to the LHS type.
+    case BO_Assign:
+      // TODO: bitfields?
+      return GetExprRange(C, BO->getRHS(), MaxWidth);
+
+    // Operations with opaque sources are black-listed.
+    case BO_PtrMemD:
+    case BO_PtrMemI:
+      return IntRange::forValueOfType(C, E->getType());
+
+    // Bitwise-and uses the *infinum* of the two source ranges.
+    case BO_And:
+    case BO_AndAssign:
+      return IntRange::meet(GetExprRange(C, BO->getLHS(), MaxWidth),
+                            GetExprRange(C, BO->getRHS(), MaxWidth));
+
+    // Left shift gets black-listed based on a judgement call.
+    case BO_Shl:
+      // ...except that we want to treat '1 << (blah)' as logically
+      // positive.  It's an important idiom.
+      if (IntegerLiteral *I
+            = dyn_cast<IntegerLiteral>(BO->getLHS()->IgnoreParenCasts())) {
+        if (I->getValue() == 1) {
+          IntRange R = IntRange::forValueOfType(C, E->getType());
+          return IntRange(R.Width, /*NonNegative*/ true);
+        }
+      }
+      // fallthrough
+
+    case BO_ShlAssign:
+      return IntRange::forValueOfType(C, E->getType());
+
+    // Right shift by a constant can narrow its left argument.
+    case BO_Shr:
+    case BO_ShrAssign: {
+      IntRange L = GetExprRange(C, BO->getLHS(), MaxWidth);
+
+      // If the shift amount is a positive constant, drop the width by
+      // that much.
+      llvm::APSInt shift;
+      if (BO->getRHS()->isIntegerConstantExpr(shift, C) &&
+          shift.isNonNegative()) {
+        unsigned zext = shift.getZExtValue();
+        if (zext >= L.Width)
+          L.Width = (L.NonNegative ? 0 : 1);
+        else
+          L.Width -= zext;
+      }
+
+      return L;
+    }
+
+    // Comma acts as its right operand.
+    case BO_Comma:
+      return GetExprRange(C, BO->getRHS(), MaxWidth);
+
+    // Black-list pointer subtractions.
+    case BO_Sub:
+      if (BO->getLHS()->getType()->isPointerType())
+        return IntRange::forValueOfType(C, E->getType());
+      break;
+
+    // The width of a division result is mostly determined by the size
+    // of the LHS.
+    case BO_Div: {
+      // Don't 'pre-truncate' the operands.
+      unsigned opWidth = C.getIntWidth(E->getType());
+      IntRange L = GetExprRange(C, BO->getLHS(), opWidth);
+
+      // If the divisor is constant, use that.
+      llvm::APSInt divisor;
+      if (BO->getRHS()->isIntegerConstantExpr(divisor, C)) {
+        unsigned log2 = divisor.logBase2(); // floor(log_2(divisor))
+        if (log2 >= L.Width)
+          L.Width = (L.NonNegative ? 0 : 1);
+        else
+          L.Width = std::min(L.Width - log2, MaxWidth);
+        return L;
+      }
+
+      // Otherwise, just use the LHS's width.
+      IntRange R = GetExprRange(C, BO->getRHS(), opWidth);
+      return IntRange(L.Width, L.NonNegative && R.NonNegative);
+    }
+
+    // The result of a remainder can't be larger than the result of
+    // either side.
+    case BO_Rem: {
+      // Don't 'pre-truncate' the operands.
+      unsigned opWidth = C.getIntWidth(E->getType());
+      IntRange L = GetExprRange(C, BO->getLHS(), opWidth);
+      IntRange R = GetExprRange(C, BO->getRHS(), opWidth);
+
+      IntRange meet = IntRange::meet(L, R);
+      meet.Width = std::min(meet.Width, MaxWidth);
+      return meet;
+    }
+
+    // The default behavior is okay for these.
+    case BO_Mul:
+    case BO_Add:
+    case BO_Xor:
+    case BO_Or:
+      break;
+    }
+
+    // The default case is to treat the operation as if it were closed
+    // on the narrowest type that encompasses both operands.
+    IntRange L = GetExprRange(C, BO->getLHS(), MaxWidth);
+    IntRange R = GetExprRange(C, BO->getRHS(), MaxWidth);
+    return IntRange::join(L, R);
+  }
+
+  if (UnaryOperator *UO = dyn_cast<UnaryOperator>(E)) {
+    switch (UO->getOpcode()) {
+    // Boolean-valued operations are white-listed.
+    case UO_LNot:
+      return IntRange::forBoolType();
+
+    // Operations with opaque sources are black-listed.
+    case UO_Deref:
+    case UO_AddrOf: // should be impossible
+      return IntRange::forValueOfType(C, E->getType());
+
+    default:
+      return GetExprRange(C, UO->getSubExpr(), MaxWidth);
+    }
+  }
+  
+  if (dyn_cast<OffsetOfExpr>(E)) {
+    IntRange::forValueOfType(C, E->getType());
+  }
+
+  if (FieldDecl *BitField = E->getBitField())
+    return IntRange(BitField->getBitWidthValue(C),
+                    BitField->getType()->isUnsignedIntegerOrEnumerationType());
+
+  return IntRange::forValueOfType(C, E->getType());
+}
+
+static IntRange GetExprRange(ASTContext &C, Expr *E) {
+  return GetExprRange(C, E, C.getIntWidth(E->getType()));
+}
+
+/// Checks whether the given value, which currently has the given
+/// source semantics, has the same value when coerced through the
+/// target semantics.
+static bool IsSameFloatAfterCast(const llvm::APFloat &value,
+                                 const llvm::fltSemantics &Src,
+                                 const llvm::fltSemantics &Tgt) {
+  llvm::APFloat truncated = value;
+
+  bool ignored;
+  truncated.convert(Src, llvm::APFloat::rmNearestTiesToEven, &ignored);
+  truncated.convert(Tgt, llvm::APFloat::rmNearestTiesToEven, &ignored);
+
+  return truncated.bitwiseIsEqual(value);
+}
+
+/// Checks whether the given value, which currently has the given
+/// source semantics, has the same value when coerced through the
+/// target semantics.
+///
+/// The value might be a vector of floats (or a complex number).
+static bool IsSameFloatAfterCast(const APValue &value,
+                                 const llvm::fltSemantics &Src,
+                                 const llvm::fltSemantics &Tgt) {
+  if (value.isFloat())
+    return IsSameFloatAfterCast(value.getFloat(), Src, Tgt);
+
+  if (value.isVector()) {
+    for (unsigned i = 0, e = value.getVectorLength(); i != e; ++i)
+      if (!IsSameFloatAfterCast(value.getVectorElt(i), Src, Tgt))
+        return false;
+    return true;
+  }
+
+  assert(value.isComplexFloat());
+  return (IsSameFloatAfterCast(value.getComplexFloatReal(), Src, Tgt) &&
+          IsSameFloatAfterCast(value.getComplexFloatImag(), Src, Tgt));
+}
+
+static void AnalyzeImplicitConversions(Sema &S, Expr *E, SourceLocation CC);
+
+static bool IsZero(Sema &S, Expr *E) {
+  // Suppress cases where we are comparing against an enum constant.
+  if (const DeclRefExpr *DR =
+      dyn_cast<DeclRefExpr>(E->IgnoreParenImpCasts()))
+    if (isa<EnumConstantDecl>(DR->getDecl()))
+      return false;
+
+  // Suppress cases where the '0' value is expanded from a macro.
+  if (E->getLocStart().isMacroID())
+    return false;
+
+  llvm::APSInt Value;
+  return E->isIntegerConstantExpr(Value, S.Context) && Value == 0;
+}
+
+static bool HasEnumType(Expr *E) {
+  // Strip off implicit integral promotions.
+  while (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(E)) {
+    if (ICE->getCastKind() != CK_IntegralCast &&
+        ICE->getCastKind() != CK_NoOp)
+      break;
+    E = ICE->getSubExpr();
+  }
+
+  return E->getType()->isEnumeralType();
+}
+
+static void CheckTrivialUnsignedComparison(Sema &S, BinaryOperator *E) {
+  BinaryOperatorKind op = E->getOpcode();
+  if (E->isValueDependent())
+    return;
+
+  if (op == BO_LT && IsZero(S, E->getRHS())) {
+    S.Diag(E->getOperatorLoc(), diag::warn_lunsigned_always_true_comparison)
+      << "< 0" << "false" << HasEnumType(E->getLHS())
+      << E->getLHS()->getSourceRange() << E->getRHS()->getSourceRange();
+  } else if (op == BO_GE && IsZero(S, E->getRHS())) {
+    S.Diag(E->getOperatorLoc(), diag::warn_lunsigned_always_true_comparison)
+      << ">= 0" << "true" << HasEnumType(E->getLHS())
+      << E->getLHS()->getSourceRange() << E->getRHS()->getSourceRange();
+  } else if (op == BO_GT && IsZero(S, E->getLHS())) {
+    S.Diag(E->getOperatorLoc(), diag::warn_runsigned_always_true_comparison)
+      << "0 >" << "false" << HasEnumType(E->getRHS())
+      << E->getLHS()->getSourceRange() << E->getRHS()->getSourceRange();
+  } else if (op == BO_LE && IsZero(S, E->getLHS())) {
+    S.Diag(E->getOperatorLoc(), diag::warn_runsigned_always_true_comparison)
+      << "0 <=" << "true" << HasEnumType(E->getRHS())
+      << E->getLHS()->getSourceRange() << E->getRHS()->getSourceRange();
+  }
+}
+
+/// Analyze the operands of the given comparison.  Implements the
+/// fallback case from AnalyzeComparison.
+static void AnalyzeImpConvsInComparison(Sema &S, BinaryOperator *E) {
+  AnalyzeImplicitConversions(S, E->getLHS(), E->getOperatorLoc());
+  AnalyzeImplicitConversions(S, E->getRHS(), E->getOperatorLoc());
+}
+
+/// \brief Implements -Wsign-compare.
+///
+/// \param E the binary operator to check for warnings
+static void AnalyzeComparison(Sema &S, BinaryOperator *E) {
+  // The type the comparison is being performed in.
+  QualType T = E->getLHS()->getType();
+  assert(S.Context.hasSameUnqualifiedType(T, E->getRHS()->getType())
+         && "comparison with mismatched types");
+
+  // We don't do anything special if this isn't an unsigned integral
+  // comparison:  we're only interested in integral comparisons, and
+  // signed comparisons only happen in cases we don't care to warn about.
+  //
+  // We also don't care about value-dependent expressions or expressions
+  // whose result is a constant.
+  if (!T->hasUnsignedIntegerRepresentation()
+      || E->isValueDependent() || E->isIntegerConstantExpr(S.Context))
+    return AnalyzeImpConvsInComparison(S, E);
+
+  Expr *LHS = E->getLHS()->IgnoreParenImpCasts();
+  Expr *RHS = E->getRHS()->IgnoreParenImpCasts();
+
+  // Check to see if one of the (unmodified) operands is of different
+  // signedness.
+  Expr *signedOperand, *unsignedOperand;
+  if (LHS->getType()->hasSignedIntegerRepresentation()) {
+    assert(!RHS->getType()->hasSignedIntegerRepresentation() &&
+           "unsigned comparison between two signed integer expressions?");
+    signedOperand = LHS;
+    unsignedOperand = RHS;
+  } else if (RHS->getType()->hasSignedIntegerRepresentation()) {
+    signedOperand = RHS;
+    unsignedOperand = LHS;
+  } else {
+    CheckTrivialUnsignedComparison(S, E);
+    return AnalyzeImpConvsInComparison(S, E);
+  }
+
+  // Otherwise, calculate the effective range of the signed operand.
+  IntRange signedRange = GetExprRange(S.Context, signedOperand);
+
+  // Go ahead and analyze implicit conversions in the operands.  Note
+  // that we skip the implicit conversions on both sides.
+  AnalyzeImplicitConversions(S, LHS, E->getOperatorLoc());
+  AnalyzeImplicitConversions(S, RHS, E->getOperatorLoc());
+
+  // If the signed range is non-negative, -Wsign-compare won't fire,
+  // but we should still check for comparisons which are always true
+  // or false.
+  if (signedRange.NonNegative)
+    return CheckTrivialUnsignedComparison(S, E);
+
+  // For (in)equality comparisons, if the unsigned operand is a
+  // constant which cannot collide with a overflowed signed operand,
+  // then reinterpreting the signed operand as unsigned will not
+  // change the result of the comparison.
+  if (E->isEqualityOp()) {
+    unsigned comparisonWidth = S.Context.getIntWidth(T);
+    IntRange unsignedRange = GetExprRange(S.Context, unsignedOperand);
+
+    // We should never be unable to prove that the unsigned operand is
+    // non-negative.
+    assert(unsignedRange.NonNegative && "unsigned range includes negative?");
+
+    if (unsignedRange.Width < comparisonWidth)
+      return;
+  }
+
+  S.Diag(E->getOperatorLoc(), diag::warn_mixed_sign_comparison)
+    << LHS->getType() << RHS->getType()
+    << LHS->getSourceRange() << RHS->getSourceRange();
+}
+
+/// Analyzes an attempt to assign the given value to a bitfield.
+///
+/// Returns true if there was something fishy about the attempt.
+static bool AnalyzeBitFieldAssignment(Sema &S, FieldDecl *Bitfield, Expr *Init,
+                                      SourceLocation InitLoc) {
+  assert(Bitfield->isBitField());
+  if (Bitfield->isInvalidDecl())
+    return false;
+
+  // White-list bool bitfields.
+  if (Bitfield->getType()->isBooleanType())
+    return false;
+
+  // Ignore value- or type-dependent expressions.
+  if (Bitfield->getBitWidth()->isValueDependent() ||
+      Bitfield->getBitWidth()->isTypeDependent() ||
+      Init->isValueDependent() ||
+      Init->isTypeDependent())
+    return false;
+
+  Expr *OriginalInit = Init->IgnoreParenImpCasts();
+
+  llvm::APSInt Value;
+  if (!OriginalInit->EvaluateAsInt(Value, S.Context, Expr::SE_AllowSideEffects))
+    return false;
+
+  unsigned OriginalWidth = Value.getBitWidth();
+  unsigned FieldWidth = Bitfield->getBitWidthValue(S.Context);
+
+  if (OriginalWidth <= FieldWidth)
+    return false;
+
+  // Compute the value which the bitfield will contain.
+  llvm::APSInt TruncatedValue = Value.trunc(FieldWidth);
+  TruncatedValue.setIsSigned(Bitfield->getType()->isSignedIntegerType());
+
+  // Check whether the stored value is equal to the original value.
+  TruncatedValue = TruncatedValue.extend(OriginalWidth);
+  if (Value == TruncatedValue)
+    return false;
+
+  // Special-case bitfields of width 1: booleans are naturally 0/1, and
+  // therefore don't strictly fit into a signed bitfield of width 1.
+  if (FieldWidth == 1 && Value == 1)
+    return false;
+
+  std::string PrettyValue = Value.toString(10);
+  std::string PrettyTrunc = TruncatedValue.toString(10);
+
+  S.Diag(InitLoc, diag::warn_impcast_bitfield_precision_constant)
+    << PrettyValue << PrettyTrunc << OriginalInit->getType()
+    << Init->getSourceRange();
+
+  return true;
+}
+
+/// Analyze the given simple or compound assignment for warning-worthy
+/// operations.
+static void AnalyzeAssignment(Sema &S, BinaryOperator *E) {
+  // Just recurse on the LHS.
+  AnalyzeImplicitConversions(S, E->getLHS(), E->getOperatorLoc());
+
+  // We want to recurse on the RHS as normal unless we're assigning to
+  // a bitfield.
+  if (FieldDecl *Bitfield = E->getLHS()->getBitField()) {
+    if (AnalyzeBitFieldAssignment(S, Bitfield, E->getRHS(),
+                                  E->getOperatorLoc())) {
+      // Recurse, ignoring any implicit conversions on the RHS.
+      return AnalyzeImplicitConversions(S, E->getRHS()->IgnoreParenImpCasts(),
+                                        E->getOperatorLoc());
+    }
+  }
+
+  AnalyzeImplicitConversions(S, E->getRHS(), E->getOperatorLoc());
+}
+
+/// Diagnose an implicit cast;  purely a helper for CheckImplicitConversion.
+static void DiagnoseImpCast(Sema &S, Expr *E, QualType SourceType, QualType T, 
+                            SourceLocation CContext, unsigned diag,
+                            bool pruneControlFlow = false) {
+  if (pruneControlFlow) {
+    S.DiagRuntimeBehavior(E->getExprLoc(), E,
+                          S.PDiag(diag)
+                            << SourceType << T << E->getSourceRange()
+                            << SourceRange(CContext));
+    return;
+  }
+  S.Diag(E->getExprLoc(), diag)
+    << SourceType << T << E->getSourceRange() << SourceRange(CContext);
+}
+
+/// Diagnose an implicit cast;  purely a helper for CheckImplicitConversion.
+static void DiagnoseImpCast(Sema &S, Expr *E, QualType T,
+                            SourceLocation CContext, unsigned diag,
+                            bool pruneControlFlow = false) {
+  DiagnoseImpCast(S, E, E->getType(), T, CContext, diag, pruneControlFlow);
+}
+
+/// Diagnose an implicit cast from a literal expression. Does not warn when the
+/// cast wouldn't lose information.
+void DiagnoseFloatingLiteralImpCast(Sema &S, FloatingLiteral *FL, QualType T,
+                                    SourceLocation CContext) {
+  // Try to convert the literal exactly to an integer. If we can, don't warn.
+  bool isExact = false;
+  const llvm::APFloat &Value = FL->getValue();
+  llvm::APSInt IntegerValue(S.Context.getIntWidth(T),
+                            T->hasUnsignedIntegerRepresentation());
+  if (Value.convertToInteger(IntegerValue,
+                             llvm::APFloat::rmTowardZero, &isExact)
+      == llvm::APFloat::opOK && isExact)
+    return;
+
+  S.Diag(FL->getExprLoc(), diag::warn_impcast_literal_float_to_integer)
+    << FL->getType() << T << FL->getSourceRange() << SourceRange(CContext);
+}
+
+std::string PrettyPrintInRange(const llvm::APSInt &Value, IntRange Range) {
+  if (!Range.Width) return "0";
+
+  llvm::APSInt ValueInRange = Value;
+  ValueInRange.setIsSigned(!Range.NonNegative);
+  ValueInRange = ValueInRange.trunc(Range.Width);
+  return ValueInRange.toString(10);
+}
+
+void CheckImplicitConversion(Sema &S, Expr *E, QualType T,
+                             SourceLocation CC, bool *ICContext = 0) {
+  if (E->isTypeDependent() || E->isValueDependent()) return;
+
+  const Type *Source = S.Context.getCanonicalType(E->getType()).getTypePtr();
+  const Type *Target = S.Context.getCanonicalType(T).getTypePtr();
+  if (Source == Target) return;
+  if (Target->isDependentType()) return;
+
+  // If the conversion context location is invalid don't complain. We also
+  // don't want to emit a warning if the issue occurs from the expansion of
+  // a system macro. The problem is that 'getSpellingLoc()' is slow, so we
+  // delay this check as long as possible. Once we detect we are in that
+  // scenario, we just return.
+  if (CC.isInvalid())
+    return;
+
+  // Diagnose implicit casts to bool.
+  if (Target->isSpecificBuiltinType(BuiltinType::Bool)) {
+    if (isa<StringLiteral>(E))
+      // Warn on string literal to bool.  Checks for string literals in logical
+      // expressions, for instances, assert(0 && "error here"), is prevented
+      // by a check in AnalyzeImplicitConversions().
+      return DiagnoseImpCast(S, E, T, CC,
+                             diag::warn_impcast_string_literal_to_bool);
+    if (Source->isFunctionType()) {
+      // Warn on function to bool. Checks free functions and static member
+      // functions. Weakly imported functions are excluded from the check,
+      // since it's common to test their value to check whether the linker
+      // found a definition for them.
+      ValueDecl *D = 0;
+      if (DeclRefExpr* R = dyn_cast<DeclRefExpr>(E)) {
+        D = R->getDecl();
+      } else if (MemberExpr *M = dyn_cast<MemberExpr>(E)) {
+        D = M->getMemberDecl();
+      }
+
+      if (D && !D->isWeak()) {
+        if (FunctionDecl* F = dyn_cast<FunctionDecl>(D)) {
+          S.Diag(E->getExprLoc(), diag::warn_impcast_function_to_bool)
+            << F << E->getSourceRange() << SourceRange(CC);
+          S.Diag(E->getExprLoc(), diag::note_function_to_bool_silence)
+            << FixItHint::CreateInsertion(E->getExprLoc(), "&");
+          QualType ReturnType;
+          UnresolvedSet<4> NonTemplateOverloads;
+          S.isExprCallable(*E, ReturnType, NonTemplateOverloads);
+          if (!ReturnType.isNull() 
+              && ReturnType->isSpecificBuiltinType(BuiltinType::Bool))
+            S.Diag(E->getExprLoc(), diag::note_function_to_bool_call)
+              << FixItHint::CreateInsertion(
+                 S.getPreprocessor().getLocForEndOfToken(E->getLocEnd()), "()");
+          return;
+        }
+      }
+    }
+    return; // Other casts to bool are not checked.
+  }
+
+  // Strip vector types.
+  if (isa<VectorType>(Source)) {
+    if (!isa<VectorType>(Target)) {
+      if (S.SourceMgr.isInSystemMacro(CC))
+        return;
+      return DiagnoseImpCast(S, E, T, CC, diag::warn_impcast_vector_scalar);
+    }
+    
+    // If the vector cast is cast between two vectors of the same size, it is
+    // a bitcast, not a conversion.
+    if (S.Context.getTypeSize(Source) == S.Context.getTypeSize(Target))
+      return;
+
+    Source = cast<VectorType>(Source)->getElementType().getTypePtr();
+    Target = cast<VectorType>(Target)->getElementType().getTypePtr();
+  }
+
+  // Strip complex types.
+  if (isa<ComplexType>(Source)) {
+    if (!isa<ComplexType>(Target)) {
+      if (S.SourceMgr.isInSystemMacro(CC))
+        return;
+
+      return DiagnoseImpCast(S, E, T, CC, diag::warn_impcast_complex_scalar);
+    }
+
+    Source = cast<ComplexType>(Source)->getElementType().getTypePtr();
+    Target = cast<ComplexType>(Target)->getElementType().getTypePtr();
+  }
+
+  const BuiltinType *SourceBT = dyn_cast<BuiltinType>(Source);
+  const BuiltinType *TargetBT = dyn_cast<BuiltinType>(Target);
+
+  // If the source is floating point...
+  if (SourceBT && SourceBT->isFloatingPoint()) {
+    // ...and the target is floating point...
+    if (TargetBT && TargetBT->isFloatingPoint()) {
+      // ...then warn if we're dropping FP rank.
+
+      // Builtin FP kinds are ordered by increasing FP rank.
+      if (SourceBT->getKind() > TargetBT->getKind()) {
+        // Don't warn about float constants that are precisely
+        // representable in the target type.
+        Expr::EvalResult result;
+        if (E->EvaluateAsRValue(result, S.Context)) {
+          // Value might be a float, a float vector, or a float complex.
+          if (IsSameFloatAfterCast(result.Val,
+                   S.Context.getFloatTypeSemantics(QualType(TargetBT, 0)),
+                   S.Context.getFloatTypeSemantics(QualType(SourceBT, 0))))
+            return;
+        }
+
+        if (S.SourceMgr.isInSystemMacro(CC))
+          return;
+
+        DiagnoseImpCast(S, E, T, CC, diag::warn_impcast_float_precision);
+      }
+      return;
+    }
+
+    // If the target is integral, always warn.    
+    if ((TargetBT && TargetBT->isInteger())) {
+      if (S.SourceMgr.isInSystemMacro(CC))
+        return;
+      
+      Expr *InnerE = E->IgnoreParenImpCasts();
+      // We also want to warn on, e.g., "int i = -1.234"
+      if (UnaryOperator *UOp = dyn_cast<UnaryOperator>(InnerE))
+        if (UOp->getOpcode() == UO_Minus || UOp->getOpcode() == UO_Plus)
+          InnerE = UOp->getSubExpr()->IgnoreParenImpCasts();
+
+      if (FloatingLiteral *FL = dyn_cast<FloatingLiteral>(InnerE)) {
+        DiagnoseFloatingLiteralImpCast(S, FL, T, CC);
+      } else {
+        DiagnoseImpCast(S, E, T, CC, diag::warn_impcast_float_integer);
+      }
+    }
+
+    return;
+  }
+
+  if (!Source->isIntegerType() || !Target->isIntegerType())
+    return;
+
+  if ((E->isNullPointerConstant(S.Context, Expr::NPC_ValueDependentIsNotNull)
+           == Expr::NPCK_GNUNull) && Target->isIntegerType()) {
+    SourceLocation Loc = E->getSourceRange().getBegin();
+    if (Loc.isMacroID())
+      Loc = S.SourceMgr.getImmediateExpansionRange(Loc).first;
+    S.Diag(Loc, diag::warn_impcast_null_pointer_to_integer)
+        << T << Loc << clang::SourceRange(CC);
+    return;
+  }
+
+  IntRange SourceRange = GetExprRange(S.Context, E);
+  IntRange TargetRange = IntRange::forTargetOfCanonicalType(S.Context, Target);
+
+  if (SourceRange.Width > TargetRange.Width) {
+    // If the source is a constant, use a default-on diagnostic.
+    // TODO: this should happen for bitfield stores, too.
+    llvm::APSInt Value(32);
+    if (E->isIntegerConstantExpr(Value, S.Context)) {
+      if (S.SourceMgr.isInSystemMacro(CC))
+        return;
+
+      std::string PrettySourceValue = Value.toString(10);
+      std::string PrettyTargetValue = PrettyPrintInRange(Value, TargetRange);
+
+      S.DiagRuntimeBehavior(E->getExprLoc(), E,
+        S.PDiag(diag::warn_impcast_integer_precision_constant)
+            << PrettySourceValue << PrettyTargetValue
+            << E->getType() << T << E->getSourceRange()
+            << clang::SourceRange(CC));
+      return;
+    }
+
+    // People want to build with -Wshorten-64-to-32 and not -Wconversion.
+    if (S.SourceMgr.isInSystemMacro(CC))
+      return;
+    
+    if (TargetRange.Width == 32 && S.Context.getIntWidth(E->getType()) == 64)
+      return DiagnoseImpCast(S, E, T, CC, diag::warn_impcast_integer_64_32,
+                             /* pruneControlFlow */ true);
+    return DiagnoseImpCast(S, E, T, CC, diag::warn_impcast_integer_precision);
+  }
+
+  if ((TargetRange.NonNegative && !SourceRange.NonNegative) ||
+      (!TargetRange.NonNegative && SourceRange.NonNegative &&
+       SourceRange.Width == TargetRange.Width)) {
+        
+    if (S.SourceMgr.isInSystemMacro(CC))
+      return;
+
+    unsigned DiagID = diag::warn_impcast_integer_sign;
+
+    // Traditionally, gcc has warned about this under -Wsign-compare.
+    // We also want to warn about it in -Wconversion.
+    // So if -Wconversion is off, use a completely identical diagnostic
+    // in the sign-compare group.
+    // The conditional-checking code will 
+    if (ICContext) {
+      DiagID = diag::warn_impcast_integer_sign_conditional;
+      *ICContext = true;
+    }
+
+    return DiagnoseImpCast(S, E, T, CC, DiagID);
+  }
+
+  // Diagnose conversions between different enumeration types.
+  // In C, we pretend that the type of an EnumConstantDecl is its enumeration
+  // type, to give us better diagnostics.
+  QualType SourceType = E->getType();
+  if (!S.getLangOpts().CPlusPlus) {
+    if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E))
+      if (EnumConstantDecl *ECD = dyn_cast<EnumConstantDecl>(DRE->getDecl())) {
+        EnumDecl *Enum = cast<EnumDecl>(ECD->getDeclContext());
+        SourceType = S.Context.getTypeDeclType(Enum);
+        Source = S.Context.getCanonicalType(SourceType).getTypePtr();
+      }
+  }
+  
+  if (const EnumType *SourceEnum = Source->getAs<EnumType>())
+    if (const EnumType *TargetEnum = Target->getAs<EnumType>())
+      if ((SourceEnum->getDecl()->getIdentifier() || 
+           SourceEnum->getDecl()->getTypedefNameForAnonDecl()) &&
+          (TargetEnum->getDecl()->getIdentifier() ||
+           TargetEnum->getDecl()->getTypedefNameForAnonDecl()) &&
+          SourceEnum != TargetEnum) {
+        if (S.SourceMgr.isInSystemMacro(CC))
+          return;
+
+        return DiagnoseImpCast(S, E, SourceType, T, CC, 
+                               diag::warn_impcast_different_enum_types);
+      }
+  
+  return;
+}
+
+void CheckConditionalOperator(Sema &S, ConditionalOperator *E, QualType T);
+
+void CheckConditionalOperand(Sema &S, Expr *E, QualType T,
+                             SourceLocation CC, bool &ICContext) {
+  E = E->IgnoreParenImpCasts();
+
+  if (isa<ConditionalOperator>(E))
+    return CheckConditionalOperator(S, cast<ConditionalOperator>(E), T);
+
+  AnalyzeImplicitConversions(S, E, CC);
+  if (E->getType() != T)
+    return CheckImplicitConversion(S, E, T, CC, &ICContext);
+  return;
+}
+
+void CheckConditionalOperator(Sema &S, ConditionalOperator *E, QualType T) {
+  SourceLocation CC = E->getQuestionLoc();
+
+  AnalyzeImplicitConversions(S, E->getCond(), CC);
+
+  bool Suspicious = false;
+  CheckConditionalOperand(S, E->getTrueExpr(), T, CC, Suspicious);
+  CheckConditionalOperand(S, E->getFalseExpr(), T, CC, Suspicious);
+
+  // If -Wconversion would have warned about either of the candidates
+  // for a signedness conversion to the context type...
+  if (!Suspicious) return;
+
+  // ...but it's currently ignored...
+  if (S.Diags.getDiagnosticLevel(diag::warn_impcast_integer_sign_conditional,
+                                 CC))
+    return;
+
+  // ...then check whether it would have warned about either of the
+  // candidates for a signedness conversion to the condition type.
+  if (E->getType() == T) return;
+ 
+  Suspicious = false;
+  CheckImplicitConversion(S, E->getTrueExpr()->IgnoreParenImpCasts(),
+                          E->getType(), CC, &Suspicious);
+  if (!Suspicious)
+    CheckImplicitConversion(S, E->getFalseExpr()->IgnoreParenImpCasts(),
+                            E->getType(), CC, &Suspicious);
+}
+
+/// AnalyzeImplicitConversions - Find and report any interesting
+/// implicit conversions in the given expression.  There are a couple
+/// of competing diagnostics here, -Wconversion and -Wsign-compare.
+void AnalyzeImplicitConversions(Sema &S, Expr *OrigE, SourceLocation CC) {
+  QualType T = OrigE->getType();
+  Expr *E = OrigE->IgnoreParenImpCasts();
+
+  if (E->isTypeDependent() || E->isValueDependent())
+    return;
+
+  // For conditional operators, we analyze the arguments as if they
+  // were being fed directly into the output.
+  if (isa<ConditionalOperator>(E)) {
+    ConditionalOperator *CO = cast<ConditionalOperator>(E);
+    CheckConditionalOperator(S, CO, T);
+    return;
+  }
+
+  // Go ahead and check any implicit conversions we might have skipped.
+  // The non-canonical typecheck is just an optimization;
+  // CheckImplicitConversion will filter out dead implicit conversions.
+  if (E->getType() != T)
+    CheckImplicitConversion(S, E, T, CC);
+
+  // Now continue drilling into this expression.
+
+  // Skip past explicit casts.
+  if (isa<ExplicitCastExpr>(E)) {
+    E = cast<ExplicitCastExpr>(E)->getSubExpr()->IgnoreParenImpCasts();
+    return AnalyzeImplicitConversions(S, E, CC);
+  }
+
+  if (BinaryOperator *BO = dyn_cast<BinaryOperator>(E)) {
+    // Do a somewhat different check with comparison operators.
+    if (BO->isComparisonOp())
+      return AnalyzeComparison(S, BO);
+
+    // And with simple assignments.
+    if (BO->getOpcode() == BO_Assign)
+      return AnalyzeAssignment(S, BO);
+  }
+
+  // These break the otherwise-useful invariant below.  Fortunately,
+  // we don't really need to recurse into them, because any internal
+  // expressions should have been analyzed already when they were
+  // built into statements.
+  if (isa<StmtExpr>(E)) return;
+
+  // Don't descend into unevaluated contexts.
+  if (isa<UnaryExprOrTypeTraitExpr>(E)) return;
+
+  // Now just recurse over the expression's children.
+  CC = E->getExprLoc();
+  BinaryOperator *BO = dyn_cast<BinaryOperator>(E);
+  bool IsLogicalOperator = BO && BO->isLogicalOp();
+  for (Stmt::child_range I = E->children(); I; ++I) {
+    Expr *ChildExpr = dyn_cast_or_null<Expr>(*I);
+    if (!ChildExpr)
+      continue;
+
+    if (IsLogicalOperator &&
+        isa<StringLiteral>(ChildExpr->IgnoreParenImpCasts()))
+      // Ignore checking string literals that are in logical operators.
+      continue;
+    AnalyzeImplicitConversions(S, ChildExpr, CC);
+  }
+}
+
+} // end anonymous namespace
+
+/// Diagnoses "dangerous" implicit conversions within the given
+/// expression (which is a full expression).  Implements -Wconversion
+/// and -Wsign-compare.
+///
+/// \param CC the "context" location of the implicit conversion, i.e.
+///   the most location of the syntactic entity requiring the implicit
+///   conversion
+void Sema::CheckImplicitConversions(Expr *E, SourceLocation CC) {
+  // Don't diagnose in unevaluated contexts.
+  if (ExprEvalContexts.back().Context == Sema::Unevaluated)
+    return;
+
+  // Don't diagnose for value- or type-dependent expressions.
+  if (E->isTypeDependent() || E->isValueDependent())
+    return;
+
+  // Check for array bounds violations in cases where the check isn't triggered
+  // elsewhere for other Expr types (like BinaryOperators), e.g. when an
+  // ArraySubscriptExpr is on the RHS of a variable initialization.
+  CheckArrayAccess(E);
+
+  // This is not the right CC for (e.g.) a variable initialization.
+  AnalyzeImplicitConversions(*this, E, CC);
+}
+
+void Sema::CheckBitFieldInitialization(SourceLocation InitLoc,
+                                       FieldDecl *BitField,
+                                       Expr *Init) {
+  (void) AnalyzeBitFieldAssignment(*this, BitField, Init, InitLoc);
+}
+
+/// CheckParmsForFunctionDef - Check that the parameters of the given
+/// function are appropriate for the definition of a function. This
+/// takes care of any checks that cannot be performed on the
+/// declaration itself, e.g., that the types of each of the function
+/// parameters are complete.
+bool Sema::CheckParmsForFunctionDef(ParmVarDecl **P, ParmVarDecl **PEnd,
+                                    bool CheckParameterNames) {
+  bool HasInvalidParm = false;
+  for (; P != PEnd; ++P) {
+    ParmVarDecl *Param = *P;
+    
+    // C99 6.7.5.3p4: the parameters in a parameter type list in a
+    // function declarator that is part of a function definition of
+    // that function shall not have incomplete type.
+    //
+    // This is also C++ [dcl.fct]p6.
+    if (!Param->isInvalidDecl() &&
+        RequireCompleteType(Param->getLocation(), Param->getType(),
+                               diag::err_typecheck_decl_incomplete_type)) {
+      Param->setInvalidDecl();
+      HasInvalidParm = true;
+    }
+
+    // C99 6.9.1p5: If the declarator includes a parameter type list, the
+    // declaration of each parameter shall include an identifier.
+    if (CheckParameterNames &&
+        Param->getIdentifier() == 0 &&
+        !Param->isImplicit() &&
+        !getLangOpts().CPlusPlus)
+      Diag(Param->getLocation(), diag::err_parameter_name_omitted);
+
+    // C99 6.7.5.3p12:
+    //   If the function declarator is not part of a definition of that
+    //   function, parameters may have incomplete type and may use the [*]
+    //   notation in their sequences of declarator specifiers to specify
+    //   variable length array types.
+    QualType PType = Param->getOriginalType();
+    if (const ArrayType *AT = Context.getAsArrayType(PType)) {
+      if (AT->getSizeModifier() == ArrayType::Star) {
+        // FIXME: This diagnosic should point the the '[*]' if source-location
+        // information is added for it.
+        Diag(Param->getLocation(), diag::err_array_star_in_function_definition);
+      }
+    }
+  }
+
+  return HasInvalidParm;
+}
+
+/// CheckCastAlign - Implements -Wcast-align, which warns when a
+/// pointer cast increases the alignment requirements.
+void Sema::CheckCastAlign(Expr *Op, QualType T, SourceRange TRange) {
+  // This is actually a lot of work to potentially be doing on every
+  // cast; don't do it if we're ignoring -Wcast_align (as is the default).
+  if (getDiagnostics().getDiagnosticLevel(diag::warn_cast_align,
+                                          TRange.getBegin())
+        == DiagnosticsEngine::Ignored)
+    return;
+
+  // Ignore dependent types.
+  if (T->isDependentType() || Op->getType()->isDependentType())
+    return;
+
+  // Require that the destination be a pointer type.
+  const PointerType *DestPtr = T->getAs<PointerType>();
+  if (!DestPtr) return;
+
+  // If the destination has alignment 1, we're done.
+  QualType DestPointee = DestPtr->getPointeeType();
+  if (DestPointee->isIncompleteType()) return;
+  CharUnits DestAlign = Context.getTypeAlignInChars(DestPointee);
+  if (DestAlign.isOne()) return;
+
+  // Require that the source be a pointer type.
+  const PointerType *SrcPtr = Op->getType()->getAs<PointerType>();
+  if (!SrcPtr) return;
+  QualType SrcPointee = SrcPtr->getPointeeType();
+
+  // Whitelist casts from cv void*.  We already implicitly
+  // whitelisted casts to cv void*, since they have alignment 1.
+  // Also whitelist casts involving incomplete types, which implicitly
+  // includes 'void'.
+  if (SrcPointee->isIncompleteType()) return;
+
+  CharUnits SrcAlign = Context.getTypeAlignInChars(SrcPointee);
+  if (SrcAlign >= DestAlign) return;
+
+  Diag(TRange.getBegin(), diag::warn_cast_align)
+    << Op->getType() << T
+    << static_cast<unsigned>(SrcAlign.getQuantity())
+    << static_cast<unsigned>(DestAlign.getQuantity())
+    << TRange << Op->getSourceRange();
+}
+
+static const Type* getElementType(const Expr *BaseExpr) {
+  const Type* EltType = BaseExpr->getType().getTypePtr();
+  if (EltType->isAnyPointerType())
+    return EltType->getPointeeType().getTypePtr();
+  else if (EltType->isArrayType())
+    return EltType->getBaseElementTypeUnsafe();
+  return EltType;
+}
+
+/// \brief Check whether this array fits the idiom of a size-one tail padded
+/// array member of a struct.
+///
+/// We avoid emitting out-of-bounds access warnings for such arrays as they are
+/// commonly used to emulate flexible arrays in C89 code.
+static bool IsTailPaddedMemberArray(Sema &S, llvm::APInt Size,
+                                    const NamedDecl *ND) {
+  if (Size != 1 || !ND) return false;
+
+  const FieldDecl *FD = dyn_cast<FieldDecl>(ND);
+  if (!FD) return false;
+
+  // Don't consider sizes resulting from macro expansions or template argument
+  // substitution to form C89 tail-padded arrays.
+  ConstantArrayTypeLoc TL =
+    cast<ConstantArrayTypeLoc>(FD->getTypeSourceInfo()->getTypeLoc());
+  const Expr *SizeExpr = dyn_cast<IntegerLiteral>(TL.getSizeExpr());
+  if (!SizeExpr || SizeExpr->getExprLoc().isMacroID())
+    return false;
+
+  const RecordDecl *RD = dyn_cast<RecordDecl>(FD->getDeclContext());
+  if (!RD) return false;
+  if (RD->isUnion()) return false;
+  if (const CXXRecordDecl *CRD = dyn_cast<CXXRecordDecl>(RD)) {
+    if (!CRD->isStandardLayout()) return false;
+  }
+
+  // See if this is the last field decl in the record.
+  const Decl *D = FD;
+  while ((D = D->getNextDeclInContext()))
+    if (isa<FieldDecl>(D))
+      return false;
+  return true;
+}
+
+void Sema::CheckArrayAccess(const Expr *BaseExpr, const Expr *IndexExpr,
+                            const ArraySubscriptExpr *ASE,
+                            bool AllowOnePastEnd, bool IndexNegated) {
+  IndexExpr = IndexExpr->IgnoreParenImpCasts();
+  if (IndexExpr->isValueDependent())
+    return;
+
+  const Type *EffectiveType = getElementType(BaseExpr);
+  BaseExpr = BaseExpr->IgnoreParenCasts();
+  const ConstantArrayType *ArrayTy =
+    Context.getAsConstantArrayType(BaseExpr->getType());
+  if (!ArrayTy)
+    return;
+
+  llvm::APSInt index;
+  if (!IndexExpr->EvaluateAsInt(index, Context))
+    return;
+  if (IndexNegated)
+    index = -index;
+
+  const NamedDecl *ND = NULL;
+  if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(BaseExpr))
+    ND = dyn_cast<NamedDecl>(DRE->getDecl());
+  if (const MemberExpr *ME = dyn_cast<MemberExpr>(BaseExpr))
+    ND = dyn_cast<NamedDecl>(ME->getMemberDecl());
+
+  if (index.isUnsigned() || !index.isNegative()) {
+    llvm::APInt size = ArrayTy->getSize();
+    if (!size.isStrictlyPositive())
+      return;
+
+    const Type* BaseType = getElementType(BaseExpr);
+    if (BaseType != EffectiveType) {
+      // Make sure we're comparing apples to apples when comparing index to size
+      uint64_t ptrarith_typesize = Context.getTypeSize(EffectiveType);
+      uint64_t array_typesize = Context.getTypeSize(BaseType);
+      // Handle ptrarith_typesize being zero, such as when casting to void*
+      if (!ptrarith_typesize) ptrarith_typesize = 1;
+      if (ptrarith_typesize != array_typesize) {
+        // There's a cast to a different size type involved
+        uint64_t ratio = array_typesize / ptrarith_typesize;
+        // TODO: Be smarter about handling cases where array_typesize is not a
+        // multiple of ptrarith_typesize
+        if (ptrarith_typesize * ratio == array_typesize)
+          size *= llvm::APInt(size.getBitWidth(), ratio);
+      }
+    }
+
+    if (size.getBitWidth() > index.getBitWidth())
+      index = index.zext(size.getBitWidth());
+    else if (size.getBitWidth() < index.getBitWidth())
+      size = size.zext(index.getBitWidth());
+
+    // For array subscripting the index must be less than size, but for pointer
+    // arithmetic also allow the index (offset) to be equal to size since
+    // computing the next address after the end of the array is legal and
+    // commonly done e.g. in C++ iterators and range-based for loops.
+    if (AllowOnePastEnd ? index.ule(size) : index.ult(size))
+      return;
+
+    // Also don't warn for arrays of size 1 which are members of some
+    // structure. These are often used to approximate flexible arrays in C89
+    // code.
+    if (IsTailPaddedMemberArray(*this, size, ND))
+      return;
+
+    // Suppress the warning if the subscript expression (as identified by the
+    // ']' location) and the index expression are both from macro expansions
+    // within a system header.
+    if (ASE) {
+      SourceLocation RBracketLoc = SourceMgr.getSpellingLoc(
+          ASE->getRBracketLoc());
+      if (SourceMgr.isInSystemHeader(RBracketLoc)) {
+        SourceLocation IndexLoc = SourceMgr.getSpellingLoc(
+            IndexExpr->getLocStart());
+        if (SourceMgr.isFromSameFile(RBracketLoc, IndexLoc))
+          return;
+      }
+    }
+
+    unsigned DiagID = diag::warn_ptr_arith_exceeds_bounds;
+    if (ASE)
+      DiagID = diag::warn_array_index_exceeds_bounds;
+
+    DiagRuntimeBehavior(BaseExpr->getLocStart(), BaseExpr,
+                        PDiag(DiagID) << index.toString(10, true)
+                          << size.toString(10, true)
+                          << (unsigned)size.getLimitedValue(~0U)
+                          << IndexExpr->getSourceRange());
+  } else {
+    unsigned DiagID = diag::warn_array_index_precedes_bounds;
+    if (!ASE) {
+      DiagID = diag::warn_ptr_arith_precedes_bounds;
+      if (index.isNegative()) index = -index;
+    }
+
+    DiagRuntimeBehavior(BaseExpr->getLocStart(), BaseExpr,
+                        PDiag(DiagID) << index.toString(10, true)
+                          << IndexExpr->getSourceRange());
+  }
+
+  if (!ND) {
+    // Try harder to find a NamedDecl to point at in the note.
+    while (const ArraySubscriptExpr *ASE =
+           dyn_cast<ArraySubscriptExpr>(BaseExpr))
+      BaseExpr = ASE->getBase()->IgnoreParenCasts();
+    if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(BaseExpr))
+      ND = dyn_cast<NamedDecl>(DRE->getDecl());
+    if (const MemberExpr *ME = dyn_cast<MemberExpr>(BaseExpr))
+      ND = dyn_cast<NamedDecl>(ME->getMemberDecl());
+  }
+
+  if (ND)
+    DiagRuntimeBehavior(ND->getLocStart(), BaseExpr,
+                        PDiag(diag::note_array_index_out_of_bounds)
+                          << ND->getDeclName());
+}
+
+void Sema::CheckArrayAccess(const Expr *expr) {
+  int AllowOnePastEnd = 0;
+  while (expr) {
+    expr = expr->IgnoreParenImpCasts();
+    switch (expr->getStmtClass()) {
+      case Stmt::ArraySubscriptExprClass: {
+        const ArraySubscriptExpr *ASE = cast<ArraySubscriptExpr>(expr);
+        CheckArrayAccess(ASE->getBase(), ASE->getIdx(), ASE,
+                         AllowOnePastEnd > 0);
+        return;
+      }
+      case Stmt::UnaryOperatorClass: {
+        // Only unwrap the * and & unary operators
+        const UnaryOperator *UO = cast<UnaryOperator>(expr);
+        expr = UO->getSubExpr();
+        switch (UO->getOpcode()) {
+          case UO_AddrOf:
+            AllowOnePastEnd++;
+            break;
+          case UO_Deref:
+            AllowOnePastEnd--;
+            break;
+          default:
+            return;
+        }
+        break;
+      }
+      case Stmt::ConditionalOperatorClass: {
+        const ConditionalOperator *cond = cast<ConditionalOperator>(expr);
+        if (const Expr *lhs = cond->getLHS())
+          CheckArrayAccess(lhs);
+        if (const Expr *rhs = cond->getRHS())
+          CheckArrayAccess(rhs);
+        return;
+      }
+      default:
+        return;
+    }
+  }
+}
+
+//===--- CHECK: Objective-C retain cycles ----------------------------------//
+
+namespace {
+  struct RetainCycleOwner {
+    RetainCycleOwner() : Variable(0), Indirect(false) {}
+    VarDecl *Variable;
+    SourceRange Range;
+    SourceLocation Loc;
+    bool Indirect;
+
+    void setLocsFrom(Expr *e) {
+      Loc = e->getExprLoc();
+      Range = e->getSourceRange();
+    }
+  };
+}
+
+/// Consider whether capturing the given variable can possibly lead to
+/// a retain cycle.
+static bool considerVariable(VarDecl *var, Expr *ref, RetainCycleOwner &owner) {
+  // In ARC, it's captured strongly iff the variable has __strong
+  // lifetime.  In MRR, it's captured strongly if the variable is
+  // __block and has an appropriate type.
+  if (var->getType().getObjCLifetime() != Qualifiers::OCL_Strong)
+    return false;
+
+  owner.Variable = var;
+  owner.setLocsFrom(ref);
+  return true;
+}
+
+static bool findRetainCycleOwner(Sema &S, Expr *e, RetainCycleOwner &owner) {
+  while (true) {
+    e = e->IgnoreParens();
+    if (CastExpr *cast = dyn_cast<CastExpr>(e)) {
+      switch (cast->getCastKind()) {
+      case CK_BitCast:
+      case CK_LValueBitCast:
+      case CK_LValueToRValue:
+      case CK_ARCReclaimReturnedObject:
+        e = cast->getSubExpr();
+        continue;
+
+      default:
+        return false;
+      }
+    }
+
+    if (ObjCIvarRefExpr *ref = dyn_cast<ObjCIvarRefExpr>(e)) {
+      ObjCIvarDecl *ivar = ref->getDecl();
+      if (ivar->getType().getObjCLifetime() != Qualifiers::OCL_Strong)
+        return false;
+
+      // Try to find a retain cycle in the base.
+      if (!findRetainCycleOwner(S, ref->getBase(), owner))
+        return false;
+
+      if (ref->isFreeIvar()) owner.setLocsFrom(ref);
+      owner.Indirect = true;
+      return true;
+    }
+
+    if (DeclRefExpr *ref = dyn_cast<DeclRefExpr>(e)) {
+      VarDecl *var = dyn_cast<VarDecl>(ref->getDecl());
+      if (!var) return false;
+      return considerVariable(var, ref, owner);
+    }
+
+    if (MemberExpr *member = dyn_cast<MemberExpr>(e)) {
+      if (member->isArrow()) return false;
+
+      // Don't count this as an indirect ownership.
+      e = member->getBase();
+      continue;
+    }
+
+    if (PseudoObjectExpr *pseudo = dyn_cast<PseudoObjectExpr>(e)) {
+      // Only pay attention to pseudo-objects on property references.
+      ObjCPropertyRefExpr *pre
+        = dyn_cast<ObjCPropertyRefExpr>(pseudo->getSyntacticForm()
+                                              ->IgnoreParens());
+      if (!pre) return false;
+      if (pre->isImplicitProperty()) return false;
+      ObjCPropertyDecl *property = pre->getExplicitProperty();
+      if (!property->isRetaining() &&
+          !(property->getPropertyIvarDecl() &&
+            property->getPropertyIvarDecl()->getType()
+              .getObjCLifetime() == Qualifiers::OCL_Strong))
+          return false;
+
+      owner.Indirect = true;
+      if (pre->isSuperReceiver()) {
+        owner.Variable = S.getCurMethodDecl()->getSelfDecl();
+        if (!owner.Variable)
+          return false;
+        owner.Loc = pre->getLocation();
+        owner.Range = pre->getSourceRange();
+        return true;
+      }
+      e = const_cast<Expr*>(cast<OpaqueValueExpr>(pre->getBase())
+                              ->getSourceExpr());
+      continue;
+    }
+
+    // Array ivars?
+
+    return false;
+  }
+}
+
+namespace {
+  struct FindCaptureVisitor : EvaluatedExprVisitor<FindCaptureVisitor> {
+    FindCaptureVisitor(ASTContext &Context, VarDecl *variable)
+      : EvaluatedExprVisitor<FindCaptureVisitor>(Context),
+        Variable(variable), Capturer(0) {}
+
+    VarDecl *Variable;
+    Expr *Capturer;
+
+    void VisitDeclRefExpr(DeclRefExpr *ref) {
+      if (ref->getDecl() == Variable && !Capturer)
+        Capturer = ref;
+    }
+
+    void VisitObjCIvarRefExpr(ObjCIvarRefExpr *ref) {
+      if (Capturer) return;
+      Visit(ref->getBase());
+      if (Capturer && ref->isFreeIvar())
+        Capturer = ref;
+    }
+
+    void VisitBlockExpr(BlockExpr *block) {
+      // Look inside nested blocks 
+      if (block->getBlockDecl()->capturesVariable(Variable))
+        Visit(block->getBlockDecl()->getBody());
+    }
+  };
+}
+
+/// Check whether the given argument is a block which captures a
+/// variable.
+static Expr *findCapturingExpr(Sema &S, Expr *e, RetainCycleOwner &owner) {
+  assert(owner.Variable && owner.Loc.isValid());
+
+  e = e->IgnoreParenCasts();
+  BlockExpr *block = dyn_cast<BlockExpr>(e);
+  if (!block || !block->getBlockDecl()->capturesVariable(owner.Variable))
+    return 0;
+
+  FindCaptureVisitor visitor(S.Context, owner.Variable);
+  visitor.Visit(block->getBlockDecl()->getBody());
+  return visitor.Capturer;
+}
+
+static void diagnoseRetainCycle(Sema &S, Expr *capturer,
+                                RetainCycleOwner &owner) {
+  assert(capturer);
+  assert(owner.Variable && owner.Loc.isValid());
+
+  S.Diag(capturer->getExprLoc(), diag::warn_arc_retain_cycle)
+    << owner.Variable << capturer->getSourceRange();
+  S.Diag(owner.Loc, diag::note_arc_retain_cycle_owner)
+    << owner.Indirect << owner.Range;
+}
+
+/// Check for a keyword selector that starts with the word 'add' or
+/// 'set'.
+static bool isSetterLikeSelector(Selector sel) {
+  if (sel.isUnarySelector()) return false;
+
+  StringRef str = sel.getNameForSlot(0);
+  while (!str.empty() && str.front() == '_') str = str.substr(1);
+  if (str.startswith("set"))
+    str = str.substr(3);
+  else if (str.startswith("add")) {
+    // Specially whitelist 'addOperationWithBlock:'.
+    if (sel.getNumArgs() == 1 && str.startswith("addOperationWithBlock"))
+      return false;
+    str = str.substr(3);
+  }
+  else
+    return false;
+
+  if (str.empty()) return true;
+  return !islower(str.front());
+}
+
+/// Check a message send to see if it's likely to cause a retain cycle.
+void Sema::checkRetainCycles(ObjCMessageExpr *msg) {
+  // Only check instance methods whose selector looks like a setter.
+  if (!msg->isInstanceMessage() || !isSetterLikeSelector(msg->getSelector()))
+    return;
+
+  // Try to find a variable that the receiver is strongly owned by.
+  RetainCycleOwner owner;
+  if (msg->getReceiverKind() == ObjCMessageExpr::Instance) {
+    if (!findRetainCycleOwner(*this, msg->getInstanceReceiver(), owner))
+      return;
+  } else {
+    assert(msg->getReceiverKind() == ObjCMessageExpr::SuperInstance);
+    owner.Variable = getCurMethodDecl()->getSelfDecl();
+    owner.Loc = msg->getSuperLoc();
+    owner.Range = msg->getSuperLoc();
+  }
+
+  // Check whether the receiver is captured by any of the arguments.
+  for (unsigned i = 0, e = msg->getNumArgs(); i != e; ++i)
+    if (Expr *capturer = findCapturingExpr(*this, msg->getArg(i), owner))
+      return diagnoseRetainCycle(*this, capturer, owner);
+}
+
+/// Check a property assign to see if it's likely to cause a retain cycle.
+void Sema::checkRetainCycles(Expr *receiver, Expr *argument) {
+  RetainCycleOwner owner;
+  if (!findRetainCycleOwner(*this, receiver, owner))
+    return;
+
+  if (Expr *capturer = findCapturingExpr(*this, argument, owner))
+    diagnoseRetainCycle(*this, capturer, owner);
+}
+
+bool Sema::checkUnsafeAssigns(SourceLocation Loc,
+                              QualType LHS, Expr *RHS) {
+  Qualifiers::ObjCLifetime LT = LHS.getObjCLifetime();
+  if (LT != Qualifiers::OCL_Weak && LT != Qualifiers::OCL_ExplicitNone)
+    return false;
+  // strip off any implicit cast added to get to the one arc-specific
+  while (ImplicitCastExpr *cast = dyn_cast<ImplicitCastExpr>(RHS)) {
+    if (cast->getCastKind() == CK_ARCConsumeObject) {
+      Diag(Loc, diag::warn_arc_retained_assign)
+        << (LT == Qualifiers::OCL_ExplicitNone) 
+        << RHS->getSourceRange();
+      return true;
+    }
+    RHS = cast->getSubExpr();
+  }
+  return false;
+}
+
+void Sema::checkUnsafeExprAssigns(SourceLocation Loc,
+                              Expr *LHS, Expr *RHS) {
+  QualType LHSType;
+  // PropertyRef on LHS type need be directly obtained from
+  // its declaration as it has a PsuedoType.
+  ObjCPropertyRefExpr *PRE
+    = dyn_cast<ObjCPropertyRefExpr>(LHS->IgnoreParens());
+  if (PRE && !PRE->isImplicitProperty()) {
+    const ObjCPropertyDecl *PD = PRE->getExplicitProperty();
+    if (PD)
+      LHSType = PD->getType();
+  }
+  
+  if (LHSType.isNull())
+    LHSType = LHS->getType();
+  if (checkUnsafeAssigns(Loc, LHSType, RHS))
+    return;
+  Qualifiers::ObjCLifetime LT = LHSType.getObjCLifetime();
+  // FIXME. Check for other life times.
+  if (LT != Qualifiers::OCL_None)
+    return;
+  
+  if (PRE) {
+    if (PRE->isImplicitProperty())
+      return;
+    const ObjCPropertyDecl *PD = PRE->getExplicitProperty();
+    if (!PD)
+      return;
+    
+    unsigned Attributes = PD->getPropertyAttributes();
+    if (Attributes & ObjCPropertyDecl::OBJC_PR_assign) {
+      // when 'assign' attribute was not explicitly specified
+      // by user, ignore it and rely on property type itself
+      // for lifetime info.
+      unsigned AsWrittenAttr = PD->getPropertyAttributesAsWritten();
+      if (!(AsWrittenAttr & ObjCPropertyDecl::OBJC_PR_assign) &&
+          LHSType->isObjCRetainableType())
+        return;
+        
+      while (ImplicitCastExpr *cast = dyn_cast<ImplicitCastExpr>(RHS)) {
+        if (cast->getCastKind() == CK_ARCConsumeObject) {
+          Diag(Loc, diag::warn_arc_retained_property_assign)
+          << RHS->getSourceRange();
+          return;
+        }
+        RHS = cast->getSubExpr();
+      }
+    }
+  }
+}
+
+//===--- CHECK: Empty statement body (-Wempty-body) ---------------------===//
+
+namespace {
+bool ShouldDiagnoseEmptyStmtBody(const SourceManager &SourceMgr,
+                                 SourceLocation StmtLoc,
+                                 const NullStmt *Body) {
+  // Do not warn if the body is a macro that expands to nothing, e.g:
+  //
+  // #define CALL(x)
+  // if (condition)
+  //   CALL(0);
+  //
+  if (Body->hasLeadingEmptyMacro())
+    return false;
+
+  // Get line numbers of statement and body.
+  bool StmtLineInvalid;
+  unsigned StmtLine = SourceMgr.getSpellingLineNumber(StmtLoc,
+                                                      &StmtLineInvalid);
+  if (StmtLineInvalid)
+    return false;
+
+  bool BodyLineInvalid;
+  unsigned BodyLine = SourceMgr.getSpellingLineNumber(Body->getSemiLoc(),
+                                                      &BodyLineInvalid);
+  if (BodyLineInvalid)
+    return false;
+
+  // Warn if null statement and body are on the same line.
+  if (StmtLine != BodyLine)
+    return false;
+
+  return true;
+}
+} // Unnamed namespace
+
+void Sema::DiagnoseEmptyStmtBody(SourceLocation StmtLoc,
+                                 const Stmt *Body,
+                                 unsigned DiagID) {
+  // Since this is a syntactic check, don't emit diagnostic for template
+  // instantiations, this just adds noise.
+  if (CurrentInstantiationScope)
+    return;
+
+  // The body should be a null statement.
+  const NullStmt *NBody = dyn_cast<NullStmt>(Body);
+  if (!NBody)
+    return;
+
+  // Do the usual checks.
+  if (!ShouldDiagnoseEmptyStmtBody(SourceMgr, StmtLoc, NBody))
+    return;
+
+  Diag(NBody->getSemiLoc(), DiagID);
+  Diag(NBody->getSemiLoc(), diag::note_empty_body_on_separate_line);
+}
+
+void Sema::DiagnoseEmptyLoopBody(const Stmt *S,
+                                 const Stmt *PossibleBody) {
+  assert(!CurrentInstantiationScope); // Ensured by caller
+
+  SourceLocation StmtLoc;
+  const Stmt *Body;
+  unsigned DiagID;
+  if (const ForStmt *FS = dyn_cast<ForStmt>(S)) {
+    StmtLoc = FS->getRParenLoc();
+    Body = FS->getBody();
+    DiagID = diag::warn_empty_for_body;
+  } else if (const WhileStmt *WS = dyn_cast<WhileStmt>(S)) {
+    StmtLoc = WS->getCond()->getSourceRange().getEnd();
+    Body = WS->getBody();
+    DiagID = diag::warn_empty_while_body;
+  } else
+    return; // Neither `for' nor `while'.
+
+  // The body should be a null statement.
+  const NullStmt *NBody = dyn_cast<NullStmt>(Body);
+  if (!NBody)
+    return;
+
+  // Skip expensive checks if diagnostic is disabled.
+  if (Diags.getDiagnosticLevel(DiagID, NBody->getSemiLoc()) ==
+          DiagnosticsEngine::Ignored)
+    return;
+
+  // Do the usual checks.
+  if (!ShouldDiagnoseEmptyStmtBody(SourceMgr, StmtLoc, NBody))
+    return;
+
+  // `for(...);' and `while(...);' are popular idioms, so in order to keep
+  // noise level low, emit diagnostics only if for/while is followed by a
+  // CompoundStmt, e.g.:
+  //    for (int i = 0; i < n; i++);
+  //    {
+  //      a(i);
+  //    }
+  // or if for/while is followed by a statement with more indentation
+  // than for/while itself:
+  //    for (int i = 0; i < n; i++);
+  //      a(i);
+  bool ProbableTypo = isa<CompoundStmt>(PossibleBody);
+  if (!ProbableTypo) {
+    bool BodyColInvalid;
+    unsigned BodyCol = SourceMgr.getPresumedColumnNumber(
+                             PossibleBody->getLocStart(),
+                             &BodyColInvalid);
+    if (BodyColInvalid)
+      return;
+
+    bool StmtColInvalid;
+    unsigned StmtCol = SourceMgr.getPresumedColumnNumber(
+                             S->getLocStart(),
+                             &StmtColInvalid);
+    if (StmtColInvalid)
+      return;
+
+    if (BodyCol > StmtCol)
+      ProbableTypo = true;
+  }
+
+  if (ProbableTypo) {
+    Diag(NBody->getSemiLoc(), DiagID);
+    Diag(NBody->getSemiLoc(), diag::note_empty_body_on_separate_line);
+  }
+}
diff --git a/clang/lib/Sema/SemaCodeComplete.cpp b/clang/lib/Sema/SemaCodeComplete.cpp
new file mode 100644
index 0000000..1ee7532
--- /dev/null
+++ b/clang/lib/Sema/SemaCodeComplete.cpp
@@ -0,0 +1,7178 @@
+//===---------------- SemaCodeComplete.cpp - Code Completion ----*- 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 code-completion semantic actions.
+//
+//===----------------------------------------------------------------------===//
+#include "clang/Sema/SemaInternal.h"
+#include "clang/Sema/Lookup.h"
+#include "clang/Sema/Overload.h"
+#include "clang/Sema/CodeCompleteConsumer.h"
+#include "clang/Sema/ExternalSemaSource.h"
+#include "clang/Sema/Scope.h"
+#include "clang/Sema/ScopeInfo.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/AST/ExprCXX.h"
+#include "clang/AST/ExprObjC.h"
+#include "clang/Lex/HeaderSearch.h"
+#include "clang/Lex/MacroInfo.h"
+#include "clang/Lex/Preprocessor.h"
+#include "llvm/ADT/DenseSet.h"
+#include "llvm/ADT/SmallBitVector.h"
+#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/StringSwitch.h"
+#include "llvm/ADT/Twine.h"
+#include <list>
+#include <map>
+#include <vector>
+
+using namespace clang;
+using namespace sema;
+
+namespace {
+  /// \brief A container of code-completion results.
+  class ResultBuilder {
+  public:
+    /// \brief The type of a name-lookup filter, which can be provided to the
+    /// name-lookup routines to specify which declarations should be included in
+    /// the result set (when it returns true) and which declarations should be
+    /// filtered out (returns false).
+    typedef bool (ResultBuilder::*LookupFilter)(NamedDecl *) const;
+    
+    typedef CodeCompletionResult Result;
+    
+  private:
+    /// \brief The actual results we have found.
+    std::vector<Result> Results;
+    
+    /// \brief A record of all of the declarations we have found and placed
+    /// into the result set, used to ensure that no declaration ever gets into
+    /// the result set twice.
+    llvm::SmallPtrSet<Decl*, 16> AllDeclsFound;
+    
+    typedef std::pair<NamedDecl *, unsigned> DeclIndexPair;
+
+    /// \brief An entry in the shadow map, which is optimized to store
+    /// a single (declaration, index) mapping (the common case) but
+    /// can also store a list of (declaration, index) mappings.
+    class ShadowMapEntry {
+      typedef SmallVector<DeclIndexPair, 4> DeclIndexPairVector;
+
+      /// \brief Contains either the solitary NamedDecl * or a vector
+      /// of (declaration, index) pairs.
+      llvm::PointerUnion<NamedDecl *, DeclIndexPairVector*> DeclOrVector;
+
+      /// \brief When the entry contains a single declaration, this is
+      /// the index associated with that entry.
+      unsigned SingleDeclIndex;
+
+    public:
+      ShadowMapEntry() : DeclOrVector(), SingleDeclIndex(0) { }
+
+      void Add(NamedDecl *ND, unsigned Index) {
+        if (DeclOrVector.isNull()) {
+          // 0 - > 1 elements: just set the single element information.
+          DeclOrVector = ND;
+          SingleDeclIndex = Index;
+          return;
+        }
+
+        if (NamedDecl *PrevND = DeclOrVector.dyn_cast<NamedDecl *>()) {
+          // 1 -> 2 elements: create the vector of results and push in the
+          // existing declaration.
+          DeclIndexPairVector *Vec = new DeclIndexPairVector;
+          Vec->push_back(DeclIndexPair(PrevND, SingleDeclIndex));
+          DeclOrVector = Vec;
+        }
+
+        // Add the new element to the end of the vector.
+        DeclOrVector.get<DeclIndexPairVector*>()->push_back(
+                                                    DeclIndexPair(ND, Index));
+      }
+
+      void Destroy() {
+        if (DeclIndexPairVector *Vec
+              = DeclOrVector.dyn_cast<DeclIndexPairVector *>()) {
+          delete Vec;
+          DeclOrVector = ((NamedDecl *)0);
+        }
+      }
+
+      // Iteration.
+      class iterator;
+      iterator begin() const;
+      iterator end() const;
+    };
+
+    /// \brief A mapping from declaration names to the declarations that have
+    /// this name within a particular scope and their index within the list of
+    /// results.
+    typedef llvm::DenseMap<DeclarationName, ShadowMapEntry> ShadowMap;
+    
+    /// \brief The semantic analysis object for which results are being 
+    /// produced.
+    Sema &SemaRef;
+
+    /// \brief The allocator used to allocate new code-completion strings.
+    CodeCompletionAllocator &Allocator;
+
+    CodeCompletionTUInfo &CCTUInfo;
+    
+    /// \brief If non-NULL, a filter function used to remove any code-completion
+    /// results that are not desirable.
+    LookupFilter Filter;
+
+    /// \brief Whether we should allow declarations as
+    /// nested-name-specifiers that would otherwise be filtered out.
+    bool AllowNestedNameSpecifiers;
+
+    /// \brief If set, the type that we would prefer our resulting value
+    /// declarations to have.
+    ///
+    /// Closely matching the preferred type gives a boost to a result's 
+    /// priority.
+    CanQualType PreferredType;
+    
+    /// \brief A list of shadow maps, which is used to model name hiding at
+    /// different levels of, e.g., the inheritance hierarchy.
+    std::list<ShadowMap> ShadowMaps;
+    
+    /// \brief If we're potentially referring to a C++ member function, the set
+    /// of qualifiers applied to the object type.
+    Qualifiers ObjectTypeQualifiers;
+    
+    /// \brief Whether the \p ObjectTypeQualifiers field is active.
+    bool HasObjectTypeQualifiers;
+    
+    /// \brief The selector that we prefer.
+    Selector PreferredSelector;
+    
+    /// \brief The completion context in which we are gathering results.
+    CodeCompletionContext CompletionContext;
+    
+    /// \brief If we are in an instance method definition, the @implementation
+    /// object.
+    ObjCImplementationDecl *ObjCImplementation;
+    
+    void AdjustResultPriorityForDecl(Result &R);
+
+    void MaybeAddConstructorResults(Result R);
+    
+  public:
+    explicit ResultBuilder(Sema &SemaRef, CodeCompletionAllocator &Allocator,
+                           CodeCompletionTUInfo &CCTUInfo,
+                           const CodeCompletionContext &CompletionContext,
+                           LookupFilter Filter = 0)
+      : SemaRef(SemaRef), Allocator(Allocator), CCTUInfo(CCTUInfo),
+        Filter(Filter), 
+        AllowNestedNameSpecifiers(false), HasObjectTypeQualifiers(false), 
+        CompletionContext(CompletionContext),
+        ObjCImplementation(0) 
+    { 
+      // If this is an Objective-C instance method definition, dig out the 
+      // corresponding implementation.
+      switch (CompletionContext.getKind()) {
+      case CodeCompletionContext::CCC_Expression:
+      case CodeCompletionContext::CCC_ObjCMessageReceiver:
+      case CodeCompletionContext::CCC_ParenthesizedExpression:
+      case CodeCompletionContext::CCC_Statement:
+      case CodeCompletionContext::CCC_Recovery:
+        if (ObjCMethodDecl *Method = SemaRef.getCurMethodDecl())
+          if (Method->isInstanceMethod())
+            if (ObjCInterfaceDecl *Interface = Method->getClassInterface())
+              ObjCImplementation = Interface->getImplementation();
+        break;
+          
+      default:
+        break;
+      }
+    }
+    
+    /// \brief Whether we should include code patterns in the completion
+    /// results.
+    bool includeCodePatterns() const {
+      return SemaRef.CodeCompleter && 
+             SemaRef.CodeCompleter->includeCodePatterns();
+    }
+    
+    /// \brief Set the filter used for code-completion results.
+    void setFilter(LookupFilter Filter) {
+      this->Filter = Filter;
+    }
+    
+    Result *data() { return Results.empty()? 0 : &Results.front(); }
+    unsigned size() const { return Results.size(); }
+    bool empty() const { return Results.empty(); }
+    
+    /// \brief Specify the preferred type.
+    void setPreferredType(QualType T) { 
+      PreferredType = SemaRef.Context.getCanonicalType(T); 
+    }
+    
+    /// \brief Set the cv-qualifiers on the object type, for us in filtering
+    /// calls to member functions.
+    ///
+    /// When there are qualifiers in this set, they will be used to filter
+    /// out member functions that aren't available (because there will be a 
+    /// cv-qualifier mismatch) or prefer functions with an exact qualifier
+    /// match.
+    void setObjectTypeQualifiers(Qualifiers Quals) {
+      ObjectTypeQualifiers = Quals;
+      HasObjectTypeQualifiers = true;
+    }
+    
+    /// \brief Set the preferred selector.
+    ///
+    /// When an Objective-C method declaration result is added, and that
+    /// method's selector matches this preferred selector, we give that method
+    /// a slight priority boost.
+    void setPreferredSelector(Selector Sel) {
+      PreferredSelector = Sel;
+    }
+        
+    /// \brief Retrieve the code-completion context for which results are
+    /// being collected.
+    const CodeCompletionContext &getCompletionContext() const { 
+      return CompletionContext; 
+    }
+    
+    /// \brief Specify whether nested-name-specifiers are allowed.
+    void allowNestedNameSpecifiers(bool Allow = true) {
+      AllowNestedNameSpecifiers = Allow;
+    }
+
+    /// \brief Return the semantic analysis object for which we are collecting
+    /// code completion results.
+    Sema &getSema() const { return SemaRef; }
+    
+    /// \brief Retrieve the allocator used to allocate code completion strings.
+    CodeCompletionAllocator &getAllocator() const { return Allocator; }
+
+    CodeCompletionTUInfo &getCodeCompletionTUInfo() const { return CCTUInfo; }
+    
+    /// \brief Determine whether the given declaration is at all interesting
+    /// as a code-completion result.
+    ///
+    /// \param ND the declaration that we are inspecting.
+    ///
+    /// \param AsNestedNameSpecifier will be set true if this declaration is
+    /// only interesting when it is a nested-name-specifier.
+    bool isInterestingDecl(NamedDecl *ND, bool &AsNestedNameSpecifier) const;
+    
+    /// \brief Check whether the result is hidden by the Hiding declaration.
+    ///
+    /// \returns true if the result is hidden and cannot be found, false if
+    /// the hidden result could still be found. When false, \p R may be
+    /// modified to describe how the result can be found (e.g., via extra
+    /// qualification).
+    bool CheckHiddenResult(Result &R, DeclContext *CurContext,
+                           NamedDecl *Hiding);
+    
+    /// \brief Add a new result to this result set (if it isn't already in one
+    /// of the shadow maps), or replace an existing result (for, e.g., a 
+    /// redeclaration).
+    ///
+    /// \param R the result to add (if it is unique).
+    ///
+    /// \param CurContext the context in which this result will be named.
+    void MaybeAddResult(Result R, DeclContext *CurContext = 0);
+    
+    /// \brief Add a new result to this result set, where we already know
+    /// the hiding declation (if any).
+    ///
+    /// \param R the result to add (if it is unique).
+    ///
+    /// \param CurContext the context in which this result will be named.
+    ///
+    /// \param Hiding the declaration that hides the result.
+    ///
+    /// \param InBaseClass whether the result was found in a base
+    /// class of the searched context.
+    void AddResult(Result R, DeclContext *CurContext, NamedDecl *Hiding,
+                   bool InBaseClass);
+    
+    /// \brief Add a new non-declaration result to this result set.
+    void AddResult(Result R);
+
+    /// \brief Enter into a new scope.
+    void EnterNewScope();
+    
+    /// \brief Exit from the current scope.
+    void ExitScope();
+    
+    /// \brief Ignore this declaration, if it is seen again.
+    void Ignore(Decl *D) { AllDeclsFound.insert(D->getCanonicalDecl()); }
+
+    /// \name Name lookup predicates
+    ///
+    /// These predicates can be passed to the name lookup functions to filter the
+    /// results of name lookup. All of the predicates have the same type, so that
+    /// 
+    //@{
+    bool IsOrdinaryName(NamedDecl *ND) const;
+    bool IsOrdinaryNonTypeName(NamedDecl *ND) const;
+    bool IsIntegralConstantValue(NamedDecl *ND) const;
+    bool IsOrdinaryNonValueName(NamedDecl *ND) const;
+    bool IsNestedNameSpecifier(NamedDecl *ND) const;
+    bool IsEnum(NamedDecl *ND) const;
+    bool IsClassOrStruct(NamedDecl *ND) const;
+    bool IsUnion(NamedDecl *ND) const;
+    bool IsNamespace(NamedDecl *ND) const;
+    bool IsNamespaceOrAlias(NamedDecl *ND) const;
+    bool IsType(NamedDecl *ND) const;
+    bool IsMember(NamedDecl *ND) const;
+    bool IsObjCIvar(NamedDecl *ND) const;
+    bool IsObjCMessageReceiver(NamedDecl *ND) const;
+    bool IsObjCMessageReceiverOrLambdaCapture(NamedDecl *ND) const;
+    bool IsObjCCollection(NamedDecl *ND) const;
+    bool IsImpossibleToSatisfy(NamedDecl *ND) const;
+    //@}    
+  };  
+}
+
+class ResultBuilder::ShadowMapEntry::iterator {
+  llvm::PointerUnion<NamedDecl*, const DeclIndexPair*> DeclOrIterator;
+  unsigned SingleDeclIndex;
+
+public:
+  typedef DeclIndexPair value_type;
+  typedef value_type reference;
+  typedef std::ptrdiff_t difference_type;
+  typedef std::input_iterator_tag iterator_category;
+        
+  class pointer {
+    DeclIndexPair Value;
+
+  public:
+    pointer(const DeclIndexPair &Value) : Value(Value) { }
+
+    const DeclIndexPair *operator->() const {
+      return &Value;
+    }
+  };
+        
+  iterator() : DeclOrIterator((NamedDecl *)0), SingleDeclIndex(0) { }
+
+  iterator(NamedDecl *SingleDecl, unsigned Index)
+    : DeclOrIterator(SingleDecl), SingleDeclIndex(Index) { }
+
+  iterator(const DeclIndexPair *Iterator)
+    : DeclOrIterator(Iterator), SingleDeclIndex(0) { }
+
+  iterator &operator++() {
+    if (DeclOrIterator.is<NamedDecl *>()) {
+      DeclOrIterator = (NamedDecl *)0;
+      SingleDeclIndex = 0;
+      return *this;
+    }
+
+    const DeclIndexPair *I = DeclOrIterator.get<const DeclIndexPair*>();
+    ++I;
+    DeclOrIterator = I;
+    return *this;
+  }
+
+  /*iterator operator++(int) {
+    iterator tmp(*this);
+    ++(*this);
+    return tmp;
+  }*/
+
+  reference operator*() const {
+    if (NamedDecl *ND = DeclOrIterator.dyn_cast<NamedDecl *>())
+      return reference(ND, SingleDeclIndex);
+
+    return *DeclOrIterator.get<const DeclIndexPair*>();
+  }
+
+  pointer operator->() const {
+    return pointer(**this);
+  }
+
+  friend bool operator==(const iterator &X, const iterator &Y) {
+    return X.DeclOrIterator.getOpaqueValue()
+                                  == Y.DeclOrIterator.getOpaqueValue() &&
+      X.SingleDeclIndex == Y.SingleDeclIndex;
+  }
+
+  friend bool operator!=(const iterator &X, const iterator &Y) {
+    return !(X == Y);
+  }
+};
+
+ResultBuilder::ShadowMapEntry::iterator 
+ResultBuilder::ShadowMapEntry::begin() const {
+  if (DeclOrVector.isNull())
+    return iterator();
+
+  if (NamedDecl *ND = DeclOrVector.dyn_cast<NamedDecl *>())
+    return iterator(ND, SingleDeclIndex);
+
+  return iterator(DeclOrVector.get<DeclIndexPairVector *>()->begin());
+}
+
+ResultBuilder::ShadowMapEntry::iterator 
+ResultBuilder::ShadowMapEntry::end() const {
+  if (DeclOrVector.is<NamedDecl *>() || DeclOrVector.isNull())
+    return iterator();
+
+  return iterator(DeclOrVector.get<DeclIndexPairVector *>()->end());
+}
+
+/// \brief Compute the qualification required to get from the current context
+/// (\p CurContext) to the target context (\p TargetContext).
+///
+/// \param Context the AST context in which the qualification will be used.
+///
+/// \param CurContext the context where an entity is being named, which is
+/// typically based on the current scope.
+///
+/// \param TargetContext the context in which the named entity actually 
+/// resides.
+///
+/// \returns a nested name specifier that refers into the target context, or
+/// NULL if no qualification is needed.
+static NestedNameSpecifier *
+getRequiredQualification(ASTContext &Context,
+                         DeclContext *CurContext,
+                         DeclContext *TargetContext) {
+  SmallVector<DeclContext *, 4> TargetParents;
+  
+  for (DeclContext *CommonAncestor = TargetContext;
+       CommonAncestor && !CommonAncestor->Encloses(CurContext);
+       CommonAncestor = CommonAncestor->getLookupParent()) {
+    if (CommonAncestor->isTransparentContext() ||
+        CommonAncestor->isFunctionOrMethod())
+      continue;
+    
+    TargetParents.push_back(CommonAncestor);
+  }
+  
+  NestedNameSpecifier *Result = 0;
+  while (!TargetParents.empty()) {
+    DeclContext *Parent = TargetParents.back();
+    TargetParents.pop_back();
+    
+    if (NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(Parent)) {
+      if (!Namespace->getIdentifier())
+        continue;
+
+      Result = NestedNameSpecifier::Create(Context, Result, Namespace);
+    }
+    else if (TagDecl *TD = dyn_cast<TagDecl>(Parent))
+      Result = NestedNameSpecifier::Create(Context, Result,
+                                           false,
+                                     Context.getTypeDeclType(TD).getTypePtr());
+  }  
+  return Result;
+}
+
+bool ResultBuilder::isInterestingDecl(NamedDecl *ND, 
+                                      bool &AsNestedNameSpecifier) const {
+  AsNestedNameSpecifier = false;
+
+  ND = ND->getUnderlyingDecl();
+  unsigned IDNS = ND->getIdentifierNamespace();
+
+  // Skip unnamed entities.
+  if (!ND->getDeclName())
+    return false;
+  
+  // Friend declarations and declarations introduced due to friends are never
+  // added as results.
+  if (IDNS & (Decl::IDNS_OrdinaryFriend | Decl::IDNS_TagFriend))
+    return false;
+  
+  // Class template (partial) specializations are never added as results.
+  if (isa<ClassTemplateSpecializationDecl>(ND) ||
+      isa<ClassTemplatePartialSpecializationDecl>(ND))
+    return false;
+  
+  // Using declarations themselves are never added as results.
+  if (isa<UsingDecl>(ND))
+    return false;
+  
+  // Some declarations have reserved names that we don't want to ever show.
+  if (const IdentifierInfo *Id = ND->getIdentifier()) {
+    // __va_list_tag is a freak of nature. Find it and skip it.
+    if (Id->isStr("__va_list_tag") || Id->isStr("__builtin_va_list"))
+      return false;
+    
+    // Filter out names reserved for the implementation (C99 7.1.3, 
+    // C++ [lib.global.names]) if they come from a system header.
+    //
+    // FIXME: Add predicate for this.
+    if (Id->getLength() >= 2) {
+      const char *Name = Id->getNameStart();
+      if (Name[0] == '_' &&
+          (Name[1] == '_' || (Name[1] >= 'A' && Name[1] <= 'Z')) &&
+          (ND->getLocation().isInvalid() ||
+           SemaRef.SourceMgr.isInSystemHeader(
+                          SemaRef.SourceMgr.getSpellingLoc(ND->getLocation()))))
+        return false;
+    }
+  }
+
+  if (Filter == &ResultBuilder::IsNestedNameSpecifier ||
+      ((isa<NamespaceDecl>(ND) || isa<NamespaceAliasDecl>(ND)) &&
+       Filter != &ResultBuilder::IsNamespace &&
+       Filter != &ResultBuilder::IsNamespaceOrAlias &&
+       Filter != 0))
+    AsNestedNameSpecifier = true;
+
+  // Filter out any unwanted results.
+  if (Filter && !(this->*Filter)(ND)) {
+    // Check whether it is interesting as a nested-name-specifier.
+    if (AllowNestedNameSpecifiers && SemaRef.getLangOpts().CPlusPlus && 
+        IsNestedNameSpecifier(ND) &&
+        (Filter != &ResultBuilder::IsMember ||
+         (isa<CXXRecordDecl>(ND) && 
+          cast<CXXRecordDecl>(ND)->isInjectedClassName()))) {
+      AsNestedNameSpecifier = true;
+      return true;
+    }
+
+    return false;
+  }  
+  // ... then it must be interesting!
+  return true;
+}
+
+bool ResultBuilder::CheckHiddenResult(Result &R, DeclContext *CurContext,
+                                      NamedDecl *Hiding) {
+  // In C, there is no way to refer to a hidden name.
+  // FIXME: This isn't true; we can find a tag name hidden by an ordinary
+  // name if we introduce the tag type.
+  if (!SemaRef.getLangOpts().CPlusPlus)
+    return true;
+  
+  DeclContext *HiddenCtx = R.Declaration->getDeclContext()->getRedeclContext();
+  
+  // There is no way to qualify a name declared in a function or method.
+  if (HiddenCtx->isFunctionOrMethod())
+    return true;
+  
+  if (HiddenCtx == Hiding->getDeclContext()->getRedeclContext())
+    return true;
+  
+  // We can refer to the result with the appropriate qualification. Do it.
+  R.Hidden = true;
+  R.QualifierIsInformative = false;
+  
+  if (!R.Qualifier)
+    R.Qualifier = getRequiredQualification(SemaRef.Context, 
+                                           CurContext, 
+                                           R.Declaration->getDeclContext());
+  return false;
+}
+
+/// \brief A simplified classification of types used to determine whether two
+/// types are "similar enough" when adjusting priorities.
+SimplifiedTypeClass clang::getSimplifiedTypeClass(CanQualType T) {
+  switch (T->getTypeClass()) {
+  case Type::Builtin:
+    switch (cast<BuiltinType>(T)->getKind()) {
+      case BuiltinType::Void:
+        return STC_Void;
+        
+      case BuiltinType::NullPtr:
+        return STC_Pointer;
+        
+      case BuiltinType::Overload:
+      case BuiltinType::Dependent:
+        return STC_Other;
+        
+      case BuiltinType::ObjCId:
+      case BuiltinType::ObjCClass:
+      case BuiltinType::ObjCSel:
+        return STC_ObjectiveC;
+        
+      default:
+        return STC_Arithmetic;
+    }
+
+  case Type::Complex:
+    return STC_Arithmetic;
+    
+  case Type::Pointer:
+    return STC_Pointer;
+    
+  case Type::BlockPointer:
+    return STC_Block;
+    
+  case Type::LValueReference:
+  case Type::RValueReference:
+    return getSimplifiedTypeClass(T->getAs<ReferenceType>()->getPointeeType());
+    
+  case Type::ConstantArray:
+  case Type::IncompleteArray:
+  case Type::VariableArray:
+  case Type::DependentSizedArray:
+    return STC_Array;
+    
+  case Type::DependentSizedExtVector:
+  case Type::Vector:
+  case Type::ExtVector:
+    return STC_Arithmetic;
+    
+  case Type::FunctionProto:
+  case Type::FunctionNoProto:
+    return STC_Function;
+    
+  case Type::Record:
+    return STC_Record;
+    
+  case Type::Enum:
+    return STC_Arithmetic;
+    
+  case Type::ObjCObject:
+  case Type::ObjCInterface:
+  case Type::ObjCObjectPointer:
+    return STC_ObjectiveC;
+    
+  default:
+    return STC_Other;
+  }
+}
+
+/// \brief Get the type that a given expression will have if this declaration
+/// is used as an expression in its "typical" code-completion form.
+QualType clang::getDeclUsageType(ASTContext &C, NamedDecl *ND) {
+  ND = cast<NamedDecl>(ND->getUnderlyingDecl());
+  
+  if (TypeDecl *Type = dyn_cast<TypeDecl>(ND))
+    return C.getTypeDeclType(Type);
+  if (ObjCInterfaceDecl *Iface = dyn_cast<ObjCInterfaceDecl>(ND))
+    return C.getObjCInterfaceType(Iface);
+  
+  QualType T;
+  if (FunctionDecl *Function = dyn_cast<FunctionDecl>(ND))
+    T = Function->getCallResultType();
+  else if (ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(ND))
+    T = Method->getSendResultType();
+  else if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(ND))
+    T = FunTmpl->getTemplatedDecl()->getCallResultType();
+  else if (EnumConstantDecl *Enumerator = dyn_cast<EnumConstantDecl>(ND))
+    T = C.getTypeDeclType(cast<EnumDecl>(Enumerator->getDeclContext()));
+  else if (ObjCPropertyDecl *Property = dyn_cast<ObjCPropertyDecl>(ND))
+    T = Property->getType();
+  else if (ValueDecl *Value = dyn_cast<ValueDecl>(ND))
+    T = Value->getType();
+  else
+    return QualType();
+
+  // Dig through references, function pointers, and block pointers to
+  // get down to the likely type of an expression when the entity is
+  // used.
+  do {
+    if (const ReferenceType *Ref = T->getAs<ReferenceType>()) {
+      T = Ref->getPointeeType();
+      continue;
+    }
+
+    if (const PointerType *Pointer = T->getAs<PointerType>()) {
+      if (Pointer->getPointeeType()->isFunctionType()) {
+        T = Pointer->getPointeeType();
+        continue;
+      }
+
+      break;
+    }
+
+    if (const BlockPointerType *Block = T->getAs<BlockPointerType>()) {
+      T = Block->getPointeeType();
+      continue;
+    }
+
+    if (const FunctionType *Function = T->getAs<FunctionType>()) {
+      T = Function->getResultType();
+      continue;
+    }
+
+    break;
+  } while (true);
+    
+  return T;
+}
+
+void ResultBuilder::AdjustResultPriorityForDecl(Result &R) {
+  // If this is an Objective-C method declaration whose selector matches our
+  // preferred selector, give it a priority boost.
+  if (!PreferredSelector.isNull())
+    if (ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(R.Declaration))
+      if (PreferredSelector == Method->getSelector())
+        R.Priority += CCD_SelectorMatch;
+  
+  // If we have a preferred type, adjust the priority for results with exactly-
+  // matching or nearly-matching types.
+  if (!PreferredType.isNull()) {
+    QualType T = getDeclUsageType(SemaRef.Context, R.Declaration);
+    if (!T.isNull()) {
+      CanQualType TC = SemaRef.Context.getCanonicalType(T);
+      // Check for exactly-matching types (modulo qualifiers).
+      if (SemaRef.Context.hasSameUnqualifiedType(PreferredType, TC))
+        R.Priority /= CCF_ExactTypeMatch;
+      // Check for nearly-matching types, based on classification of each.
+      else if ((getSimplifiedTypeClass(PreferredType)
+                                               == getSimplifiedTypeClass(TC)) &&
+               !(PreferredType->isEnumeralType() && TC->isEnumeralType()))
+        R.Priority /= CCF_SimilarTypeMatch;  
+    }
+  }  
+}
+
+void ResultBuilder::MaybeAddConstructorResults(Result R) {
+  if (!SemaRef.getLangOpts().CPlusPlus || !R.Declaration ||
+      !CompletionContext.wantConstructorResults())
+    return;
+  
+  ASTContext &Context = SemaRef.Context;
+  NamedDecl *D = R.Declaration;
+  CXXRecordDecl *Record = 0;
+  if (ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(D))
+    Record = ClassTemplate->getTemplatedDecl();
+  else if ((Record = dyn_cast<CXXRecordDecl>(D))) {
+    // Skip specializations and partial specializations.
+    if (isa<ClassTemplateSpecializationDecl>(Record))
+      return;
+  } else {
+    // There are no constructors here.
+    return;
+  }
+  
+  Record = Record->getDefinition();
+  if (!Record)
+    return;
+
+  
+  QualType RecordTy = Context.getTypeDeclType(Record);
+  DeclarationName ConstructorName
+    = Context.DeclarationNames.getCXXConstructorName(
+                                           Context.getCanonicalType(RecordTy));
+  for (DeclContext::lookup_result Ctors = Record->lookup(ConstructorName);
+       Ctors.first != Ctors.second; ++Ctors.first) {
+    R.Declaration = *Ctors.first;
+    R.CursorKind = getCursorKindForDecl(R.Declaration);
+    Results.push_back(R);
+  }
+}
+
+void ResultBuilder::MaybeAddResult(Result R, DeclContext *CurContext) {
+  assert(!ShadowMaps.empty() && "Must enter into a results scope");
+  
+  if (R.Kind != Result::RK_Declaration) {
+    // For non-declaration results, just add the result.
+    Results.push_back(R);
+    return;
+  }
+
+  // Look through using declarations.
+  if (UsingShadowDecl *Using = dyn_cast<UsingShadowDecl>(R.Declaration)) {
+    MaybeAddResult(Result(Using->getTargetDecl(), R.Qualifier), CurContext);
+    return;
+  }
+  
+  Decl *CanonDecl = R.Declaration->getCanonicalDecl();
+  unsigned IDNS = CanonDecl->getIdentifierNamespace();
+
+  bool AsNestedNameSpecifier = false;
+  if (!isInterestingDecl(R.Declaration, AsNestedNameSpecifier))
+    return;
+      
+  // C++ constructors are never found by name lookup.
+  if (isa<CXXConstructorDecl>(R.Declaration))
+    return;
+
+  ShadowMap &SMap = ShadowMaps.back();
+  ShadowMapEntry::iterator I, IEnd;
+  ShadowMap::iterator NamePos = SMap.find(R.Declaration->getDeclName());
+  if (NamePos != SMap.end()) {
+    I = NamePos->second.begin();
+    IEnd = NamePos->second.end();
+  }
+
+  for (; I != IEnd; ++I) {
+    NamedDecl *ND = I->first;
+    unsigned Index = I->second;
+    if (ND->getCanonicalDecl() == CanonDecl) {
+      // This is a redeclaration. Always pick the newer declaration.
+      Results[Index].Declaration = R.Declaration;
+      
+      // We're done.
+      return;
+    }
+  }
+  
+  // This is a new declaration in this scope. However, check whether this
+  // declaration name is hidden by a similarly-named declaration in an outer
+  // scope.
+  std::list<ShadowMap>::iterator SM, SMEnd = ShadowMaps.end();
+  --SMEnd;
+  for (SM = ShadowMaps.begin(); SM != SMEnd; ++SM) {
+    ShadowMapEntry::iterator I, IEnd;
+    ShadowMap::iterator NamePos = SM->find(R.Declaration->getDeclName());
+    if (NamePos != SM->end()) {
+      I = NamePos->second.begin();
+      IEnd = NamePos->second.end();
+    }
+    for (; I != IEnd; ++I) {
+      // A tag declaration does not hide a non-tag declaration.
+      if (I->first->hasTagIdentifierNamespace() &&
+          (IDNS & (Decl::IDNS_Member | Decl::IDNS_Ordinary | 
+                   Decl::IDNS_ObjCProtocol)))
+        continue;
+      
+      // Protocols are in distinct namespaces from everything else.
+      if (((I->first->getIdentifierNamespace() & Decl::IDNS_ObjCProtocol)
+           || (IDNS & Decl::IDNS_ObjCProtocol)) &&
+          I->first->getIdentifierNamespace() != IDNS)
+        continue;
+      
+      // The newly-added result is hidden by an entry in the shadow map.
+      if (CheckHiddenResult(R, CurContext, I->first))
+        return;
+      
+      break;
+    }
+  }
+  
+  // Make sure that any given declaration only shows up in the result set once.
+  if (!AllDeclsFound.insert(CanonDecl))
+    return;
+
+  // If the filter is for nested-name-specifiers, then this result starts a
+  // nested-name-specifier.
+  if (AsNestedNameSpecifier) {
+    R.StartsNestedNameSpecifier = true;
+    R.Priority = CCP_NestedNameSpecifier;
+  } else 
+      AdjustResultPriorityForDecl(R);
+      
+  // If this result is supposed to have an informative qualifier, add one.
+  if (R.QualifierIsInformative && !R.Qualifier &&
+      !R.StartsNestedNameSpecifier) {
+    DeclContext *Ctx = R.Declaration->getDeclContext();
+    if (NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(Ctx))
+      R.Qualifier = NestedNameSpecifier::Create(SemaRef.Context, 0, Namespace);
+    else if (TagDecl *Tag = dyn_cast<TagDecl>(Ctx))
+      R.Qualifier = NestedNameSpecifier::Create(SemaRef.Context, 0, false, 
+                             SemaRef.Context.getTypeDeclType(Tag).getTypePtr());
+    else
+      R.QualifierIsInformative = false;
+  }
+    
+  // Insert this result into the set of results and into the current shadow
+  // map.
+  SMap[R.Declaration->getDeclName()].Add(R.Declaration, Results.size());
+  Results.push_back(R);
+  
+  if (!AsNestedNameSpecifier)
+    MaybeAddConstructorResults(R);
+}
+
+void ResultBuilder::AddResult(Result R, DeclContext *CurContext, 
+                              NamedDecl *Hiding, bool InBaseClass = false) {
+  if (R.Kind != Result::RK_Declaration) {
+    // For non-declaration results, just add the result.
+    Results.push_back(R);
+    return;
+  }
+
+  // Look through using declarations.
+  if (UsingShadowDecl *Using = dyn_cast<UsingShadowDecl>(R.Declaration)) {
+    AddResult(Result(Using->getTargetDecl(), R.Qualifier), CurContext, Hiding);
+    return;
+  }
+  
+  bool AsNestedNameSpecifier = false;
+  if (!isInterestingDecl(R.Declaration, AsNestedNameSpecifier))
+    return;
+  
+  // C++ constructors are never found by name lookup.
+  if (isa<CXXConstructorDecl>(R.Declaration))
+    return;
+
+  if (Hiding && CheckHiddenResult(R, CurContext, Hiding))
+    return;
+
+  // Make sure that any given declaration only shows up in the result set once.
+  if (!AllDeclsFound.insert(R.Declaration->getCanonicalDecl()))
+    return;
+  
+  // If the filter is for nested-name-specifiers, then this result starts a
+  // nested-name-specifier.
+  if (AsNestedNameSpecifier) {
+    R.StartsNestedNameSpecifier = true;
+    R.Priority = CCP_NestedNameSpecifier;
+  }
+  else if (Filter == &ResultBuilder::IsMember && !R.Qualifier && InBaseClass &&
+           isa<CXXRecordDecl>(R.Declaration->getDeclContext()
+                                                  ->getRedeclContext()))
+    R.QualifierIsInformative = true;
+
+  // If this result is supposed to have an informative qualifier, add one.
+  if (R.QualifierIsInformative && !R.Qualifier &&
+      !R.StartsNestedNameSpecifier) {
+    DeclContext *Ctx = R.Declaration->getDeclContext();
+    if (NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(Ctx))
+      R.Qualifier = NestedNameSpecifier::Create(SemaRef.Context, 0, Namespace);
+    else if (TagDecl *Tag = dyn_cast<TagDecl>(Ctx))
+      R.Qualifier = NestedNameSpecifier::Create(SemaRef.Context, 0, false, 
+                            SemaRef.Context.getTypeDeclType(Tag).getTypePtr());
+    else
+      R.QualifierIsInformative = false;
+  }
+  
+  // Adjust the priority if this result comes from a base class.
+  if (InBaseClass)
+    R.Priority += CCD_InBaseClass;
+  
+  AdjustResultPriorityForDecl(R);
+  
+  if (HasObjectTypeQualifiers)
+    if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(R.Declaration))
+      if (Method->isInstance()) {
+        Qualifiers MethodQuals
+                        = Qualifiers::fromCVRMask(Method->getTypeQualifiers());
+        if (ObjectTypeQualifiers == MethodQuals)
+          R.Priority += CCD_ObjectQualifierMatch;
+        else if (ObjectTypeQualifiers - MethodQuals) {
+          // The method cannot be invoked, because doing so would drop 
+          // qualifiers.
+          return;
+        }
+      }
+  
+  // Insert this result into the set of results.
+  Results.push_back(R);
+  
+  if (!AsNestedNameSpecifier)
+    MaybeAddConstructorResults(R);
+}
+
+void ResultBuilder::AddResult(Result R) {
+  assert(R.Kind != Result::RK_Declaration && 
+          "Declaration results need more context");
+  Results.push_back(R);
+}
+
+/// \brief Enter into a new scope.
+void ResultBuilder::EnterNewScope() {
+  ShadowMaps.push_back(ShadowMap());
+}
+
+/// \brief Exit from the current scope.
+void ResultBuilder::ExitScope() {
+  for (ShadowMap::iterator E = ShadowMaps.back().begin(),
+                        EEnd = ShadowMaps.back().end();
+       E != EEnd;
+       ++E)
+    E->second.Destroy();
+         
+  ShadowMaps.pop_back();
+}
+
+/// \brief Determines whether this given declaration will be found by
+/// ordinary name lookup.
+bool ResultBuilder::IsOrdinaryName(NamedDecl *ND) const {
+  ND = cast<NamedDecl>(ND->getUnderlyingDecl());
+
+  unsigned IDNS = Decl::IDNS_Ordinary;
+  if (SemaRef.getLangOpts().CPlusPlus)
+    IDNS |= Decl::IDNS_Tag | Decl::IDNS_Namespace | Decl::IDNS_Member;
+  else if (SemaRef.getLangOpts().ObjC1) {
+    if (isa<ObjCIvarDecl>(ND))
+      return true;
+  }
+  
+  return ND->getIdentifierNamespace() & IDNS;
+}
+
+/// \brief Determines whether this given declaration will be found by
+/// ordinary name lookup but is not a type name.
+bool ResultBuilder::IsOrdinaryNonTypeName(NamedDecl *ND) const {
+  ND = cast<NamedDecl>(ND->getUnderlyingDecl());
+  if (isa<TypeDecl>(ND) || isa<ObjCInterfaceDecl>(ND))
+    return false;
+  
+  unsigned IDNS = Decl::IDNS_Ordinary;
+  if (SemaRef.getLangOpts().CPlusPlus)
+    IDNS |= Decl::IDNS_Tag | Decl::IDNS_Namespace | Decl::IDNS_Member;
+  else if (SemaRef.getLangOpts().ObjC1) {
+    if (isa<ObjCIvarDecl>(ND))
+      return true;
+  }
+ 
+  return ND->getIdentifierNamespace() & IDNS;
+}
+
+bool ResultBuilder::IsIntegralConstantValue(NamedDecl *ND) const {
+  if (!IsOrdinaryNonTypeName(ND))
+    return 0;
+  
+  if (ValueDecl *VD = dyn_cast<ValueDecl>(ND->getUnderlyingDecl()))
+    if (VD->getType()->isIntegralOrEnumerationType())
+      return true;
+        
+  return false;
+}
+
+/// \brief Determines whether this given declaration will be found by
+/// ordinary name lookup.
+bool ResultBuilder::IsOrdinaryNonValueName(NamedDecl *ND) const {
+  ND = cast<NamedDecl>(ND->getUnderlyingDecl());
+
+  unsigned IDNS = Decl::IDNS_Ordinary;
+  if (SemaRef.getLangOpts().CPlusPlus)
+    IDNS |= Decl::IDNS_Tag | Decl::IDNS_Namespace;
+  
+  return (ND->getIdentifierNamespace() & IDNS) && 
+    !isa<ValueDecl>(ND) && !isa<FunctionTemplateDecl>(ND) && 
+    !isa<ObjCPropertyDecl>(ND);
+}
+
+/// \brief Determines whether the given declaration is suitable as the 
+/// start of a C++ nested-name-specifier, e.g., a class or namespace.
+bool ResultBuilder::IsNestedNameSpecifier(NamedDecl *ND) const {
+  // Allow us to find class templates, too.
+  if (ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(ND))
+    ND = ClassTemplate->getTemplatedDecl();
+  
+  return SemaRef.isAcceptableNestedNameSpecifier(ND);
+}
+
+/// \brief Determines whether the given declaration is an enumeration.
+bool ResultBuilder::IsEnum(NamedDecl *ND) const {
+  return isa<EnumDecl>(ND);
+}
+
+/// \brief Determines whether the given declaration is a class or struct.
+bool ResultBuilder::IsClassOrStruct(NamedDecl *ND) const {
+  // Allow us to find class templates, too.
+  if (ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(ND))
+    ND = ClassTemplate->getTemplatedDecl();
+  
+  if (RecordDecl *RD = dyn_cast<RecordDecl>(ND))
+    return RD->getTagKind() == TTK_Class ||
+    RD->getTagKind() == TTK_Struct;
+  
+  return false;
+}
+
+/// \brief Determines whether the given declaration is a union.
+bool ResultBuilder::IsUnion(NamedDecl *ND) const {
+  // Allow us to find class templates, too.
+  if (ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(ND))
+    ND = ClassTemplate->getTemplatedDecl();
+  
+  if (RecordDecl *RD = dyn_cast<RecordDecl>(ND))
+    return RD->getTagKind() == TTK_Union;
+  
+  return false;
+}
+
+/// \brief Determines whether the given declaration is a namespace.
+bool ResultBuilder::IsNamespace(NamedDecl *ND) const {
+  return isa<NamespaceDecl>(ND);
+}
+
+/// \brief Determines whether the given declaration is a namespace or 
+/// namespace alias.
+bool ResultBuilder::IsNamespaceOrAlias(NamedDecl *ND) const {
+  return isa<NamespaceDecl>(ND) || isa<NamespaceAliasDecl>(ND);
+}
+
+/// \brief Determines whether the given declaration is a type.
+bool ResultBuilder::IsType(NamedDecl *ND) const {
+  if (UsingShadowDecl *Using = dyn_cast<UsingShadowDecl>(ND))
+    ND = Using->getTargetDecl();
+  
+  return isa<TypeDecl>(ND) || isa<ObjCInterfaceDecl>(ND);
+}
+
+/// \brief Determines which members of a class should be visible via
+/// "." or "->".  Only value declarations, nested name specifiers, and
+/// using declarations thereof should show up.
+bool ResultBuilder::IsMember(NamedDecl *ND) const {
+  if (UsingShadowDecl *Using = dyn_cast<UsingShadowDecl>(ND))
+    ND = Using->getTargetDecl();
+
+  return isa<ValueDecl>(ND) || isa<FunctionTemplateDecl>(ND) ||
+    isa<ObjCPropertyDecl>(ND);
+}
+
+static bool isObjCReceiverType(ASTContext &C, QualType T) {
+  T = C.getCanonicalType(T);
+  switch (T->getTypeClass()) {
+  case Type::ObjCObject: 
+  case Type::ObjCInterface:
+  case Type::ObjCObjectPointer:
+    return true;
+      
+  case Type::Builtin:
+    switch (cast<BuiltinType>(T)->getKind()) {
+    case BuiltinType::ObjCId:
+    case BuiltinType::ObjCClass:
+    case BuiltinType::ObjCSel:
+      return true;
+      
+    default:
+      break;
+    }
+    return false;
+      
+  default:
+    break;
+  }
+  
+  if (!C.getLangOpts().CPlusPlus)
+    return false;
+
+  // FIXME: We could perform more analysis here to determine whether a 
+  // particular class type has any conversions to Objective-C types. For now,
+  // just accept all class types.
+  return T->isDependentType() || T->isRecordType();
+}
+
+bool ResultBuilder::IsObjCMessageReceiver(NamedDecl *ND) const {
+  QualType T = getDeclUsageType(SemaRef.Context, ND);
+  if (T.isNull())
+    return false;
+  
+  T = SemaRef.Context.getBaseElementType(T);
+  return isObjCReceiverType(SemaRef.Context, T);
+}
+
+bool ResultBuilder::IsObjCMessageReceiverOrLambdaCapture(NamedDecl *ND) const {
+  if (IsObjCMessageReceiver(ND))
+    return true;
+  
+  VarDecl *Var = dyn_cast<VarDecl>(ND);
+  if (!Var)
+    return false;
+  
+  return Var->hasLocalStorage() && !Var->hasAttr<BlocksAttr>();
+}
+
+bool ResultBuilder::IsObjCCollection(NamedDecl *ND) const {
+  if ((SemaRef.getLangOpts().CPlusPlus && !IsOrdinaryName(ND)) ||
+      (!SemaRef.getLangOpts().CPlusPlus && !IsOrdinaryNonTypeName(ND)))
+    return false;
+  
+  QualType T = getDeclUsageType(SemaRef.Context, ND);
+  if (T.isNull())
+    return false;
+  
+  T = SemaRef.Context.getBaseElementType(T);
+  return T->isObjCObjectType() || T->isObjCObjectPointerType() ||
+         T->isObjCIdType() || 
+         (SemaRef.getLangOpts().CPlusPlus && T->isRecordType());
+}
+
+bool ResultBuilder::IsImpossibleToSatisfy(NamedDecl *ND) const {
+  return false;
+}
+
+/// \rief Determines whether the given declaration is an Objective-C
+/// instance variable.
+bool ResultBuilder::IsObjCIvar(NamedDecl *ND) const {
+  return isa<ObjCIvarDecl>(ND);
+}
+
+namespace {
+  /// \brief Visible declaration consumer that adds a code-completion result
+  /// for each visible declaration.
+  class CodeCompletionDeclConsumer : public VisibleDeclConsumer {
+    ResultBuilder &Results;
+    DeclContext *CurContext;
+    
+  public:
+    CodeCompletionDeclConsumer(ResultBuilder &Results, DeclContext *CurContext)
+      : Results(Results), CurContext(CurContext) { }
+    
+    virtual void FoundDecl(NamedDecl *ND, NamedDecl *Hiding, DeclContext *Ctx,
+                           bool InBaseClass) {
+      bool Accessible = true;
+      if (Ctx)
+        Accessible = Results.getSema().IsSimplyAccessible(ND, Ctx);
+      
+      ResultBuilder::Result Result(ND, 0, false, Accessible);
+      Results.AddResult(Result, CurContext, Hiding, InBaseClass);
+    }
+  };
+}
+
+/// \brief Add type specifiers for the current language as keyword results.
+static void AddTypeSpecifierResults(const LangOptions &LangOpts,
+                                    ResultBuilder &Results) {
+  typedef CodeCompletionResult Result;
+  Results.AddResult(Result("short", CCP_Type));
+  Results.AddResult(Result("long", CCP_Type));
+  Results.AddResult(Result("signed", CCP_Type));
+  Results.AddResult(Result("unsigned", CCP_Type));
+  Results.AddResult(Result("void", CCP_Type));
+  Results.AddResult(Result("char", CCP_Type));
+  Results.AddResult(Result("int", CCP_Type));
+  Results.AddResult(Result("float", CCP_Type));
+  Results.AddResult(Result("double", CCP_Type));
+  Results.AddResult(Result("enum", CCP_Type));
+  Results.AddResult(Result("struct", CCP_Type));
+  Results.AddResult(Result("union", CCP_Type));
+  Results.AddResult(Result("const", CCP_Type));
+  Results.AddResult(Result("volatile", CCP_Type));
+
+  if (LangOpts.C99) {
+    // C99-specific
+    Results.AddResult(Result("_Complex", CCP_Type));
+    Results.AddResult(Result("_Imaginary", CCP_Type));
+    Results.AddResult(Result("_Bool", CCP_Type));
+    Results.AddResult(Result("restrict", CCP_Type));
+  }
+  
+  CodeCompletionBuilder Builder(Results.getAllocator(),
+                                Results.getCodeCompletionTUInfo());
+  if (LangOpts.CPlusPlus) {
+    // C++-specific
+    Results.AddResult(Result("bool", CCP_Type + 
+                             (LangOpts.ObjC1? CCD_bool_in_ObjC : 0)));
+    Results.AddResult(Result("class", CCP_Type));
+    Results.AddResult(Result("wchar_t", CCP_Type));
+    
+    // typename qualified-id
+    Builder.AddTypedTextChunk("typename");
+    Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
+    Builder.AddPlaceholderChunk("qualifier");
+    Builder.AddTextChunk("::");
+    Builder.AddPlaceholderChunk("name");
+    Results.AddResult(Result(Builder.TakeString()));
+    
+    if (LangOpts.CPlusPlus0x) {
+      Results.AddResult(Result("auto", CCP_Type));
+      Results.AddResult(Result("char16_t", CCP_Type));
+      Results.AddResult(Result("char32_t", CCP_Type));
+      
+      Builder.AddTypedTextChunk("decltype");
+      Builder.AddChunk(CodeCompletionString::CK_LeftParen);
+      Builder.AddPlaceholderChunk("expression");
+      Builder.AddChunk(CodeCompletionString::CK_RightParen);
+      Results.AddResult(Result(Builder.TakeString()));
+    }
+  }
+  
+  // GNU extensions
+  if (LangOpts.GNUMode) {
+    // FIXME: Enable when we actually support decimal floating point.
+    //    Results.AddResult(Result("_Decimal32"));
+    //    Results.AddResult(Result("_Decimal64"));
+    //    Results.AddResult(Result("_Decimal128"));
+    
+    Builder.AddTypedTextChunk("typeof");
+    Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
+    Builder.AddPlaceholderChunk("expression");
+    Results.AddResult(Result(Builder.TakeString()));
+
+    Builder.AddTypedTextChunk("typeof");
+    Builder.AddChunk(CodeCompletionString::CK_LeftParen);
+    Builder.AddPlaceholderChunk("type");
+    Builder.AddChunk(CodeCompletionString::CK_RightParen);
+    Results.AddResult(Result(Builder.TakeString()));
+  }
+}
+
+static void AddStorageSpecifiers(Sema::ParserCompletionContext CCC,
+                                 const LangOptions &LangOpts, 
+                                 ResultBuilder &Results) {
+  typedef CodeCompletionResult Result;
+  // Note: we don't suggest either "auto" or "register", because both
+  // are pointless as storage specifiers. Elsewhere, we suggest "auto"
+  // in C++0x as a type specifier.
+  Results.AddResult(Result("extern"));
+  Results.AddResult(Result("static"));
+}
+
+static void AddFunctionSpecifiers(Sema::ParserCompletionContext CCC,
+                                  const LangOptions &LangOpts, 
+                                  ResultBuilder &Results) {
+  typedef CodeCompletionResult Result;
+  switch (CCC) {
+  case Sema::PCC_Class:
+  case Sema::PCC_MemberTemplate:
+    if (LangOpts.CPlusPlus) {
+      Results.AddResult(Result("explicit"));
+      Results.AddResult(Result("friend"));
+      Results.AddResult(Result("mutable"));
+      Results.AddResult(Result("virtual"));
+    }    
+    // Fall through
+
+  case Sema::PCC_ObjCInterface:
+  case Sema::PCC_ObjCImplementation:
+  case Sema::PCC_Namespace:
+  case Sema::PCC_Template:
+    if (LangOpts.CPlusPlus || LangOpts.C99)
+      Results.AddResult(Result("inline"));
+    break;
+
+  case Sema::PCC_ObjCInstanceVariableList:
+  case Sema::PCC_Expression:
+  case Sema::PCC_Statement:
+  case Sema::PCC_ForInit:
+  case Sema::PCC_Condition:
+  case Sema::PCC_RecoveryInFunction:
+  case Sema::PCC_Type:
+  case Sema::PCC_ParenthesizedExpression:
+  case Sema::PCC_LocalDeclarationSpecifiers:
+    break;
+  }
+}
+
+static void AddObjCExpressionResults(ResultBuilder &Results, bool NeedAt);
+static void AddObjCStatementResults(ResultBuilder &Results, bool NeedAt);
+static void AddObjCVisibilityResults(const LangOptions &LangOpts,
+                                     ResultBuilder &Results,
+                                     bool NeedAt);  
+static void AddObjCImplementationResults(const LangOptions &LangOpts,
+                                         ResultBuilder &Results,
+                                         bool NeedAt);
+static void AddObjCInterfaceResults(const LangOptions &LangOpts,
+                                    ResultBuilder &Results,
+                                    bool NeedAt);
+static void AddObjCTopLevelResults(ResultBuilder &Results, bool NeedAt);
+
+static void AddTypedefResult(ResultBuilder &Results) {
+  CodeCompletionBuilder Builder(Results.getAllocator(),
+                                Results.getCodeCompletionTUInfo());
+  Builder.AddTypedTextChunk("typedef");
+  Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
+  Builder.AddPlaceholderChunk("type");
+  Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
+  Builder.AddPlaceholderChunk("name");
+  Results.AddResult(CodeCompletionResult(Builder.TakeString()));        
+}
+
+static bool WantTypesInContext(Sema::ParserCompletionContext CCC,
+                               const LangOptions &LangOpts) {
+  switch (CCC) {
+  case Sema::PCC_Namespace:
+  case Sema::PCC_Class:
+  case Sema::PCC_ObjCInstanceVariableList:
+  case Sema::PCC_Template:
+  case Sema::PCC_MemberTemplate:
+  case Sema::PCC_Statement:
+  case Sema::PCC_RecoveryInFunction:
+  case Sema::PCC_Type:
+  case Sema::PCC_ParenthesizedExpression:
+  case Sema::PCC_LocalDeclarationSpecifiers:
+    return true;
+    
+  case Sema::PCC_Expression:
+  case Sema::PCC_Condition:
+    return LangOpts.CPlusPlus;
+      
+  case Sema::PCC_ObjCInterface:
+  case Sema::PCC_ObjCImplementation:
+    return false;
+    
+  case Sema::PCC_ForInit:
+    return LangOpts.CPlusPlus || LangOpts.ObjC1 || LangOpts.C99;
+  }
+
+  llvm_unreachable("Invalid ParserCompletionContext!");
+}
+
+static PrintingPolicy getCompletionPrintingPolicy(const ASTContext &Context,
+                                                  const Preprocessor &PP) {
+  PrintingPolicy Policy = Sema::getPrintingPolicy(Context, PP);
+  Policy.AnonymousTagLocations = false;
+  Policy.SuppressStrongLifetime = true;
+  Policy.SuppressUnwrittenScope = true;
+  return Policy;
+}
+
+/// \brief Retrieve a printing policy suitable for code completion.
+static PrintingPolicy getCompletionPrintingPolicy(Sema &S) {
+  return getCompletionPrintingPolicy(S.Context, S.PP);
+}
+
+/// \brief Retrieve the string representation of the given type as a string
+/// that has the appropriate lifetime for code completion.
+///
+/// This routine provides a fast path where we provide constant strings for
+/// common type names.
+static const char *GetCompletionTypeString(QualType T,
+                                           ASTContext &Context,
+                                           const PrintingPolicy &Policy,
+                                           CodeCompletionAllocator &Allocator) {
+  if (!T.getLocalQualifiers()) {
+    // Built-in type names are constant strings.
+    if (const BuiltinType *BT = dyn_cast<BuiltinType>(T))
+      return BT->getName(Policy);
+    
+    // Anonymous tag types are constant strings.
+    if (const TagType *TagT = dyn_cast<TagType>(T))
+      if (TagDecl *Tag = TagT->getDecl())
+        if (!Tag->getIdentifier() && !Tag->getTypedefNameForAnonDecl()) {
+          switch (Tag->getTagKind()) {
+          case TTK_Struct: return "struct <anonymous>";
+          case TTK_Class:  return "class <anonymous>";            
+          case TTK_Union:  return "union <anonymous>";
+          case TTK_Enum:   return "enum <anonymous>";
+          }
+        }
+  }
+  
+  // Slow path: format the type as a string.
+  std::string Result;
+  T.getAsStringInternal(Result, Policy);
+  return Allocator.CopyString(Result);
+}
+
+/// \brief Add a completion for "this", if we're in a member function.
+static void addThisCompletion(Sema &S, ResultBuilder &Results) {
+  QualType ThisTy = S.getCurrentThisType();
+  if (ThisTy.isNull())
+    return;
+  
+  CodeCompletionAllocator &Allocator = Results.getAllocator();
+  CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo());
+  PrintingPolicy Policy = getCompletionPrintingPolicy(S);
+  Builder.AddResultTypeChunk(GetCompletionTypeString(ThisTy, 
+                                                     S.Context, 
+                                                     Policy,
+                                                     Allocator));
+  Builder.AddTypedTextChunk("this");
+  Results.AddResult(CodeCompletionResult(Builder.TakeString()));            
+}
+
+/// \brief Add language constructs that show up for "ordinary" names.
+static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC,
+                                   Scope *S,
+                                   Sema &SemaRef,
+                                   ResultBuilder &Results) {
+  CodeCompletionAllocator &Allocator = Results.getAllocator();
+  CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo());
+  PrintingPolicy Policy = getCompletionPrintingPolicy(SemaRef);
+  
+  typedef CodeCompletionResult Result;
+  switch (CCC) {
+  case Sema::PCC_Namespace:
+    if (SemaRef.getLangOpts().CPlusPlus) {
+      if (Results.includeCodePatterns()) {
+        // namespace <identifier> { declarations }
+        Builder.AddTypedTextChunk("namespace");
+        Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
+        Builder.AddPlaceholderChunk("identifier");
+        Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
+        Builder.AddPlaceholderChunk("declarations");
+        Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
+        Builder.AddChunk(CodeCompletionString::CK_RightBrace);
+        Results.AddResult(Result(Builder.TakeString()));
+      }
+      
+      // namespace identifier = identifier ;
+      Builder.AddTypedTextChunk("namespace");
+      Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
+      Builder.AddPlaceholderChunk("name");
+      Builder.AddChunk(CodeCompletionString::CK_Equal);
+      Builder.AddPlaceholderChunk("namespace");
+      Results.AddResult(Result(Builder.TakeString()));
+
+      // Using directives
+      Builder.AddTypedTextChunk("using");
+      Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
+      Builder.AddTextChunk("namespace");
+      Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
+      Builder.AddPlaceholderChunk("identifier");
+      Results.AddResult(Result(Builder.TakeString()));
+
+      // asm(string-literal)      
+      Builder.AddTypedTextChunk("asm");
+      Builder.AddChunk(CodeCompletionString::CK_LeftParen);
+      Builder.AddPlaceholderChunk("string-literal");
+      Builder.AddChunk(CodeCompletionString::CK_RightParen);
+      Results.AddResult(Result(Builder.TakeString()));
+
+      if (Results.includeCodePatterns()) {
+        // Explicit template instantiation
+        Builder.AddTypedTextChunk("template");
+        Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
+        Builder.AddPlaceholderChunk("declaration");
+        Results.AddResult(Result(Builder.TakeString()));
+      }
+    }
+      
+    if (SemaRef.getLangOpts().ObjC1)
+      AddObjCTopLevelResults(Results, true);
+      
+    AddTypedefResult(Results);
+    // Fall through
+
+  case Sema::PCC_Class:
+    if (SemaRef.getLangOpts().CPlusPlus) {
+      // Using declaration
+      Builder.AddTypedTextChunk("using");
+      Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
+      Builder.AddPlaceholderChunk("qualifier");
+      Builder.AddTextChunk("::");
+      Builder.AddPlaceholderChunk("name");
+      Results.AddResult(Result(Builder.TakeString()));
+      
+      // using typename qualifier::name (only in a dependent context)
+      if (SemaRef.CurContext->isDependentContext()) {
+        Builder.AddTypedTextChunk("using");
+        Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
+        Builder.AddTextChunk("typename");
+        Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
+        Builder.AddPlaceholderChunk("qualifier");
+        Builder.AddTextChunk("::");
+        Builder.AddPlaceholderChunk("name");
+        Results.AddResult(Result(Builder.TakeString()));
+      }
+
+      if (CCC == Sema::PCC_Class) {
+        AddTypedefResult(Results);
+
+        // public:
+        Builder.AddTypedTextChunk("public");
+        if (Results.includeCodePatterns())
+          Builder.AddChunk(CodeCompletionString::CK_Colon);
+        Results.AddResult(Result(Builder.TakeString()));
+
+        // protected:
+        Builder.AddTypedTextChunk("protected");
+        if (Results.includeCodePatterns())
+          Builder.AddChunk(CodeCompletionString::CK_Colon);
+        Results.AddResult(Result(Builder.TakeString()));
+
+        // private:
+        Builder.AddTypedTextChunk("private");
+        if (Results.includeCodePatterns())
+          Builder.AddChunk(CodeCompletionString::CK_Colon);
+        Results.AddResult(Result(Builder.TakeString()));
+      }
+    }
+    // Fall through
+
+  case Sema::PCC_Template:
+  case Sema::PCC_MemberTemplate:
+    if (SemaRef.getLangOpts().CPlusPlus && Results.includeCodePatterns()) {
+      // template < parameters >
+      Builder.AddTypedTextChunk("template");
+      Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
+      Builder.AddPlaceholderChunk("parameters");
+      Builder.AddChunk(CodeCompletionString::CK_RightAngle);
+      Results.AddResult(Result(Builder.TakeString()));
+    }
+
+    AddStorageSpecifiers(CCC, SemaRef.getLangOpts(), Results);
+    AddFunctionSpecifiers(CCC, SemaRef.getLangOpts(), Results);
+    break;
+
+  case Sema::PCC_ObjCInterface:
+    AddObjCInterfaceResults(SemaRef.getLangOpts(), Results, true);
+    AddStorageSpecifiers(CCC, SemaRef.getLangOpts(), Results);
+    AddFunctionSpecifiers(CCC, SemaRef.getLangOpts(), Results);
+    break;
+      
+  case Sema::PCC_ObjCImplementation:
+    AddObjCImplementationResults(SemaRef.getLangOpts(), Results, true);
+    AddStorageSpecifiers(CCC, SemaRef.getLangOpts(), Results);
+    AddFunctionSpecifiers(CCC, SemaRef.getLangOpts(), Results);
+    break;
+      
+  case Sema::PCC_ObjCInstanceVariableList:
+    AddObjCVisibilityResults(SemaRef.getLangOpts(), Results, true);
+    break;
+      
+  case Sema::PCC_RecoveryInFunction:
+  case Sema::PCC_Statement: {
+    AddTypedefResult(Results);
+
+    if (SemaRef.getLangOpts().CPlusPlus && Results.includeCodePatterns() &&
+        SemaRef.getLangOpts().CXXExceptions) {
+      Builder.AddTypedTextChunk("try");
+      Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
+      Builder.AddPlaceholderChunk("statements");
+      Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
+      Builder.AddChunk(CodeCompletionString::CK_RightBrace);
+      Builder.AddTextChunk("catch");
+      Builder.AddChunk(CodeCompletionString::CK_LeftParen);
+      Builder.AddPlaceholderChunk("declaration");
+      Builder.AddChunk(CodeCompletionString::CK_RightParen);
+      Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
+      Builder.AddPlaceholderChunk("statements");
+      Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
+      Builder.AddChunk(CodeCompletionString::CK_RightBrace);
+      Results.AddResult(Result(Builder.TakeString()));
+    }
+    if (SemaRef.getLangOpts().ObjC1)
+      AddObjCStatementResults(Results, true);
+    
+    if (Results.includeCodePatterns()) {
+      // if (condition) { statements }
+      Builder.AddTypedTextChunk("if");
+      Builder.AddChunk(CodeCompletionString::CK_LeftParen);
+      if (SemaRef.getLangOpts().CPlusPlus)
+        Builder.AddPlaceholderChunk("condition");
+      else
+        Builder.AddPlaceholderChunk("expression");
+      Builder.AddChunk(CodeCompletionString::CK_RightParen);
+      Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
+      Builder.AddPlaceholderChunk("statements");
+      Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
+      Builder.AddChunk(CodeCompletionString::CK_RightBrace);
+      Results.AddResult(Result(Builder.TakeString()));
+
+      // switch (condition) { }
+      Builder.AddTypedTextChunk("switch");
+      Builder.AddChunk(CodeCompletionString::CK_LeftParen);
+      if (SemaRef.getLangOpts().CPlusPlus)
+        Builder.AddPlaceholderChunk("condition");
+      else
+        Builder.AddPlaceholderChunk("expression");
+      Builder.AddChunk(CodeCompletionString::CK_RightParen);
+      Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
+      Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
+      Builder.AddChunk(CodeCompletionString::CK_RightBrace);
+      Results.AddResult(Result(Builder.TakeString()));
+    }
+    
+    // Switch-specific statements.
+    if (!SemaRef.getCurFunction()->SwitchStack.empty()) {
+      // case expression:
+      Builder.AddTypedTextChunk("case");
+      Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
+      Builder.AddPlaceholderChunk("expression");
+      Builder.AddChunk(CodeCompletionString::CK_Colon);
+      Results.AddResult(Result(Builder.TakeString()));
+
+      // default:
+      Builder.AddTypedTextChunk("default");
+      Builder.AddChunk(CodeCompletionString::CK_Colon);
+      Results.AddResult(Result(Builder.TakeString()));
+    }
+
+    if (Results.includeCodePatterns()) {
+      /// while (condition) { statements }
+      Builder.AddTypedTextChunk("while");
+      Builder.AddChunk(CodeCompletionString::CK_LeftParen);
+      if (SemaRef.getLangOpts().CPlusPlus)
+        Builder.AddPlaceholderChunk("condition");
+      else
+        Builder.AddPlaceholderChunk("expression");
+      Builder.AddChunk(CodeCompletionString::CK_RightParen);
+      Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
+      Builder.AddPlaceholderChunk("statements");
+      Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
+      Builder.AddChunk(CodeCompletionString::CK_RightBrace);
+      Results.AddResult(Result(Builder.TakeString()));
+
+      // do { statements } while ( expression );
+      Builder.AddTypedTextChunk("do");
+      Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
+      Builder.AddPlaceholderChunk("statements");
+      Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
+      Builder.AddChunk(CodeCompletionString::CK_RightBrace);
+      Builder.AddTextChunk("while");
+      Builder.AddChunk(CodeCompletionString::CK_LeftParen);
+      Builder.AddPlaceholderChunk("expression");
+      Builder.AddChunk(CodeCompletionString::CK_RightParen);
+      Results.AddResult(Result(Builder.TakeString()));
+
+      // for ( for-init-statement ; condition ; expression ) { statements }
+      Builder.AddTypedTextChunk("for");
+      Builder.AddChunk(CodeCompletionString::CK_LeftParen);
+      if (SemaRef.getLangOpts().CPlusPlus || SemaRef.getLangOpts().C99)
+        Builder.AddPlaceholderChunk("init-statement");
+      else
+        Builder.AddPlaceholderChunk("init-expression");
+      Builder.AddChunk(CodeCompletionString::CK_SemiColon);
+      Builder.AddPlaceholderChunk("condition");
+      Builder.AddChunk(CodeCompletionString::CK_SemiColon);
+      Builder.AddPlaceholderChunk("inc-expression");
+      Builder.AddChunk(CodeCompletionString::CK_RightParen);
+      Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
+      Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
+      Builder.AddPlaceholderChunk("statements");
+      Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
+      Builder.AddChunk(CodeCompletionString::CK_RightBrace);
+      Results.AddResult(Result(Builder.TakeString()));
+    }
+    
+    if (S->getContinueParent()) {
+      // continue ;
+      Builder.AddTypedTextChunk("continue");
+      Results.AddResult(Result(Builder.TakeString()));
+    }
+
+    if (S->getBreakParent()) {
+      // break ;
+      Builder.AddTypedTextChunk("break");
+      Results.AddResult(Result(Builder.TakeString()));
+    }
+
+    // "return expression ;" or "return ;", depending on whether we
+    // know the function is void or not.
+    bool isVoid = false;
+    if (FunctionDecl *Function = dyn_cast<FunctionDecl>(SemaRef.CurContext))
+      isVoid = Function->getResultType()->isVoidType();
+    else if (ObjCMethodDecl *Method
+                                 = dyn_cast<ObjCMethodDecl>(SemaRef.CurContext))
+      isVoid = Method->getResultType()->isVoidType();
+    else if (SemaRef.getCurBlock() && 
+             !SemaRef.getCurBlock()->ReturnType.isNull())
+      isVoid = SemaRef.getCurBlock()->ReturnType->isVoidType();
+    Builder.AddTypedTextChunk("return");
+    if (!isVoid) {
+      Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
+      Builder.AddPlaceholderChunk("expression");
+    }
+    Results.AddResult(Result(Builder.TakeString()));
+
+    // goto identifier ;
+    Builder.AddTypedTextChunk("goto");
+    Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
+    Builder.AddPlaceholderChunk("label");
+    Results.AddResult(Result(Builder.TakeString()));    
+
+    // Using directives
+    Builder.AddTypedTextChunk("using");
+    Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
+    Builder.AddTextChunk("namespace");
+    Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
+    Builder.AddPlaceholderChunk("identifier");
+    Results.AddResult(Result(Builder.TakeString()));
+  }
+
+  // Fall through (for statement expressions).
+  case Sema::PCC_ForInit:
+  case Sema::PCC_Condition:
+    AddStorageSpecifiers(CCC, SemaRef.getLangOpts(), Results);
+    // Fall through: conditions and statements can have expressions.
+
+  case Sema::PCC_ParenthesizedExpression:
+    if (SemaRef.getLangOpts().ObjCAutoRefCount &&
+        CCC == Sema::PCC_ParenthesizedExpression) {
+      // (__bridge <type>)<expression>
+      Builder.AddTypedTextChunk("__bridge");
+      Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
+      Builder.AddPlaceholderChunk("type");
+      Builder.AddChunk(CodeCompletionString::CK_RightParen);
+      Builder.AddPlaceholderChunk("expression");
+      Results.AddResult(Result(Builder.TakeString()));      
+
+      // (__bridge_transfer <Objective-C type>)<expression>
+      Builder.AddTypedTextChunk("__bridge_transfer");
+      Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
+      Builder.AddPlaceholderChunk("Objective-C type");
+      Builder.AddChunk(CodeCompletionString::CK_RightParen);
+      Builder.AddPlaceholderChunk("expression");
+      Results.AddResult(Result(Builder.TakeString()));      
+
+      // (__bridge_retained <CF type>)<expression>
+      Builder.AddTypedTextChunk("__bridge_retained");
+      Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
+      Builder.AddPlaceholderChunk("CF type");
+      Builder.AddChunk(CodeCompletionString::CK_RightParen);
+      Builder.AddPlaceholderChunk("expression");
+      Results.AddResult(Result(Builder.TakeString()));      
+    }
+    // Fall through
+
+  case Sema::PCC_Expression: {
+    if (SemaRef.getLangOpts().CPlusPlus) {
+      // 'this', if we're in a non-static member function.
+      addThisCompletion(SemaRef, Results);
+      
+      // true
+      Builder.AddResultTypeChunk("bool");
+      Builder.AddTypedTextChunk("true");
+      Results.AddResult(Result(Builder.TakeString()));
+      
+      // false
+      Builder.AddResultTypeChunk("bool");
+      Builder.AddTypedTextChunk("false");
+      Results.AddResult(Result(Builder.TakeString()));
+
+      if (SemaRef.getLangOpts().RTTI) {
+        // dynamic_cast < type-id > ( expression )
+        Builder.AddTypedTextChunk("dynamic_cast");
+        Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
+        Builder.AddPlaceholderChunk("type");
+        Builder.AddChunk(CodeCompletionString::CK_RightAngle);
+        Builder.AddChunk(CodeCompletionString::CK_LeftParen);
+        Builder.AddPlaceholderChunk("expression");
+        Builder.AddChunk(CodeCompletionString::CK_RightParen);
+        Results.AddResult(Result(Builder.TakeString()));      
+      }
+      
+      // static_cast < type-id > ( expression )
+      Builder.AddTypedTextChunk("static_cast");
+      Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
+      Builder.AddPlaceholderChunk("type");
+      Builder.AddChunk(CodeCompletionString::CK_RightAngle);
+      Builder.AddChunk(CodeCompletionString::CK_LeftParen);
+      Builder.AddPlaceholderChunk("expression");
+      Builder.AddChunk(CodeCompletionString::CK_RightParen);
+      Results.AddResult(Result(Builder.TakeString()));      
+
+      // reinterpret_cast < type-id > ( expression )
+      Builder.AddTypedTextChunk("reinterpret_cast");
+      Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
+      Builder.AddPlaceholderChunk("type");
+      Builder.AddChunk(CodeCompletionString::CK_RightAngle);
+      Builder.AddChunk(CodeCompletionString::CK_LeftParen);
+      Builder.AddPlaceholderChunk("expression");
+      Builder.AddChunk(CodeCompletionString::CK_RightParen);
+      Results.AddResult(Result(Builder.TakeString()));      
+
+      // const_cast < type-id > ( expression )
+      Builder.AddTypedTextChunk("const_cast");
+      Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
+      Builder.AddPlaceholderChunk("type");
+      Builder.AddChunk(CodeCompletionString::CK_RightAngle);
+      Builder.AddChunk(CodeCompletionString::CK_LeftParen);
+      Builder.AddPlaceholderChunk("expression");
+      Builder.AddChunk(CodeCompletionString::CK_RightParen);
+      Results.AddResult(Result(Builder.TakeString()));      
+
+      if (SemaRef.getLangOpts().RTTI) {
+        // typeid ( expression-or-type )
+        Builder.AddResultTypeChunk("std::type_info");
+        Builder.AddTypedTextChunk("typeid");
+        Builder.AddChunk(CodeCompletionString::CK_LeftParen);
+        Builder.AddPlaceholderChunk("expression-or-type");
+        Builder.AddChunk(CodeCompletionString::CK_RightParen);
+        Results.AddResult(Result(Builder.TakeString()));      
+      }
+      
+      // new T ( ... )
+      Builder.AddTypedTextChunk("new");
+      Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
+      Builder.AddPlaceholderChunk("type");
+      Builder.AddChunk(CodeCompletionString::CK_LeftParen);
+      Builder.AddPlaceholderChunk("expressions");
+      Builder.AddChunk(CodeCompletionString::CK_RightParen);
+      Results.AddResult(Result(Builder.TakeString()));      
+
+      // new T [ ] ( ... )
+      Builder.AddTypedTextChunk("new");
+      Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
+      Builder.AddPlaceholderChunk("type");
+      Builder.AddChunk(CodeCompletionString::CK_LeftBracket);
+      Builder.AddPlaceholderChunk("size");
+      Builder.AddChunk(CodeCompletionString::CK_RightBracket);
+      Builder.AddChunk(CodeCompletionString::CK_LeftParen);
+      Builder.AddPlaceholderChunk("expressions");
+      Builder.AddChunk(CodeCompletionString::CK_RightParen);
+      Results.AddResult(Result(Builder.TakeString()));      
+
+      // delete expression
+      Builder.AddResultTypeChunk("void");
+      Builder.AddTypedTextChunk("delete");
+      Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
+      Builder.AddPlaceholderChunk("expression");
+      Results.AddResult(Result(Builder.TakeString()));      
+
+      // delete [] expression
+      Builder.AddResultTypeChunk("void");
+      Builder.AddTypedTextChunk("delete");
+      Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
+      Builder.AddChunk(CodeCompletionString::CK_LeftBracket);
+      Builder.AddChunk(CodeCompletionString::CK_RightBracket);
+      Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
+      Builder.AddPlaceholderChunk("expression");
+      Results.AddResult(Result(Builder.TakeString()));
+
+      if (SemaRef.getLangOpts().CXXExceptions) {
+        // throw expression
+        Builder.AddResultTypeChunk("void");
+        Builder.AddTypedTextChunk("throw");
+        Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
+        Builder.AddPlaceholderChunk("expression");
+        Results.AddResult(Result(Builder.TakeString()));
+      }
+     
+      // FIXME: Rethrow?
+
+      if (SemaRef.getLangOpts().CPlusPlus0x) {
+        // nullptr
+        Builder.AddResultTypeChunk("std::nullptr_t");
+        Builder.AddTypedTextChunk("nullptr");
+        Results.AddResult(Result(Builder.TakeString()));
+
+        // alignof
+        Builder.AddResultTypeChunk("size_t");
+        Builder.AddTypedTextChunk("alignof");
+        Builder.AddChunk(CodeCompletionString::CK_LeftParen);
+        Builder.AddPlaceholderChunk("type");
+        Builder.AddChunk(CodeCompletionString::CK_RightParen);
+        Results.AddResult(Result(Builder.TakeString()));
+
+        // noexcept
+        Builder.AddResultTypeChunk("bool");
+        Builder.AddTypedTextChunk("noexcept");
+        Builder.AddChunk(CodeCompletionString::CK_LeftParen);
+        Builder.AddPlaceholderChunk("expression");
+        Builder.AddChunk(CodeCompletionString::CK_RightParen);
+        Results.AddResult(Result(Builder.TakeString()));
+
+        // sizeof... expression
+        Builder.AddResultTypeChunk("size_t");
+        Builder.AddTypedTextChunk("sizeof...");
+        Builder.AddChunk(CodeCompletionString::CK_LeftParen);
+        Builder.AddPlaceholderChunk("parameter-pack");
+        Builder.AddChunk(CodeCompletionString::CK_RightParen);
+        Results.AddResult(Result(Builder.TakeString()));
+      }
+    }
+
+    if (SemaRef.getLangOpts().ObjC1) {
+      // Add "super", if we're in an Objective-C class with a superclass.
+      if (ObjCMethodDecl *Method = SemaRef.getCurMethodDecl()) {
+        // The interface can be NULL.
+        if (ObjCInterfaceDecl *ID = Method->getClassInterface())
+          if (ID->getSuperClass()) {
+            std::string SuperType;
+            SuperType = ID->getSuperClass()->getNameAsString();
+            if (Method->isInstanceMethod())
+              SuperType += " *";
+            
+            Builder.AddResultTypeChunk(Allocator.CopyString(SuperType));
+            Builder.AddTypedTextChunk("super");
+            Results.AddResult(Result(Builder.TakeString()));
+          }
+      }
+
+      AddObjCExpressionResults(Results, true);
+    }
+
+    // sizeof expression
+    Builder.AddResultTypeChunk("size_t");
+    Builder.AddTypedTextChunk("sizeof");
+    Builder.AddChunk(CodeCompletionString::CK_LeftParen);
+    Builder.AddPlaceholderChunk("expression-or-type");
+    Builder.AddChunk(CodeCompletionString::CK_RightParen);
+    Results.AddResult(Result(Builder.TakeString()));
+    break;
+  }
+      
+  case Sema::PCC_Type:
+  case Sema::PCC_LocalDeclarationSpecifiers:
+    break;
+  }
+
+  if (WantTypesInContext(CCC, SemaRef.getLangOpts()))
+    AddTypeSpecifierResults(SemaRef.getLangOpts(), Results);
+
+  if (SemaRef.getLangOpts().CPlusPlus && CCC != Sema::PCC_Type)
+    Results.AddResult(Result("operator"));
+}
+
+/// \brief If the given declaration has an associated type, add it as a result 
+/// type chunk.
+static void AddResultTypeChunk(ASTContext &Context,
+                               const PrintingPolicy &Policy,
+                               NamedDecl *ND,
+                               CodeCompletionBuilder &Result) {
+  if (!ND)
+    return;
+
+  // Skip constructors and conversion functions, which have their return types
+  // built into their names.
+  if (isa<CXXConstructorDecl>(ND) || isa<CXXConversionDecl>(ND))
+    return;
+
+  // Determine the type of the declaration (if it has a type).
+  QualType T;  
+  if (FunctionDecl *Function = dyn_cast<FunctionDecl>(ND))
+    T = Function->getResultType();
+  else if (ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(ND))
+    T = Method->getResultType();
+  else if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(ND))
+    T = FunTmpl->getTemplatedDecl()->getResultType();
+  else if (EnumConstantDecl *Enumerator = dyn_cast<EnumConstantDecl>(ND))
+    T = Context.getTypeDeclType(cast<TypeDecl>(Enumerator->getDeclContext()));
+  else if (isa<UnresolvedUsingValueDecl>(ND)) {
+    /* Do nothing: ignore unresolved using declarations*/
+  } else if (ValueDecl *Value = dyn_cast<ValueDecl>(ND)) {
+    T = Value->getType();
+  } else if (ObjCPropertyDecl *Property = dyn_cast<ObjCPropertyDecl>(ND))
+    T = Property->getType();
+  
+  if (T.isNull() || Context.hasSameType(T, Context.DependentTy))
+    return;
+  
+  Result.AddResultTypeChunk(GetCompletionTypeString(T, Context, Policy,
+                                                    Result.getAllocator()));
+}
+
+static void MaybeAddSentinel(ASTContext &Context, NamedDecl *FunctionOrMethod,
+                             CodeCompletionBuilder &Result) {
+  if (SentinelAttr *Sentinel = FunctionOrMethod->getAttr<SentinelAttr>())
+    if (Sentinel->getSentinel() == 0) {
+      if (Context.getLangOpts().ObjC1 &&
+          Context.Idents.get("nil").hasMacroDefinition())
+        Result.AddTextChunk(", nil");
+      else if (Context.Idents.get("NULL").hasMacroDefinition())
+        Result.AddTextChunk(", NULL");
+      else
+        Result.AddTextChunk(", (void*)0");
+    }
+}
+
+static std::string formatObjCParamQualifiers(unsigned ObjCQuals) {
+  std::string Result;
+  if (ObjCQuals & Decl::OBJC_TQ_In)
+    Result += "in ";
+  else if (ObjCQuals & Decl::OBJC_TQ_Inout)
+    Result += "inout ";
+  else if (ObjCQuals & Decl::OBJC_TQ_Out)
+    Result += "out ";
+  if (ObjCQuals & Decl::OBJC_TQ_Bycopy)
+    Result += "bycopy ";
+  else if (ObjCQuals & Decl::OBJC_TQ_Byref)
+    Result += "byref ";
+  if (ObjCQuals & Decl::OBJC_TQ_Oneway)
+    Result += "oneway ";
+  return Result;
+}
+
+static std::string FormatFunctionParameter(ASTContext &Context,
+                                           const PrintingPolicy &Policy,
+                                           ParmVarDecl *Param,
+                                           bool SuppressName = false,
+                                           bool SuppressBlock = false) {
+  bool ObjCMethodParam = isa<ObjCMethodDecl>(Param->getDeclContext());
+  if (Param->getType()->isDependentType() ||
+      !Param->getType()->isBlockPointerType()) {
+    // The argument for a dependent or non-block parameter is a placeholder 
+    // containing that parameter's type.
+    std::string Result;
+    
+    if (Param->getIdentifier() && !ObjCMethodParam && !SuppressName)
+      Result = Param->getIdentifier()->getName();
+    
+    Param->getType().getAsStringInternal(Result, Policy);
+    
+    if (ObjCMethodParam) {
+      Result = "(" + formatObjCParamQualifiers(Param->getObjCDeclQualifier())
+             + Result + ")";
+      if (Param->getIdentifier() && !SuppressName)
+        Result += Param->getIdentifier()->getName();
+    }
+    return Result;
+  }
+  
+  // The argument for a block pointer parameter is a block literal with
+  // the appropriate type.
+  FunctionTypeLoc *Block = 0;
+  FunctionProtoTypeLoc *BlockProto = 0;
+  TypeLoc TL;
+  if (TypeSourceInfo *TSInfo = Param->getTypeSourceInfo()) {
+    TL = TSInfo->getTypeLoc().getUnqualifiedLoc();
+    while (true) {
+      // Look through typedefs.
+      if (!SuppressBlock) {
+        if (TypedefTypeLoc *TypedefTL = dyn_cast<TypedefTypeLoc>(&TL)) {
+          if (TypeSourceInfo *InnerTSInfo
+              = TypedefTL->getTypedefNameDecl()->getTypeSourceInfo()) {
+            TL = InnerTSInfo->getTypeLoc().getUnqualifiedLoc();
+            continue;
+          }
+        }
+        
+        // Look through qualified types
+        if (QualifiedTypeLoc *QualifiedTL = dyn_cast<QualifiedTypeLoc>(&TL)) {
+          TL = QualifiedTL->getUnqualifiedLoc();
+          continue;
+        }
+      }
+      
+      // Try to get the function prototype behind the block pointer type,
+      // then we're done.
+      if (BlockPointerTypeLoc *BlockPtr
+          = dyn_cast<BlockPointerTypeLoc>(&TL)) {
+        TL = BlockPtr->getPointeeLoc().IgnoreParens();
+        Block = dyn_cast<FunctionTypeLoc>(&TL);
+        BlockProto = dyn_cast<FunctionProtoTypeLoc>(&TL);
+      }
+      break;
+    }
+  }
+
+  if (!Block) {
+    // We were unable to find a FunctionProtoTypeLoc with parameter names
+    // for the block; just use the parameter type as a placeholder.
+    std::string Result;
+    if (!ObjCMethodParam && Param->getIdentifier())
+      Result = Param->getIdentifier()->getName();
+
+    Param->getType().getUnqualifiedType().getAsStringInternal(Result, Policy);
+    
+    if (ObjCMethodParam) {
+      Result = "(" + formatObjCParamQualifiers(Param->getObjCDeclQualifier())
+             + Result + ")";
+      if (Param->getIdentifier())
+        Result += Param->getIdentifier()->getName();
+    }
+      
+    return Result;
+  }
+    
+  // We have the function prototype behind the block pointer type, as it was
+  // written in the source.
+  std::string Result;
+  QualType ResultType = Block->getTypePtr()->getResultType();
+  if (!ResultType->isVoidType() || SuppressBlock)
+    ResultType.getAsStringInternal(Result, Policy);
+
+  // Format the parameter list.
+  std::string Params;
+  if (!BlockProto || Block->getNumArgs() == 0) {
+    if (BlockProto && BlockProto->getTypePtr()->isVariadic())
+      Params = "(...)";
+    else
+      Params = "(void)";
+  } else {
+    Params += "(";
+    for (unsigned I = 0, N = Block->getNumArgs(); I != N; ++I) {
+      if (I)
+        Params += ", ";
+      Params += FormatFunctionParameter(Context, Policy, Block->getArg(I),
+                                        /*SuppressName=*/false, 
+                                        /*SuppressBlock=*/true);
+      
+      if (I == N - 1 && BlockProto->getTypePtr()->isVariadic())
+        Params += ", ...";
+    }
+    Params += ")";
+  }
+  
+  if (SuppressBlock) {
+    // Format as a parameter.
+    Result = Result + " (^";
+    if (Param->getIdentifier())
+      Result += Param->getIdentifier()->getName();
+    Result += ")";
+    Result += Params;
+  } else {
+    // Format as a block literal argument.
+    Result = '^' + Result;
+    Result += Params;
+    
+    if (Param->getIdentifier())
+      Result += Param->getIdentifier()->getName();
+  }
+  
+  return Result;
+}
+
+/// \brief Add function parameter chunks to the given code completion string.
+static void AddFunctionParameterChunks(ASTContext &Context,
+                                       const PrintingPolicy &Policy,
+                                       FunctionDecl *Function,
+                                       CodeCompletionBuilder &Result,
+                                       unsigned Start = 0,
+                                       bool InOptional = false) {
+  bool FirstParameter = true;
+  
+  for (unsigned P = Start, N = Function->getNumParams(); P != N; ++P) {
+    ParmVarDecl *Param = Function->getParamDecl(P);
+    
+    if (Param->hasDefaultArg() && !InOptional) {
+      // When we see an optional default argument, put that argument and
+      // the remaining default arguments into a new, optional string.
+      CodeCompletionBuilder Opt(Result.getAllocator(),
+                                Result.getCodeCompletionTUInfo());
+      if (!FirstParameter)
+        Opt.AddChunk(CodeCompletionString::CK_Comma);
+      AddFunctionParameterChunks(Context, Policy, Function, Opt, P, true);
+      Result.AddOptionalChunk(Opt.TakeString());
+      break;
+    }
+    
+    if (FirstParameter)
+      FirstParameter = false;
+    else
+      Result.AddChunk(CodeCompletionString::CK_Comma);
+    
+    InOptional = false;
+    
+    // Format the placeholder string.
+    std::string PlaceholderStr = FormatFunctionParameter(Context, Policy, 
+                                                         Param);
+        
+    if (Function->isVariadic() && P == N - 1)
+      PlaceholderStr += ", ...";
+
+    // Add the placeholder string.
+    Result.AddPlaceholderChunk(
+                             Result.getAllocator().CopyString(PlaceholderStr));
+  }
+  
+  if (const FunctionProtoType *Proto 
+        = Function->getType()->getAs<FunctionProtoType>())
+    if (Proto->isVariadic()) {
+      if (Proto->getNumArgs() == 0)
+        Result.AddPlaceholderChunk("...");
+
+      MaybeAddSentinel(Context, Function, Result);
+    }
+}
+
+/// \brief Add template parameter chunks to the given code completion string.
+static void AddTemplateParameterChunks(ASTContext &Context,
+                                       const PrintingPolicy &Policy,
+                                       TemplateDecl *Template,
+                                       CodeCompletionBuilder &Result,
+                                       unsigned MaxParameters = 0,
+                                       unsigned Start = 0,
+                                       bool InDefaultArg = false) {
+  bool FirstParameter = true;
+  
+  TemplateParameterList *Params = Template->getTemplateParameters();
+  TemplateParameterList::iterator PEnd = Params->end();
+  if (MaxParameters)
+    PEnd = Params->begin() + MaxParameters;
+  for (TemplateParameterList::iterator P = Params->begin() + Start; 
+       P != PEnd; ++P) {
+    bool HasDefaultArg = false;
+    std::string PlaceholderStr;
+    if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(*P)) {
+      if (TTP->wasDeclaredWithTypename())
+        PlaceholderStr = "typename";
+      else
+        PlaceholderStr = "class";
+      
+      if (TTP->getIdentifier()) {
+        PlaceholderStr += ' ';
+        PlaceholderStr += TTP->getIdentifier()->getName();
+      }
+      
+      HasDefaultArg = TTP->hasDefaultArgument();
+    } else if (NonTypeTemplateParmDecl *NTTP 
+                                    = dyn_cast<NonTypeTemplateParmDecl>(*P)) {
+      if (NTTP->getIdentifier())
+        PlaceholderStr = NTTP->getIdentifier()->getName();
+      NTTP->getType().getAsStringInternal(PlaceholderStr, Policy);
+      HasDefaultArg = NTTP->hasDefaultArgument();
+    } else {
+      assert(isa<TemplateTemplateParmDecl>(*P));
+      TemplateTemplateParmDecl *TTP = cast<TemplateTemplateParmDecl>(*P);
+      
+      // Since putting the template argument list into the placeholder would
+      // be very, very long, we just use an abbreviation.
+      PlaceholderStr = "template<...> class";
+      if (TTP->getIdentifier()) {
+        PlaceholderStr += ' ';
+        PlaceholderStr += TTP->getIdentifier()->getName();
+      }
+      
+      HasDefaultArg = TTP->hasDefaultArgument();
+    }
+    
+    if (HasDefaultArg && !InDefaultArg) {
+      // When we see an optional default argument, put that argument and
+      // the remaining default arguments into a new, optional string.
+      CodeCompletionBuilder Opt(Result.getAllocator(),
+                                Result.getCodeCompletionTUInfo());
+      if (!FirstParameter)
+        Opt.AddChunk(CodeCompletionString::CK_Comma);
+      AddTemplateParameterChunks(Context, Policy, Template, Opt, MaxParameters,
+                                 P - Params->begin(), true);
+      Result.AddOptionalChunk(Opt.TakeString());
+      break;
+    }
+    
+    InDefaultArg = false;
+    
+    if (FirstParameter)
+      FirstParameter = false;
+    else
+      Result.AddChunk(CodeCompletionString::CK_Comma);
+    
+    // Add the placeholder string.
+    Result.AddPlaceholderChunk(
+                              Result.getAllocator().CopyString(PlaceholderStr));
+  }    
+}
+
+/// \brief Add a qualifier to the given code-completion string, if the
+/// provided nested-name-specifier is non-NULL.
+static void 
+AddQualifierToCompletionString(CodeCompletionBuilder &Result, 
+                               NestedNameSpecifier *Qualifier, 
+                               bool QualifierIsInformative,
+                               ASTContext &Context,
+                               const PrintingPolicy &Policy) {
+  if (!Qualifier)
+    return;
+  
+  std::string PrintedNNS;
+  {
+    llvm::raw_string_ostream OS(PrintedNNS);
+    Qualifier->print(OS, Policy);
+  }
+  if (QualifierIsInformative)
+    Result.AddInformativeChunk(Result.getAllocator().CopyString(PrintedNNS));
+  else
+    Result.AddTextChunk(Result.getAllocator().CopyString(PrintedNNS));
+}
+
+static void 
+AddFunctionTypeQualsToCompletionString(CodeCompletionBuilder &Result,
+                                       FunctionDecl *Function) {
+  const FunctionProtoType *Proto
+    = Function->getType()->getAs<FunctionProtoType>();
+  if (!Proto || !Proto->getTypeQuals())
+    return;
+
+  // FIXME: Add ref-qualifier!
+  
+  // Handle single qualifiers without copying
+  if (Proto->getTypeQuals() == Qualifiers::Const) {
+    Result.AddInformativeChunk(" const");
+    return;
+  }
+
+  if (Proto->getTypeQuals() == Qualifiers::Volatile) {
+    Result.AddInformativeChunk(" volatile");
+    return;
+  }
+
+  if (Proto->getTypeQuals() == Qualifiers::Restrict) {
+    Result.AddInformativeChunk(" restrict");
+    return;
+  }
+
+  // Handle multiple qualifiers.
+  std::string QualsStr;
+  if (Proto->getTypeQuals() & Qualifiers::Const)
+    QualsStr += " const";
+  if (Proto->getTypeQuals() & Qualifiers::Volatile)
+    QualsStr += " volatile";
+  if (Proto->getTypeQuals() & Qualifiers::Restrict)
+    QualsStr += " restrict";
+  Result.AddInformativeChunk(Result.getAllocator().CopyString(QualsStr));
+}
+
+/// \brief Add the name of the given declaration 
+static void AddTypedNameChunk(ASTContext &Context, const PrintingPolicy &Policy,
+                              NamedDecl *ND, CodeCompletionBuilder &Result) {
+  DeclarationName Name = ND->getDeclName();
+  if (!Name)
+    return;
+  
+  switch (Name.getNameKind()) {
+    case DeclarationName::CXXOperatorName: {
+      const char *OperatorName = 0;
+      switch (Name.getCXXOverloadedOperator()) {
+      case OO_None: 
+      case OO_Conditional:
+      case NUM_OVERLOADED_OPERATORS:
+        OperatorName = "operator"; 
+        break;
+    
+#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \
+      case OO_##Name: OperatorName = "operator" Spelling; break;
+#define OVERLOADED_OPERATOR_MULTI(Name,Spelling,Unary,Binary,MemberOnly)
+#include "clang/Basic/OperatorKinds.def"
+          
+      case OO_New:          OperatorName = "operator new"; break;
+      case OO_Delete:       OperatorName = "operator delete"; break;
+      case OO_Array_New:    OperatorName = "operator new[]"; break;
+      case OO_Array_Delete: OperatorName = "operator delete[]"; break;
+      case OO_Call:         OperatorName = "operator()"; break;
+      case OO_Subscript:    OperatorName = "operator[]"; break;
+      }
+      Result.AddTypedTextChunk(OperatorName);
+      break;
+    }
+      
+  case DeclarationName::Identifier:
+  case DeclarationName::CXXConversionFunctionName:
+  case DeclarationName::CXXDestructorName:
+  case DeclarationName::CXXLiteralOperatorName:
+    Result.AddTypedTextChunk(
+                      Result.getAllocator().CopyString(ND->getNameAsString()));
+    break;
+      
+  case DeclarationName::CXXUsingDirective:
+  case DeclarationName::ObjCZeroArgSelector:
+  case DeclarationName::ObjCOneArgSelector:
+  case DeclarationName::ObjCMultiArgSelector:
+    break;
+      
+  case DeclarationName::CXXConstructorName: {
+    CXXRecordDecl *Record = 0;
+    QualType Ty = Name.getCXXNameType();
+    if (const RecordType *RecordTy = Ty->getAs<RecordType>())
+      Record = cast<CXXRecordDecl>(RecordTy->getDecl());
+    else if (const InjectedClassNameType *InjectedTy
+                                        = Ty->getAs<InjectedClassNameType>())
+      Record = InjectedTy->getDecl();
+    else {
+      Result.AddTypedTextChunk(
+                      Result.getAllocator().CopyString(ND->getNameAsString()));
+      break;
+    }
+    
+    Result.AddTypedTextChunk(
+                  Result.getAllocator().CopyString(Record->getNameAsString()));
+    if (ClassTemplateDecl *Template = Record->getDescribedClassTemplate()) {
+      Result.AddChunk(CodeCompletionString::CK_LeftAngle);
+      AddTemplateParameterChunks(Context, Policy, Template, Result);
+      Result.AddChunk(CodeCompletionString::CK_RightAngle);
+    }
+    break;
+  }
+  }
+}
+
+CodeCompletionString *CodeCompletionResult::CreateCodeCompletionString(Sema &S,
+                                         CodeCompletionAllocator &Allocator,
+                                         CodeCompletionTUInfo &CCTUInfo) {
+  return CreateCodeCompletionString(S.Context, S.PP, Allocator, CCTUInfo);
+}
+
+/// \brief If possible, create a new code completion string for the given
+/// result.
+///
+/// \returns Either a new, heap-allocated code completion string describing
+/// how to use this result, or NULL to indicate that the string or name of the
+/// result is all that is needed.
+CodeCompletionString *
+CodeCompletionResult::CreateCodeCompletionString(ASTContext &Ctx,
+                                                 Preprocessor &PP,
+                                           CodeCompletionAllocator &Allocator,
+                                           CodeCompletionTUInfo &CCTUInfo) {
+  CodeCompletionBuilder Result(Allocator, CCTUInfo, Priority, Availability);
+  
+  PrintingPolicy Policy = getCompletionPrintingPolicy(Ctx, PP);
+  if (Kind == RK_Pattern) {
+    Pattern->Priority = Priority;
+    Pattern->Availability = Availability;
+    
+    if (Declaration) {
+      Result.addParentContext(Declaration->getDeclContext());
+      Pattern->ParentKind = Result.getParentKind();
+      Pattern->ParentName = Result.getParentName();
+    }
+    
+    return Pattern;
+  }
+  
+  if (Kind == RK_Keyword) {
+    Result.AddTypedTextChunk(Keyword);
+    return Result.TakeString();
+  }
+  
+  if (Kind == RK_Macro) {
+    MacroInfo *MI = PP.getMacroInfo(Macro);
+    assert(MI && "Not a macro?");
+
+    Result.AddTypedTextChunk(
+                            Result.getAllocator().CopyString(Macro->getName()));
+
+    if (!MI->isFunctionLike())
+      return Result.TakeString();
+    
+    // Format a function-like macro with placeholders for the arguments.
+    Result.AddChunk(CodeCompletionString::CK_LeftParen);
+    MacroInfo::arg_iterator A = MI->arg_begin(), AEnd = MI->arg_end();
+    
+    // C99 variadic macros add __VA_ARGS__ at the end. Skip it.
+    if (MI->isC99Varargs()) {
+      --AEnd;
+      
+      if (A == AEnd) {
+        Result.AddPlaceholderChunk("...");
+      }
+    }
+    
+    for (MacroInfo::arg_iterator A = MI->arg_begin(); A != AEnd; ++A) {
+      if (A != MI->arg_begin())
+        Result.AddChunk(CodeCompletionString::CK_Comma);
+
+      if (MI->isVariadic() && (A+1) == AEnd) {
+        SmallString<32> Arg = (*A)->getName();
+        if (MI->isC99Varargs())
+          Arg += ", ...";
+        else
+          Arg += "...";
+        Result.AddPlaceholderChunk(Result.getAllocator().CopyString(Arg));
+        break;
+      }
+
+      // Non-variadic macros are simple.
+      Result.AddPlaceholderChunk(
+                          Result.getAllocator().CopyString((*A)->getName()));
+    }
+    Result.AddChunk(CodeCompletionString::CK_RightParen);
+    return Result.TakeString();
+  }
+  
+  assert(Kind == RK_Declaration && "Missed a result kind?");
+  NamedDecl *ND = Declaration;
+  Result.addParentContext(ND->getDeclContext());
+                          
+  if (StartsNestedNameSpecifier) {
+    Result.AddTypedTextChunk(
+                      Result.getAllocator().CopyString(ND->getNameAsString()));
+    Result.AddTextChunk("::");
+    return Result.TakeString();
+  }
+
+  for (Decl::attr_iterator i = ND->attr_begin(); i != ND->attr_end(); ++i) {
+    if (AnnotateAttr *Attr = dyn_cast_or_null<AnnotateAttr>(*i)) {
+      Result.AddAnnotation(Result.getAllocator().CopyString(Attr->getAnnotation()));
+    }
+  }
+  
+  AddResultTypeChunk(Ctx, Policy, ND, Result);
+  
+  if (FunctionDecl *Function = dyn_cast<FunctionDecl>(ND)) {
+    AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative, 
+                                   Ctx, Policy);
+    AddTypedNameChunk(Ctx, Policy, ND, Result);
+    Result.AddChunk(CodeCompletionString::CK_LeftParen);
+    AddFunctionParameterChunks(Ctx, Policy, Function, Result);
+    Result.AddChunk(CodeCompletionString::CK_RightParen);
+    AddFunctionTypeQualsToCompletionString(Result, Function);
+    return Result.TakeString();
+  }
+  
+  if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(ND)) {
+    AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative, 
+                                   Ctx, Policy);
+    FunctionDecl *Function = FunTmpl->getTemplatedDecl();
+    AddTypedNameChunk(Ctx, Policy, Function, Result);
+
+    // Figure out which template parameters are deduced (or have default
+    // arguments).
+    llvm::SmallBitVector Deduced;
+    Sema::MarkDeducedTemplateParameters(Ctx, FunTmpl, Deduced);
+    unsigned LastDeducibleArgument;
+    for (LastDeducibleArgument = Deduced.size(); LastDeducibleArgument > 0;
+         --LastDeducibleArgument) {
+      if (!Deduced[LastDeducibleArgument - 1]) {
+        // C++0x: Figure out if the template argument has a default. If so,
+        // the user doesn't need to type this argument.
+        // FIXME: We need to abstract template parameters better!
+        bool HasDefaultArg = false;
+        NamedDecl *Param = FunTmpl->getTemplateParameters()->getParam(
+                                                    LastDeducibleArgument - 1);
+        if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(Param))
+          HasDefaultArg = TTP->hasDefaultArgument();
+        else if (NonTypeTemplateParmDecl *NTTP 
+                 = dyn_cast<NonTypeTemplateParmDecl>(Param))
+          HasDefaultArg = NTTP->hasDefaultArgument();
+        else {
+          assert(isa<TemplateTemplateParmDecl>(Param));
+          HasDefaultArg 
+            = cast<TemplateTemplateParmDecl>(Param)->hasDefaultArgument();
+        }
+        
+        if (!HasDefaultArg)
+          break;
+      }
+    }
+    
+    if (LastDeducibleArgument) {
+      // Some of the function template arguments cannot be deduced from a
+      // function call, so we introduce an explicit template argument list
+      // containing all of the arguments up to the first deducible argument.
+      Result.AddChunk(CodeCompletionString::CK_LeftAngle);
+      AddTemplateParameterChunks(Ctx, Policy, FunTmpl, Result, 
+                                 LastDeducibleArgument);
+      Result.AddChunk(CodeCompletionString::CK_RightAngle);
+    }
+    
+    // Add the function parameters
+    Result.AddChunk(CodeCompletionString::CK_LeftParen);
+    AddFunctionParameterChunks(Ctx, Policy, Function, Result);
+    Result.AddChunk(CodeCompletionString::CK_RightParen);
+    AddFunctionTypeQualsToCompletionString(Result, Function);
+    return Result.TakeString();
+  }
+  
+  if (TemplateDecl *Template = dyn_cast<TemplateDecl>(ND)) {
+    AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative, 
+                                   Ctx, Policy);
+    Result.AddTypedTextChunk(
+                Result.getAllocator().CopyString(Template->getNameAsString()));
+    Result.AddChunk(CodeCompletionString::CK_LeftAngle);
+    AddTemplateParameterChunks(Ctx, Policy, Template, Result);
+    Result.AddChunk(CodeCompletionString::CK_RightAngle);
+    return Result.TakeString();
+  }
+  
+  if (ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(ND)) {
+    Selector Sel = Method->getSelector();
+    if (Sel.isUnarySelector()) {
+      Result.AddTypedTextChunk(Result.getAllocator().CopyString(
+                                  Sel.getNameForSlot(0)));
+      return Result.TakeString();
+    }
+
+    std::string SelName = Sel.getNameForSlot(0).str();
+    SelName += ':';
+    if (StartParameter == 0)
+      Result.AddTypedTextChunk(Result.getAllocator().CopyString(SelName));
+    else {
+      Result.AddInformativeChunk(Result.getAllocator().CopyString(SelName));
+      
+      // If there is only one parameter, and we're past it, add an empty
+      // typed-text chunk since there is nothing to type.
+      if (Method->param_size() == 1)
+        Result.AddTypedTextChunk("");
+    }
+    unsigned Idx = 0;
+    for (ObjCMethodDecl::param_iterator P = Method->param_begin(),
+                                     PEnd = Method->param_end();
+         P != PEnd; (void)++P, ++Idx) {
+      if (Idx > 0) {
+        std::string Keyword;
+        if (Idx > StartParameter)
+          Result.AddChunk(CodeCompletionString::CK_HorizontalSpace);
+        if (IdentifierInfo *II = Sel.getIdentifierInfoForSlot(Idx))
+          Keyword += II->getName();
+        Keyword += ":";
+        if (Idx < StartParameter || AllParametersAreInformative)
+          Result.AddInformativeChunk(Result.getAllocator().CopyString(Keyword));
+        else 
+          Result.AddTypedTextChunk(Result.getAllocator().CopyString(Keyword));
+      }
+      
+      // If we're before the starting parameter, skip the placeholder.
+      if (Idx < StartParameter)
+        continue;
+
+      std::string Arg;
+      
+      if ((*P)->getType()->isBlockPointerType() && !DeclaringEntity)
+        Arg = FormatFunctionParameter(Ctx, Policy, *P, true);
+      else {
+        (*P)->getType().getAsStringInternal(Arg, Policy);
+        Arg = "(" + formatObjCParamQualifiers((*P)->getObjCDeclQualifier()) 
+            + Arg + ")";
+        if (IdentifierInfo *II = (*P)->getIdentifier())
+          if (DeclaringEntity || AllParametersAreInformative)
+            Arg += II->getName();
+      }
+      
+      if (Method->isVariadic() && (P + 1) == PEnd)
+        Arg += ", ...";
+      
+      if (DeclaringEntity)
+        Result.AddTextChunk(Result.getAllocator().CopyString(Arg));
+      else if (AllParametersAreInformative)
+        Result.AddInformativeChunk(Result.getAllocator().CopyString(Arg));
+      else
+        Result.AddPlaceholderChunk(Result.getAllocator().CopyString(Arg));
+    }
+
+    if (Method->isVariadic()) {
+      if (Method->param_size() == 0) {
+        if (DeclaringEntity)
+          Result.AddTextChunk(", ...");
+        else if (AllParametersAreInformative)
+          Result.AddInformativeChunk(", ...");
+        else
+          Result.AddPlaceholderChunk(", ...");
+      }
+      
+      MaybeAddSentinel(Ctx, Method, Result);
+    }
+    
+    return Result.TakeString();
+  }
+
+  if (Qualifier)
+    AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative, 
+                                   Ctx, Policy);
+
+  Result.AddTypedTextChunk(
+                       Result.getAllocator().CopyString(ND->getNameAsString()));
+  return Result.TakeString();
+}
+
+CodeCompletionString *
+CodeCompleteConsumer::OverloadCandidate::CreateSignatureString(
+                                                          unsigned CurrentArg,
+                                                               Sema &S,
+                                     CodeCompletionAllocator &Allocator,
+                                     CodeCompletionTUInfo &CCTUInfo) const {
+  PrintingPolicy Policy = getCompletionPrintingPolicy(S);
+
+  // FIXME: Set priority, availability appropriately.
+  CodeCompletionBuilder Result(Allocator,CCTUInfo, 1, CXAvailability_Available);
+  FunctionDecl *FDecl = getFunction();
+  AddResultTypeChunk(S.Context, Policy, FDecl, Result);
+  const FunctionProtoType *Proto 
+    = dyn_cast<FunctionProtoType>(getFunctionType());
+  if (!FDecl && !Proto) {
+    // Function without a prototype. Just give the return type and a 
+    // highlighted ellipsis.
+    const FunctionType *FT = getFunctionType();
+    Result.AddTextChunk(GetCompletionTypeString(FT->getResultType(),
+                                                S.Context, Policy, 
+                                                Result.getAllocator()));
+    Result.AddChunk(CodeCompletionString::CK_LeftParen);
+    Result.AddChunk(CodeCompletionString::CK_CurrentParameter, "...");
+    Result.AddChunk(CodeCompletionString::CK_RightParen);
+    return Result.TakeString();
+  }
+  
+  if (FDecl)
+    Result.AddTextChunk(
+                    Result.getAllocator().CopyString(FDecl->getNameAsString()));
+  else
+    Result.AddTextChunk(
+         Result.getAllocator().CopyString(
+                                  Proto->getResultType().getAsString(Policy)));
+  
+  Result.AddChunk(CodeCompletionString::CK_LeftParen);
+  unsigned NumParams = FDecl? FDecl->getNumParams() : Proto->getNumArgs();
+  for (unsigned I = 0; I != NumParams; ++I) {
+    if (I)
+      Result.AddChunk(CodeCompletionString::CK_Comma);
+    
+    std::string ArgString;
+    QualType ArgType;
+    
+    if (FDecl) {
+      ArgString = FDecl->getParamDecl(I)->getNameAsString();
+      ArgType = FDecl->getParamDecl(I)->getOriginalType();
+    } else {
+      ArgType = Proto->getArgType(I);
+    }
+    
+    ArgType.getAsStringInternal(ArgString, Policy);
+    
+    if (I == CurrentArg)
+      Result.AddChunk(CodeCompletionString::CK_CurrentParameter,
+                      Result.getAllocator().CopyString(ArgString));
+    else
+      Result.AddTextChunk(Result.getAllocator().CopyString(ArgString));
+  }
+  
+  if (Proto && Proto->isVariadic()) {
+    Result.AddChunk(CodeCompletionString::CK_Comma);
+    if (CurrentArg < NumParams)
+      Result.AddTextChunk("...");
+    else
+      Result.AddChunk(CodeCompletionString::CK_CurrentParameter, "...");
+  }
+  Result.AddChunk(CodeCompletionString::CK_RightParen);
+  
+  return Result.TakeString();
+}
+
+unsigned clang::getMacroUsagePriority(StringRef MacroName, 
+                                      const LangOptions &LangOpts,
+                                      bool PreferredTypeIsPointer) {
+  unsigned Priority = CCP_Macro;
+  
+  // Treat the "nil", "Nil" and "NULL" macros as null pointer constants.
+  if (MacroName.equals("nil") || MacroName.equals("NULL") || 
+      MacroName.equals("Nil")) {
+    Priority = CCP_Constant;
+    if (PreferredTypeIsPointer)
+      Priority = Priority / CCF_SimilarTypeMatch;
+  } 
+  // Treat "YES", "NO", "true", and "false" as constants.
+  else if (MacroName.equals("YES") || MacroName.equals("NO") ||
+           MacroName.equals("true") || MacroName.equals("false"))
+    Priority = CCP_Constant;
+  // Treat "bool" as a type.
+  else if (MacroName.equals("bool"))
+    Priority = CCP_Type + (LangOpts.ObjC1? CCD_bool_in_ObjC : 0);
+    
+  
+  return Priority;
+}
+
+CXCursorKind clang::getCursorKindForDecl(Decl *D) {
+  if (!D)
+    return CXCursor_UnexposedDecl;
+  
+  switch (D->getKind()) {
+    case Decl::Enum:               return CXCursor_EnumDecl;
+    case Decl::EnumConstant:       return CXCursor_EnumConstantDecl;
+    case Decl::Field:              return CXCursor_FieldDecl;
+    case Decl::Function:  
+      return CXCursor_FunctionDecl;
+    case Decl::ObjCCategory:       return CXCursor_ObjCCategoryDecl;
+    case Decl::ObjCCategoryImpl:   return CXCursor_ObjCCategoryImplDecl;
+    case Decl::ObjCImplementation: return CXCursor_ObjCImplementationDecl;
+
+    case Decl::ObjCInterface:      return CXCursor_ObjCInterfaceDecl;
+    case Decl::ObjCIvar:           return CXCursor_ObjCIvarDecl; 
+    case Decl::ObjCMethod:
+      return cast<ObjCMethodDecl>(D)->isInstanceMethod()
+      ? CXCursor_ObjCInstanceMethodDecl : CXCursor_ObjCClassMethodDecl;
+    case Decl::CXXMethod:          return CXCursor_CXXMethod;
+    case Decl::CXXConstructor:     return CXCursor_Constructor;
+    case Decl::CXXDestructor:      return CXCursor_Destructor;
+    case Decl::CXXConversion:      return CXCursor_ConversionFunction;
+    case Decl::ObjCProperty:       return CXCursor_ObjCPropertyDecl;
+    case Decl::ObjCProtocol:       return CXCursor_ObjCProtocolDecl;
+    case Decl::ParmVar:            return CXCursor_ParmDecl;
+    case Decl::Typedef:            return CXCursor_TypedefDecl;
+    case Decl::TypeAlias:          return CXCursor_TypeAliasDecl;
+    case Decl::Var:                return CXCursor_VarDecl;
+    case Decl::Namespace:          return CXCursor_Namespace;
+    case Decl::NamespaceAlias:     return CXCursor_NamespaceAlias;
+    case Decl::TemplateTypeParm:   return CXCursor_TemplateTypeParameter;
+    case Decl::NonTypeTemplateParm:return CXCursor_NonTypeTemplateParameter;
+    case Decl::TemplateTemplateParm:return CXCursor_TemplateTemplateParameter;
+    case Decl::FunctionTemplate:   return CXCursor_FunctionTemplate;
+    case Decl::ClassTemplate:      return CXCursor_ClassTemplate;
+    case Decl::AccessSpec:         return CXCursor_CXXAccessSpecifier;
+    case Decl::ClassTemplatePartialSpecialization:
+      return CXCursor_ClassTemplatePartialSpecialization;
+    case Decl::UsingDirective:     return CXCursor_UsingDirective;
+      
+    case Decl::Using:
+    case Decl::UnresolvedUsingValue:
+    case Decl::UnresolvedUsingTypename: 
+      return CXCursor_UsingDeclaration;
+      
+    case Decl::ObjCPropertyImpl:
+      switch (cast<ObjCPropertyImplDecl>(D)->getPropertyImplementation()) {
+      case ObjCPropertyImplDecl::Dynamic:
+        return CXCursor_ObjCDynamicDecl;
+          
+      case ObjCPropertyImplDecl::Synthesize:
+        return CXCursor_ObjCSynthesizeDecl;
+      }
+      
+    default:
+      if (TagDecl *TD = dyn_cast<TagDecl>(D)) {
+        switch (TD->getTagKind()) {
+          case TTK_Struct: return CXCursor_StructDecl;
+          case TTK_Class:  return CXCursor_ClassDecl;
+          case TTK_Union:  return CXCursor_UnionDecl;
+          case TTK_Enum:   return CXCursor_EnumDecl;
+        }
+      }
+  }
+  
+  return CXCursor_UnexposedDecl;
+}
+
+static void AddMacroResults(Preprocessor &PP, ResultBuilder &Results,
+                            bool TargetTypeIsPointer = false) {
+  typedef CodeCompletionResult Result;
+  
+  Results.EnterNewScope();
+  
+  for (Preprocessor::macro_iterator M = PP.macro_begin(), 
+                                 MEnd = PP.macro_end();
+       M != MEnd; ++M) {
+    Results.AddResult(Result(M->first, 
+                             getMacroUsagePriority(M->first->getName(),
+                                                   PP.getLangOpts(),
+                                                   TargetTypeIsPointer)));
+  }
+  
+  Results.ExitScope();
+  
+}
+
+static void AddPrettyFunctionResults(const LangOptions &LangOpts, 
+                                     ResultBuilder &Results) {
+  typedef CodeCompletionResult Result;
+  
+  Results.EnterNewScope();
+  
+  Results.AddResult(Result("__PRETTY_FUNCTION__", CCP_Constant));
+  Results.AddResult(Result("__FUNCTION__", CCP_Constant));
+  if (LangOpts.C99 || LangOpts.CPlusPlus0x)
+    Results.AddResult(Result("__func__", CCP_Constant));
+  Results.ExitScope();
+}
+
+static void HandleCodeCompleteResults(Sema *S,
+                                      CodeCompleteConsumer *CodeCompleter,
+                                      CodeCompletionContext Context,
+                                      CodeCompletionResult *Results,
+                                      unsigned NumResults) {
+  if (CodeCompleter)
+    CodeCompleter->ProcessCodeCompleteResults(*S, Context, Results, NumResults);
+}
+
+static enum CodeCompletionContext::Kind mapCodeCompletionContext(Sema &S, 
+                                            Sema::ParserCompletionContext PCC) {
+  switch (PCC) {
+  case Sema::PCC_Namespace:
+    return CodeCompletionContext::CCC_TopLevel;
+      
+  case Sema::PCC_Class:
+    return CodeCompletionContext::CCC_ClassStructUnion;
+
+  case Sema::PCC_ObjCInterface:
+    return CodeCompletionContext::CCC_ObjCInterface;
+      
+  case Sema::PCC_ObjCImplementation:
+    return CodeCompletionContext::CCC_ObjCImplementation;
+
+  case Sema::PCC_ObjCInstanceVariableList:
+    return CodeCompletionContext::CCC_ObjCIvarList;
+      
+  case Sema::PCC_Template:
+  case Sema::PCC_MemberTemplate:
+    if (S.CurContext->isFileContext())
+      return CodeCompletionContext::CCC_TopLevel;
+    if (S.CurContext->isRecord())
+      return CodeCompletionContext::CCC_ClassStructUnion;
+    return CodeCompletionContext::CCC_Other;
+      
+  case Sema::PCC_RecoveryInFunction:
+    return CodeCompletionContext::CCC_Recovery;
+
+  case Sema::PCC_ForInit:
+    if (S.getLangOpts().CPlusPlus || S.getLangOpts().C99 ||
+        S.getLangOpts().ObjC1)
+      return CodeCompletionContext::CCC_ParenthesizedExpression;
+    else
+      return CodeCompletionContext::CCC_Expression;
+
+  case Sema::PCC_Expression:
+  case Sema::PCC_Condition:
+    return CodeCompletionContext::CCC_Expression;
+      
+  case Sema::PCC_Statement:
+    return CodeCompletionContext::CCC_Statement;
+
+  case Sema::PCC_Type:
+    return CodeCompletionContext::CCC_Type;
+
+  case Sema::PCC_ParenthesizedExpression:
+    return CodeCompletionContext::CCC_ParenthesizedExpression;
+      
+  case Sema::PCC_LocalDeclarationSpecifiers:
+    return CodeCompletionContext::CCC_Type;
+  }
+
+  llvm_unreachable("Invalid ParserCompletionContext!");
+}
+
+/// \brief If we're in a C++ virtual member function, add completion results
+/// that invoke the functions we override, since it's common to invoke the 
+/// overridden function as well as adding new functionality.
+///
+/// \param S The semantic analysis object for which we are generating results.
+///
+/// \param InContext This context in which the nested-name-specifier preceding
+/// the code-completion point 
+static void MaybeAddOverrideCalls(Sema &S, DeclContext *InContext,
+                                  ResultBuilder &Results) {
+  // Look through blocks.
+  DeclContext *CurContext = S.CurContext;
+  while (isa<BlockDecl>(CurContext))
+    CurContext = CurContext->getParent();
+  
+  
+  CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(CurContext);
+  if (!Method || !Method->isVirtual())
+    return;
+  
+  // We need to have names for all of the parameters, if we're going to 
+  // generate a forwarding call.
+  for (CXXMethodDecl::param_iterator P = Method->param_begin(),
+                                  PEnd = Method->param_end();
+       P != PEnd;
+       ++P) {
+    if (!(*P)->getDeclName())
+      return;
+  }
+
+  PrintingPolicy Policy = getCompletionPrintingPolicy(S);
+  for (CXXMethodDecl::method_iterator M = Method->begin_overridden_methods(),
+                                   MEnd = Method->end_overridden_methods();
+       M != MEnd; ++M) {
+    CodeCompletionBuilder Builder(Results.getAllocator(),
+                                  Results.getCodeCompletionTUInfo());
+    CXXMethodDecl *Overridden = const_cast<CXXMethodDecl *>(*M);
+    if (Overridden->getCanonicalDecl() == Method->getCanonicalDecl())
+      continue;
+        
+    // If we need a nested-name-specifier, add one now.
+    if (!InContext) {
+      NestedNameSpecifier *NNS
+        = getRequiredQualification(S.Context, CurContext,
+                                   Overridden->getDeclContext());
+      if (NNS) {
+        std::string Str;
+        llvm::raw_string_ostream OS(Str);
+        NNS->print(OS, Policy);
+        Builder.AddTextChunk(Results.getAllocator().CopyString(OS.str()));
+      }
+    } else if (!InContext->Equals(Overridden->getDeclContext()))
+      continue;
+    
+    Builder.AddTypedTextChunk(Results.getAllocator().CopyString( 
+                                         Overridden->getNameAsString()));
+    Builder.AddChunk(CodeCompletionString::CK_LeftParen);
+    bool FirstParam = true;
+    for (CXXMethodDecl::param_iterator P = Method->param_begin(),
+                                    PEnd = Method->param_end();
+         P != PEnd; ++P) {
+      if (FirstParam)
+        FirstParam = false;
+      else
+        Builder.AddChunk(CodeCompletionString::CK_Comma);
+
+      Builder.AddPlaceholderChunk(Results.getAllocator().CopyString( 
+                                        (*P)->getIdentifier()->getName()));
+    }
+    Builder.AddChunk(CodeCompletionString::CK_RightParen);
+    Results.AddResult(CodeCompletionResult(Builder.TakeString(),
+                                           CCP_SuperCompletion,
+                                           CXCursor_CXXMethod,
+                                           CXAvailability_Available,
+                                           Overridden));
+    Results.Ignore(Overridden);
+  }
+}
+
+void Sema::CodeCompleteModuleImport(SourceLocation ImportLoc, 
+                                    ModuleIdPath Path) {
+  typedef CodeCompletionResult Result;
+  ResultBuilder Results(*this, CodeCompleter->getAllocator(),
+                        CodeCompleter->getCodeCompletionTUInfo(),
+                        CodeCompletionContext::CCC_Other);
+  Results.EnterNewScope();
+  
+  CodeCompletionAllocator &Allocator = Results.getAllocator();
+  CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo());
+  typedef CodeCompletionResult Result;
+  if (Path.empty()) {
+    // Enumerate all top-level modules.
+    llvm::SmallVector<Module *, 8> Modules;
+    PP.getHeaderSearchInfo().collectAllModules(Modules);
+    for (unsigned I = 0, N = Modules.size(); I != N; ++I) {
+      Builder.AddTypedTextChunk(
+        Builder.getAllocator().CopyString(Modules[I]->Name));
+      Results.AddResult(Result(Builder.TakeString(),
+                               CCP_Declaration, 
+                               CXCursor_NotImplemented,
+                               Modules[I]->isAvailable()
+                                 ? CXAvailability_Available
+                                  : CXAvailability_NotAvailable));
+    }
+  } else {
+    // Load the named module.
+    Module *Mod = PP.getModuleLoader().loadModule(ImportLoc, Path,
+                                                  Module::AllVisible,
+                                                /*IsInclusionDirective=*/false);
+    // Enumerate submodules.
+    if (Mod) {
+      for (Module::submodule_iterator Sub = Mod->submodule_begin(), 
+                                   SubEnd = Mod->submodule_end();
+           Sub != SubEnd; ++Sub) {
+        
+        Builder.AddTypedTextChunk(
+          Builder.getAllocator().CopyString((*Sub)->Name));
+        Results.AddResult(Result(Builder.TakeString(),
+                                 CCP_Declaration, 
+                                 CXCursor_NotImplemented,
+                                 (*Sub)->isAvailable()
+                                   ? CXAvailability_Available
+                                   : CXAvailability_NotAvailable));
+      }
+    }
+  }
+  Results.ExitScope();    
+  HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
+                            Results.data(),Results.size());
+}
+
+void Sema::CodeCompleteOrdinaryName(Scope *S, 
+                                    ParserCompletionContext CompletionContext) {
+  typedef CodeCompletionResult Result;
+  ResultBuilder Results(*this, CodeCompleter->getAllocator(),
+                        CodeCompleter->getCodeCompletionTUInfo(),
+                        mapCodeCompletionContext(*this, CompletionContext));
+  Results.EnterNewScope();
+  
+  // Determine how to filter results, e.g., so that the names of
+  // values (functions, enumerators, function templates, etc.) are
+  // only allowed where we can have an expression.
+  switch (CompletionContext) {
+  case PCC_Namespace:
+  case PCC_Class:
+  case PCC_ObjCInterface:
+  case PCC_ObjCImplementation:
+  case PCC_ObjCInstanceVariableList:
+  case PCC_Template:
+  case PCC_MemberTemplate:
+  case PCC_Type:
+  case PCC_LocalDeclarationSpecifiers:
+    Results.setFilter(&ResultBuilder::IsOrdinaryNonValueName);
+    break;
+
+  case PCC_Statement:
+  case PCC_ParenthesizedExpression:
+  case PCC_Expression:
+  case PCC_ForInit:
+  case PCC_Condition:
+    if (WantTypesInContext(CompletionContext, getLangOpts()))
+      Results.setFilter(&ResultBuilder::IsOrdinaryName);
+    else
+      Results.setFilter(&ResultBuilder::IsOrdinaryNonTypeName);
+      
+    if (getLangOpts().CPlusPlus)
+      MaybeAddOverrideCalls(*this, /*InContext=*/0, Results);
+    break;
+      
+  case PCC_RecoveryInFunction:
+    // Unfiltered
+    break;
+  }
+
+  // If we are in a C++ non-static member function, check the qualifiers on
+  // the member function to filter/prioritize the results list.
+  if (CXXMethodDecl *CurMethod = dyn_cast<CXXMethodDecl>(CurContext))
+    if (CurMethod->isInstance())
+      Results.setObjectTypeQualifiers(
+                      Qualifiers::fromCVRMask(CurMethod->getTypeQualifiers()));
+  
+  CodeCompletionDeclConsumer Consumer(Results, CurContext);
+  LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
+                     CodeCompleter->includeGlobals());
+
+  AddOrdinaryNameResults(CompletionContext, S, *this, Results);
+  Results.ExitScope();
+
+  switch (CompletionContext) {
+  case PCC_ParenthesizedExpression:
+  case PCC_Expression:
+  case PCC_Statement:
+  case PCC_RecoveryInFunction:
+    if (S->getFnParent())
+      AddPrettyFunctionResults(PP.getLangOpts(), Results);        
+    break;
+    
+  case PCC_Namespace:
+  case PCC_Class:
+  case PCC_ObjCInterface:
+  case PCC_ObjCImplementation:
+  case PCC_ObjCInstanceVariableList:
+  case PCC_Template:
+  case PCC_MemberTemplate:
+  case PCC_ForInit:
+  case PCC_Condition:
+  case PCC_Type:
+  case PCC_LocalDeclarationSpecifiers:
+    break;
+  }
+  
+  if (CodeCompleter->includeMacros())
+    AddMacroResults(PP, Results);
+  
+  HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
+                            Results.data(),Results.size());
+}
+
+static void AddClassMessageCompletions(Sema &SemaRef, Scope *S, 
+                                       ParsedType Receiver,
+                                       IdentifierInfo **SelIdents,
+                                       unsigned NumSelIdents,
+                                       bool AtArgumentExpression,
+                                       bool IsSuper,
+                                       ResultBuilder &Results);
+
+void Sema::CodeCompleteDeclSpec(Scope *S, DeclSpec &DS,
+                                bool AllowNonIdentifiers,
+                                bool AllowNestedNameSpecifiers) {
+  typedef CodeCompletionResult Result;
+  ResultBuilder Results(*this, CodeCompleter->getAllocator(),
+                        CodeCompleter->getCodeCompletionTUInfo(),
+                        AllowNestedNameSpecifiers
+                          ? CodeCompletionContext::CCC_PotentiallyQualifiedName
+                          : CodeCompletionContext::CCC_Name);
+  Results.EnterNewScope();
+  
+  // Type qualifiers can come after names.
+  Results.AddResult(Result("const"));
+  Results.AddResult(Result("volatile"));
+  if (getLangOpts().C99)
+    Results.AddResult(Result("restrict"));
+
+  if (getLangOpts().CPlusPlus) {
+    if (AllowNonIdentifiers) {
+      Results.AddResult(Result("operator")); 
+    }
+    
+    // Add nested-name-specifiers.
+    if (AllowNestedNameSpecifiers) {
+      Results.allowNestedNameSpecifiers();
+      Results.setFilter(&ResultBuilder::IsImpossibleToSatisfy);
+      CodeCompletionDeclConsumer Consumer(Results, CurContext);
+      LookupVisibleDecls(S, LookupNestedNameSpecifierName, Consumer,
+                         CodeCompleter->includeGlobals());
+      Results.setFilter(0);
+    }
+  }
+  Results.ExitScope();
+
+  // If we're in a context where we might have an expression (rather than a
+  // declaration), and what we've seen so far is an Objective-C type that could
+  // be a receiver of a class message, this may be a class message send with
+  // the initial opening bracket '[' missing. Add appropriate completions.
+  if (AllowNonIdentifiers && !AllowNestedNameSpecifiers &&
+      DS.getTypeSpecType() == DeclSpec::TST_typename &&
+      DS.getStorageClassSpecAsWritten() == DeclSpec::SCS_unspecified &&
+      !DS.isThreadSpecified() && !DS.isExternInLinkageSpec() &&
+      DS.getTypeSpecComplex() == DeclSpec::TSC_unspecified &&
+      DS.getTypeSpecSign() == DeclSpec::TSS_unspecified &&
+      DS.getTypeQualifiers() == 0 &&
+      S && 
+      (S->getFlags() & Scope::DeclScope) != 0 &&
+      (S->getFlags() & (Scope::ClassScope | Scope::TemplateParamScope |
+                        Scope::FunctionPrototypeScope | 
+                        Scope::AtCatchScope)) == 0) {
+    ParsedType T = DS.getRepAsType();
+    if (!T.get().isNull() && T.get()->isObjCObjectOrInterfaceType())
+      AddClassMessageCompletions(*this, S, T, 0, 0, false, false, Results); 
+  }
+
+  // Note that we intentionally suppress macro results here, since we do not
+  // encourage using macros to produce the names of entities.
+
+  HandleCodeCompleteResults(this, CodeCompleter, 
+                            Results.getCompletionContext(),
+                            Results.data(), Results.size());
+}
+
+struct Sema::CodeCompleteExpressionData {
+  CodeCompleteExpressionData(QualType PreferredType = QualType()) 
+    : PreferredType(PreferredType), IntegralConstantExpression(false),
+      ObjCCollection(false) { }
+  
+  QualType PreferredType;
+  bool IntegralConstantExpression;
+  bool ObjCCollection;
+  SmallVector<Decl *, 4> IgnoreDecls;
+};
+
+/// \brief Perform code-completion in an expression context when we know what
+/// type we're looking for.
+///
+/// \param IntegralConstantExpression Only permit integral constant 
+/// expressions.
+void Sema::CodeCompleteExpression(Scope *S, 
+                                  const CodeCompleteExpressionData &Data) {
+  typedef CodeCompletionResult Result;
+  ResultBuilder Results(*this, CodeCompleter->getAllocator(),
+                        CodeCompleter->getCodeCompletionTUInfo(),
+                        CodeCompletionContext::CCC_Expression);
+  if (Data.ObjCCollection)
+    Results.setFilter(&ResultBuilder::IsObjCCollection);
+  else if (Data.IntegralConstantExpression)
+    Results.setFilter(&ResultBuilder::IsIntegralConstantValue);
+  else if (WantTypesInContext(PCC_Expression, getLangOpts()))
+    Results.setFilter(&ResultBuilder::IsOrdinaryName);
+  else
+    Results.setFilter(&ResultBuilder::IsOrdinaryNonTypeName);
+
+  if (!Data.PreferredType.isNull())
+    Results.setPreferredType(Data.PreferredType.getNonReferenceType());
+  
+  // Ignore any declarations that we were told that we don't care about.
+  for (unsigned I = 0, N = Data.IgnoreDecls.size(); I != N; ++I)
+    Results.Ignore(Data.IgnoreDecls[I]);
+  
+  CodeCompletionDeclConsumer Consumer(Results, CurContext);
+  LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
+                     CodeCompleter->includeGlobals());
+  
+  Results.EnterNewScope();
+  AddOrdinaryNameResults(PCC_Expression, S, *this, Results);
+  Results.ExitScope();
+  
+  bool PreferredTypeIsPointer = false;
+  if (!Data.PreferredType.isNull())
+    PreferredTypeIsPointer = Data.PreferredType->isAnyPointerType()
+      || Data.PreferredType->isMemberPointerType() 
+      || Data.PreferredType->isBlockPointerType();
+  
+  if (S->getFnParent() && 
+      !Data.ObjCCollection && 
+      !Data.IntegralConstantExpression)
+    AddPrettyFunctionResults(PP.getLangOpts(), Results);        
+
+  if (CodeCompleter->includeMacros())
+    AddMacroResults(PP, Results, PreferredTypeIsPointer);
+  HandleCodeCompleteResults(this, CodeCompleter, 
+                CodeCompletionContext(CodeCompletionContext::CCC_Expression, 
+                                      Data.PreferredType),
+                            Results.data(),Results.size());
+}
+
+void Sema::CodeCompletePostfixExpression(Scope *S, ExprResult E) {
+  if (E.isInvalid())
+    CodeCompleteOrdinaryName(S, PCC_RecoveryInFunction);
+  else if (getLangOpts().ObjC1)
+    CodeCompleteObjCInstanceMessage(S, E.take(), 0, 0, false);
+}
+
+/// \brief The set of properties that have already been added, referenced by
+/// property name.
+typedef llvm::SmallPtrSet<IdentifierInfo*, 16> AddedPropertiesSet;
+
+static void AddObjCProperties(ObjCContainerDecl *Container, 
+                              bool AllowCategories,
+                              bool AllowNullaryMethods,
+                              DeclContext *CurContext,
+                              AddedPropertiesSet &AddedProperties,
+                              ResultBuilder &Results) {
+  typedef CodeCompletionResult Result;
+
+  // Add properties in this container.
+  for (ObjCContainerDecl::prop_iterator P = Container->prop_begin(),
+                                     PEnd = Container->prop_end();
+       P != PEnd;
+       ++P) {
+    if (AddedProperties.insert(P->getIdentifier()))
+      Results.MaybeAddResult(Result(*P, 0), CurContext);
+  }
+  
+  // Add nullary methods
+  if (AllowNullaryMethods) {
+    ASTContext &Context = Container->getASTContext();
+    PrintingPolicy Policy = getCompletionPrintingPolicy(Results.getSema());
+    for (ObjCContainerDecl::method_iterator M = Container->meth_begin(),
+                                         MEnd = Container->meth_end();
+         M != MEnd; ++M) {
+      if (M->getSelector().isUnarySelector())
+        if (IdentifierInfo *Name = M->getSelector().getIdentifierInfoForSlot(0))
+          if (AddedProperties.insert(Name)) {
+            CodeCompletionBuilder Builder(Results.getAllocator(),
+                                          Results.getCodeCompletionTUInfo());
+            AddResultTypeChunk(Context, Policy, *M, Builder);
+            Builder.AddTypedTextChunk(
+                            Results.getAllocator().CopyString(Name->getName()));
+            
+            Results.MaybeAddResult(Result(Builder.TakeString(), *M,
+                                  CCP_MemberDeclaration + CCD_MethodAsProperty),
+                                          CurContext);
+          }
+    }
+  }
+    
+  
+  // Add properties in referenced protocols.
+  if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
+    for (ObjCProtocolDecl::protocol_iterator P = Protocol->protocol_begin(),
+                                          PEnd = Protocol->protocol_end();
+         P != PEnd; ++P)
+      AddObjCProperties(*P, AllowCategories, AllowNullaryMethods, CurContext, 
+                        AddedProperties, Results);
+  } else if (ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container)){
+    if (AllowCategories) {
+      // Look through categories.
+      for (ObjCCategoryDecl *Category = IFace->getCategoryList();
+           Category; Category = Category->getNextClassCategory())
+        AddObjCProperties(Category, AllowCategories, AllowNullaryMethods, 
+                          CurContext, AddedProperties, Results);
+    }
+    
+    // Look through protocols.
+    for (ObjCInterfaceDecl::all_protocol_iterator
+         I = IFace->all_referenced_protocol_begin(),
+         E = IFace->all_referenced_protocol_end(); I != E; ++I)
+      AddObjCProperties(*I, AllowCategories, AllowNullaryMethods, CurContext,
+                        AddedProperties, Results);
+    
+    // Look in the superclass.
+    if (IFace->getSuperClass())
+      AddObjCProperties(IFace->getSuperClass(), AllowCategories, 
+                        AllowNullaryMethods, CurContext, 
+                        AddedProperties, Results);
+  } else if (const ObjCCategoryDecl *Category
+                                    = dyn_cast<ObjCCategoryDecl>(Container)) {
+    // Look through protocols.
+    for (ObjCCategoryDecl::protocol_iterator P = Category->protocol_begin(),
+                                          PEnd = Category->protocol_end(); 
+         P != PEnd; ++P)
+      AddObjCProperties(*P, AllowCategories, AllowNullaryMethods, CurContext,
+                        AddedProperties, Results);
+  }
+}
+
+void Sema::CodeCompleteMemberReferenceExpr(Scope *S, Expr *Base,
+                                           SourceLocation OpLoc,
+                                           bool IsArrow) {
+  if (!Base || !CodeCompleter)
+    return;
+  
+  ExprResult ConvertedBase = PerformMemberExprBaseConversion(Base, IsArrow);
+  if (ConvertedBase.isInvalid())
+    return;
+  Base = ConvertedBase.get();
+
+  typedef CodeCompletionResult Result;
+  
+  QualType BaseType = Base->getType();
+
+  if (IsArrow) {
+    if (const PointerType *Ptr = BaseType->getAs<PointerType>())
+      BaseType = Ptr->getPointeeType();
+    else if (BaseType->isObjCObjectPointerType())
+      /*Do nothing*/ ;
+    else
+      return;
+  }
+  
+  enum CodeCompletionContext::Kind contextKind;
+  
+  if (IsArrow) {
+    contextKind = CodeCompletionContext::CCC_ArrowMemberAccess;
+  }
+  else {
+    if (BaseType->isObjCObjectPointerType() ||
+        BaseType->isObjCObjectOrInterfaceType()) {
+      contextKind = CodeCompletionContext::CCC_ObjCPropertyAccess;
+    }
+    else {
+      contextKind = CodeCompletionContext::CCC_DotMemberAccess;
+    }
+  }
+  
+  ResultBuilder Results(*this, CodeCompleter->getAllocator(),
+                        CodeCompleter->getCodeCompletionTUInfo(),
+                  CodeCompletionContext(contextKind,
+                                        BaseType),
+                        &ResultBuilder::IsMember);
+  Results.EnterNewScope();
+  if (const RecordType *Record = BaseType->getAs<RecordType>()) {
+    // Indicate that we are performing a member access, and the cv-qualifiers
+    // for the base object type.
+    Results.setObjectTypeQualifiers(BaseType.getQualifiers());
+    
+    // Access to a C/C++ class, struct, or union.
+    Results.allowNestedNameSpecifiers();
+    CodeCompletionDeclConsumer Consumer(Results, CurContext);
+    LookupVisibleDecls(Record->getDecl(), LookupMemberName, Consumer,
+                       CodeCompleter->includeGlobals());
+
+    if (getLangOpts().CPlusPlus) {
+      if (!Results.empty()) {
+        // The "template" keyword can follow "->" or "." in the grammar.
+        // However, we only want to suggest the template keyword if something
+        // is dependent.
+        bool IsDependent = BaseType->isDependentType();
+        if (!IsDependent) {
+          for (Scope *DepScope = S; DepScope; DepScope = DepScope->getParent())
+            if (DeclContext *Ctx = (DeclContext *)DepScope->getEntity()) {
+              IsDependent = Ctx->isDependentContext();
+              break;
+            }
+        }
+
+        if (IsDependent)
+          Results.AddResult(Result("template"));
+      }
+    }
+  } else if (!IsArrow && BaseType->getAsObjCInterfacePointerType()) {
+    // Objective-C property reference.
+    AddedPropertiesSet AddedProperties;
+    
+    // Add property results based on our interface.
+    const ObjCObjectPointerType *ObjCPtr
+      = BaseType->getAsObjCInterfacePointerType();
+    assert(ObjCPtr && "Non-NULL pointer guaranteed above!");
+    AddObjCProperties(ObjCPtr->getInterfaceDecl(), true, 
+                      /*AllowNullaryMethods=*/true, CurContext, 
+                      AddedProperties, Results);
+    
+    // Add properties from the protocols in a qualified interface.
+    for (ObjCObjectPointerType::qual_iterator I = ObjCPtr->qual_begin(),
+                                              E = ObjCPtr->qual_end();
+         I != E; ++I)
+      AddObjCProperties(*I, true, /*AllowNullaryMethods=*/true, CurContext, 
+                        AddedProperties, Results);
+  } else if ((IsArrow && BaseType->isObjCObjectPointerType()) ||
+             (!IsArrow && BaseType->isObjCObjectType())) {
+    // Objective-C instance variable access.
+    ObjCInterfaceDecl *Class = 0;
+    if (const ObjCObjectPointerType *ObjCPtr
+                                    = BaseType->getAs<ObjCObjectPointerType>())
+      Class = ObjCPtr->getInterfaceDecl();
+    else
+      Class = BaseType->getAs<ObjCObjectType>()->getInterface();
+    
+    // Add all ivars from this class and its superclasses.
+    if (Class) {
+      CodeCompletionDeclConsumer Consumer(Results, CurContext);
+      Results.setFilter(&ResultBuilder::IsObjCIvar);
+      LookupVisibleDecls(Class, LookupMemberName, Consumer,
+                         CodeCompleter->includeGlobals());
+    }
+  }
+  
+  // FIXME: How do we cope with isa?
+  
+  Results.ExitScope();
+
+  // Hand off the results found for code completion.
+  HandleCodeCompleteResults(this, CodeCompleter, 
+                            Results.getCompletionContext(),
+                            Results.data(),Results.size());
+}
+
+void Sema::CodeCompleteTag(Scope *S, unsigned TagSpec) {
+  if (!CodeCompleter)
+    return;
+  
+  typedef CodeCompletionResult Result;
+  ResultBuilder::LookupFilter Filter = 0;
+  enum CodeCompletionContext::Kind ContextKind
+    = CodeCompletionContext::CCC_Other;
+  switch ((DeclSpec::TST)TagSpec) {
+  case DeclSpec::TST_enum:
+    Filter = &ResultBuilder::IsEnum;
+    ContextKind = CodeCompletionContext::CCC_EnumTag;
+    break;
+    
+  case DeclSpec::TST_union:
+    Filter = &ResultBuilder::IsUnion;
+    ContextKind = CodeCompletionContext::CCC_UnionTag;
+    break;
+    
+  case DeclSpec::TST_struct:
+  case DeclSpec::TST_class:
+    Filter = &ResultBuilder::IsClassOrStruct;
+    ContextKind = CodeCompletionContext::CCC_ClassOrStructTag;
+    break;
+    
+  default:
+    llvm_unreachable("Unknown type specifier kind in CodeCompleteTag");
+  }
+  
+  ResultBuilder Results(*this, CodeCompleter->getAllocator(),
+                        CodeCompleter->getCodeCompletionTUInfo(), ContextKind);
+  CodeCompletionDeclConsumer Consumer(Results, CurContext);
+
+  // First pass: look for tags.
+  Results.setFilter(Filter);
+  LookupVisibleDecls(S, LookupTagName, Consumer,
+                     CodeCompleter->includeGlobals());
+
+  if (CodeCompleter->includeGlobals()) {
+    // Second pass: look for nested name specifiers.
+    Results.setFilter(&ResultBuilder::IsNestedNameSpecifier);
+    LookupVisibleDecls(S, LookupNestedNameSpecifierName, Consumer);
+  }
+  
+  HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
+                            Results.data(),Results.size());
+}
+
+void Sema::CodeCompleteTypeQualifiers(DeclSpec &DS) {
+  ResultBuilder Results(*this, CodeCompleter->getAllocator(),
+                        CodeCompleter->getCodeCompletionTUInfo(),
+                        CodeCompletionContext::CCC_TypeQualifiers);
+  Results.EnterNewScope();
+  if (!(DS.getTypeQualifiers() & DeclSpec::TQ_const))
+    Results.AddResult("const");
+  if (!(DS.getTypeQualifiers() & DeclSpec::TQ_volatile))
+    Results.AddResult("volatile");
+  if (getLangOpts().C99 &&
+      !(DS.getTypeQualifiers() & DeclSpec::TQ_restrict))
+    Results.AddResult("restrict");
+  Results.ExitScope();
+  HandleCodeCompleteResults(this, CodeCompleter, 
+                            Results.getCompletionContext(),
+                            Results.data(), Results.size());
+}
+
+void Sema::CodeCompleteCase(Scope *S) {
+  if (getCurFunction()->SwitchStack.empty() || !CodeCompleter)
+    return;
+
+  SwitchStmt *Switch = getCurFunction()->SwitchStack.back();
+  QualType type = Switch->getCond()->IgnoreImplicit()->getType();
+  if (!type->isEnumeralType()) {
+    CodeCompleteExpressionData Data(type);
+    Data.IntegralConstantExpression = true;
+    CodeCompleteExpression(S, Data);
+    return;
+  }
+  
+  // Code-complete the cases of a switch statement over an enumeration type
+  // by providing the list of 
+  EnumDecl *Enum = type->castAs<EnumType>()->getDecl();
+  
+  // Determine which enumerators we have already seen in the switch statement.
+  // FIXME: Ideally, we would also be able to look *past* the code-completion
+  // token, in case we are code-completing in the middle of the switch and not
+  // at the end. However, we aren't able to do so at the moment.
+  llvm::SmallPtrSet<EnumConstantDecl *, 8> EnumeratorsSeen;
+  NestedNameSpecifier *Qualifier = 0;
+  for (SwitchCase *SC = Switch->getSwitchCaseList(); SC; 
+       SC = SC->getNextSwitchCase()) {
+    CaseStmt *Case = dyn_cast<CaseStmt>(SC);
+    if (!Case)
+      continue;
+
+    Expr *CaseVal = Case->getLHS()->IgnoreParenCasts();
+    if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(CaseVal))
+      if (EnumConstantDecl *Enumerator 
+            = dyn_cast<EnumConstantDecl>(DRE->getDecl())) {
+        // We look into the AST of the case statement to determine which 
+        // enumerator was named. Alternatively, we could compute the value of 
+        // the integral constant expression, then compare it against the
+        // values of each enumerator. However, value-based approach would not 
+        // work as well with C++ templates where enumerators declared within a 
+        // template are type- and value-dependent.
+        EnumeratorsSeen.insert(Enumerator);
+        
+        // If this is a qualified-id, keep track of the nested-name-specifier
+        // so that we can reproduce it as part of code completion, e.g.,
+        //
+        //   switch (TagD.getKind()) {
+        //     case TagDecl::TK_enum:
+        //       break;
+        //     case XXX
+        //
+        // At the XXX, our completions are TagDecl::TK_union,
+        // TagDecl::TK_struct, and TagDecl::TK_class, rather than TK_union,
+        // TK_struct, and TK_class.
+        Qualifier = DRE->getQualifier();
+      }
+  }
+  
+  if (getLangOpts().CPlusPlus && !Qualifier && EnumeratorsSeen.empty()) {
+    // If there are no prior enumerators in C++, check whether we have to 
+    // qualify the names of the enumerators that we suggest, because they
+    // may not be visible in this scope.
+    Qualifier = getRequiredQualification(Context, CurContext, Enum);
+  }
+  
+  // Add any enumerators that have not yet been mentioned.
+  ResultBuilder Results(*this, CodeCompleter->getAllocator(),
+                        CodeCompleter->getCodeCompletionTUInfo(),
+                        CodeCompletionContext::CCC_Expression);
+  Results.EnterNewScope();
+  for (EnumDecl::enumerator_iterator E = Enum->enumerator_begin(),
+                                  EEnd = Enum->enumerator_end();
+       E != EEnd; ++E) {
+    if (EnumeratorsSeen.count(*E))
+      continue;
+    
+    CodeCompletionResult R(*E, Qualifier);
+    R.Priority = CCP_EnumInCase;
+    Results.AddResult(R, CurContext, 0, false);
+  }
+  Results.ExitScope();
+
+  //We need to make sure we're setting the right context, 
+  //so only say we include macros if the code completer says we do
+  enum CodeCompletionContext::Kind kind = CodeCompletionContext::CCC_Other;
+  if (CodeCompleter->includeMacros()) {
+    AddMacroResults(PP, Results);
+    kind = CodeCompletionContext::CCC_OtherWithMacros;
+  }
+  
+  HandleCodeCompleteResults(this, CodeCompleter, 
+                            kind,
+                            Results.data(),Results.size());
+}
+
+namespace {
+  struct IsBetterOverloadCandidate {
+    Sema &S;
+    SourceLocation Loc;
+    
+  public:
+    explicit IsBetterOverloadCandidate(Sema &S, SourceLocation Loc)
+      : S(S), Loc(Loc) { }
+    
+    bool 
+    operator()(const OverloadCandidate &X, const OverloadCandidate &Y) const {
+      return isBetterOverloadCandidate(S, X, Y, Loc);
+    }
+  };
+}
+
+static bool anyNullArguments(llvm::ArrayRef<Expr*> Args) {
+  if (Args.size() && !Args.data())
+    return true;
+
+  for (unsigned I = 0; I != Args.size(); ++I)
+    if (!Args[I])
+      return true;
+
+  return false;
+}
+
+void Sema::CodeCompleteCall(Scope *S, Expr *FnIn,
+                            llvm::ArrayRef<Expr *> Args) {
+  if (!CodeCompleter)
+    return;
+
+  // When we're code-completing for a call, we fall back to ordinary
+  // name code-completion whenever we can't produce specific
+  // results. We may want to revisit this strategy in the future,
+  // e.g., by merging the two kinds of results.
+
+  Expr *Fn = (Expr *)FnIn;
+
+  // Ignore type-dependent call expressions entirely.
+  if (!Fn || Fn->isTypeDependent() || anyNullArguments(Args) ||
+      Expr::hasAnyTypeDependentArguments(Args)) {
+    CodeCompleteOrdinaryName(S, PCC_Expression);
+    return;
+  }
+
+  // Build an overload candidate set based on the functions we find.
+  SourceLocation Loc = Fn->getExprLoc();
+  OverloadCandidateSet CandidateSet(Loc);
+
+  // FIXME: What if we're calling something that isn't a function declaration?
+  // FIXME: What if we're calling a pseudo-destructor?
+  // FIXME: What if we're calling a member function?
+  
+  typedef CodeCompleteConsumer::OverloadCandidate ResultCandidate;
+  SmallVector<ResultCandidate, 8> Results;
+
+  Expr *NakedFn = Fn->IgnoreParenCasts();
+  if (UnresolvedLookupExpr *ULE = dyn_cast<UnresolvedLookupExpr>(NakedFn))
+    AddOverloadedCallCandidates(ULE, Args, CandidateSet,
+                                /*PartialOverloading=*/ true);
+  else if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(NakedFn)) {
+    FunctionDecl *FDecl = dyn_cast<FunctionDecl>(DRE->getDecl());
+    if (FDecl) {
+      if (!getLangOpts().CPlusPlus || 
+          !FDecl->getType()->getAs<FunctionProtoType>())
+        Results.push_back(ResultCandidate(FDecl));
+      else
+        // FIXME: access?
+        AddOverloadCandidate(FDecl, DeclAccessPair::make(FDecl, AS_none), Args,
+                             CandidateSet, false, /*PartialOverloading*/true);
+    }
+  }
+  
+  QualType ParamType;
+  
+  if (!CandidateSet.empty()) {
+    // Sort the overload candidate set by placing the best overloads first.
+    std::stable_sort(CandidateSet.begin(), CandidateSet.end(),
+                     IsBetterOverloadCandidate(*this, Loc));
+  
+    // Add the remaining viable overload candidates as code-completion reslults.
+    for (OverloadCandidateSet::iterator Cand = CandidateSet.begin(),
+                                     CandEnd = CandidateSet.end();
+         Cand != CandEnd; ++Cand) {
+      if (Cand->Viable)
+        Results.push_back(ResultCandidate(Cand->Function));
+    }
+
+    // From the viable candidates, try to determine the type of this parameter.
+    for (unsigned I = 0, N = Results.size(); I != N; ++I) {
+      if (const FunctionType *FType = Results[I].getFunctionType())
+        if (const FunctionProtoType *Proto = dyn_cast<FunctionProtoType>(FType))
+          if (Args.size() < Proto->getNumArgs()) {
+            if (ParamType.isNull())
+              ParamType = Proto->getArgType(Args.size());
+            else if (!Context.hasSameUnqualifiedType(
+                                            ParamType.getNonReferenceType(),
+                       Proto->getArgType(Args.size()).getNonReferenceType())) {
+              ParamType = QualType();
+              break;
+            }
+          }
+    }
+  } else {
+    // Try to determine the parameter type from the type of the expression
+    // being called.
+    QualType FunctionType = Fn->getType();
+    if (const PointerType *Ptr = FunctionType->getAs<PointerType>())
+      FunctionType = Ptr->getPointeeType();
+    else if (const BlockPointerType *BlockPtr
+                                    = FunctionType->getAs<BlockPointerType>())
+      FunctionType = BlockPtr->getPointeeType();
+    else if (const MemberPointerType *MemPtr
+                                    = FunctionType->getAs<MemberPointerType>())
+      FunctionType = MemPtr->getPointeeType();
+    
+    if (const FunctionProtoType *Proto
+                                  = FunctionType->getAs<FunctionProtoType>()) {
+      if (Args.size() < Proto->getNumArgs())
+        ParamType = Proto->getArgType(Args.size());
+    }
+  }
+
+  if (ParamType.isNull())
+    CodeCompleteOrdinaryName(S, PCC_Expression);
+  else
+    CodeCompleteExpression(S, ParamType);
+  
+  if (!Results.empty())
+    CodeCompleter->ProcessOverloadCandidates(*this, Args.size(), Results.data(),
+                                             Results.size());
+}
+
+void Sema::CodeCompleteInitializer(Scope *S, Decl *D) {
+  ValueDecl *VD = dyn_cast_or_null<ValueDecl>(D);
+  if (!VD) {
+    CodeCompleteOrdinaryName(S, PCC_Expression);
+    return;
+  }
+  
+  CodeCompleteExpression(S, VD->getType());
+}
+
+void Sema::CodeCompleteReturn(Scope *S) {
+  QualType ResultType;
+  if (isa<BlockDecl>(CurContext)) {
+    if (BlockScopeInfo *BSI = getCurBlock())
+      ResultType = BSI->ReturnType;
+  } else if (FunctionDecl *Function = dyn_cast<FunctionDecl>(CurContext))
+    ResultType = Function->getResultType();
+  else if (ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(CurContext))
+    ResultType = Method->getResultType();
+  
+  if (ResultType.isNull())
+    CodeCompleteOrdinaryName(S, PCC_Expression);
+  else
+    CodeCompleteExpression(S, ResultType);
+}
+
+void Sema::CodeCompleteAfterIf(Scope *S) {
+  typedef CodeCompletionResult Result;
+  ResultBuilder Results(*this, CodeCompleter->getAllocator(),
+                        CodeCompleter->getCodeCompletionTUInfo(),
+                        mapCodeCompletionContext(*this, PCC_Statement));
+  Results.setFilter(&ResultBuilder::IsOrdinaryName);
+  Results.EnterNewScope();
+  
+  CodeCompletionDeclConsumer Consumer(Results, CurContext);
+  LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
+                     CodeCompleter->includeGlobals());
+  
+  AddOrdinaryNameResults(PCC_Statement, S, *this, Results);
+  
+  // "else" block
+  CodeCompletionBuilder Builder(Results.getAllocator(),
+                                Results.getCodeCompletionTUInfo());
+  Builder.AddTypedTextChunk("else");
+  if (Results.includeCodePatterns()) {
+    Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
+    Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
+    Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
+    Builder.AddPlaceholderChunk("statements");
+    Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
+    Builder.AddChunk(CodeCompletionString::CK_RightBrace);
+  }
+  Results.AddResult(Builder.TakeString());
+
+  // "else if" block
+  Builder.AddTypedTextChunk("else");
+  Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
+  Builder.AddTextChunk("if");
+  Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
+  Builder.AddChunk(CodeCompletionString::CK_LeftParen);
+  if (getLangOpts().CPlusPlus)
+    Builder.AddPlaceholderChunk("condition");
+  else
+    Builder.AddPlaceholderChunk("expression");
+  Builder.AddChunk(CodeCompletionString::CK_RightParen);
+  if (Results.includeCodePatterns()) {
+    Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
+    Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
+    Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
+    Builder.AddPlaceholderChunk("statements");
+    Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
+    Builder.AddChunk(CodeCompletionString::CK_RightBrace);
+  }
+  Results.AddResult(Builder.TakeString());
+
+  Results.ExitScope();
+  
+  if (S->getFnParent())
+    AddPrettyFunctionResults(PP.getLangOpts(), Results);        
+  
+  if (CodeCompleter->includeMacros())
+    AddMacroResults(PP, Results);
+  
+  HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
+                            Results.data(),Results.size());
+}
+
+void Sema::CodeCompleteAssignmentRHS(Scope *S, Expr *LHS) {
+  if (LHS)
+    CodeCompleteExpression(S, static_cast<Expr *>(LHS)->getType());
+  else
+    CodeCompleteOrdinaryName(S, PCC_Expression);
+}
+
+void Sema::CodeCompleteQualifiedId(Scope *S, CXXScopeSpec &SS,
+                                   bool EnteringContext) {
+  if (!SS.getScopeRep() || !CodeCompleter)
+    return;
+  
+  DeclContext *Ctx = computeDeclContext(SS, EnteringContext);
+  if (!Ctx)
+    return;
+
+  // Try to instantiate any non-dependent declaration contexts before
+  // we look in them.
+  if (!isDependentScopeSpecifier(SS) && RequireCompleteDeclContext(SS, Ctx))
+    return;
+
+  ResultBuilder Results(*this, CodeCompleter->getAllocator(),
+                        CodeCompleter->getCodeCompletionTUInfo(),
+                        CodeCompletionContext::CCC_Name);
+  Results.EnterNewScope();
+  
+  // The "template" keyword can follow "::" in the grammar, but only
+  // put it into the grammar if the nested-name-specifier is dependent.
+  NestedNameSpecifier *NNS = (NestedNameSpecifier *)SS.getScopeRep();
+  if (!Results.empty() && NNS->isDependent())
+    Results.AddResult("template");
+
+  // Add calls to overridden virtual functions, if there are any.
+  //
+  // FIXME: This isn't wonderful, because we don't know whether we're actually
+  // in a context that permits expressions. This is a general issue with
+  // qualified-id completions.
+  if (!EnteringContext)
+    MaybeAddOverrideCalls(*this, Ctx, Results);
+  Results.ExitScope();  
+  
+  CodeCompletionDeclConsumer Consumer(Results, CurContext);
+  LookupVisibleDecls(Ctx, LookupOrdinaryName, Consumer);
+
+  HandleCodeCompleteResults(this, CodeCompleter, 
+                            Results.getCompletionContext(),
+                            Results.data(),Results.size());
+}
+
+void Sema::CodeCompleteUsing(Scope *S) {
+  if (!CodeCompleter)
+    return;
+  
+  ResultBuilder Results(*this, CodeCompleter->getAllocator(),
+                        CodeCompleter->getCodeCompletionTUInfo(),
+                        CodeCompletionContext::CCC_PotentiallyQualifiedName,
+                        &ResultBuilder::IsNestedNameSpecifier);
+  Results.EnterNewScope();
+  
+  // If we aren't in class scope, we could see the "namespace" keyword.
+  if (!S->isClassScope())
+    Results.AddResult(CodeCompletionResult("namespace"));
+  
+  // After "using", we can see anything that would start a 
+  // nested-name-specifier.
+  CodeCompletionDeclConsumer Consumer(Results, CurContext);
+  LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
+                     CodeCompleter->includeGlobals());
+  Results.ExitScope();
+  
+  HandleCodeCompleteResults(this, CodeCompleter, 
+                            CodeCompletionContext::CCC_PotentiallyQualifiedName,
+                            Results.data(),Results.size());
+}
+
+void Sema::CodeCompleteUsingDirective(Scope *S) {
+  if (!CodeCompleter)
+    return;
+  
+  // After "using namespace", we expect to see a namespace name or namespace
+  // alias.
+  ResultBuilder Results(*this, CodeCompleter->getAllocator(),
+                        CodeCompleter->getCodeCompletionTUInfo(),
+                        CodeCompletionContext::CCC_Namespace,
+                        &ResultBuilder::IsNamespaceOrAlias);
+  Results.EnterNewScope();
+  CodeCompletionDeclConsumer Consumer(Results, CurContext);
+  LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
+                     CodeCompleter->includeGlobals());
+  Results.ExitScope();
+  HandleCodeCompleteResults(this, CodeCompleter, 
+                            CodeCompletionContext::CCC_Namespace,
+                            Results.data(),Results.size());
+}
+
+void Sema::CodeCompleteNamespaceDecl(Scope *S)  {
+  if (!CodeCompleter)
+    return;
+  
+  DeclContext *Ctx = (DeclContext *)S->getEntity();
+  if (!S->getParent())
+    Ctx = Context.getTranslationUnitDecl();
+  
+  bool SuppressedGlobalResults
+    = Ctx && !CodeCompleter->includeGlobals() && isa<TranslationUnitDecl>(Ctx);
+  
+  ResultBuilder Results(*this, CodeCompleter->getAllocator(),
+                        CodeCompleter->getCodeCompletionTUInfo(),
+                        SuppressedGlobalResults
+                          ? CodeCompletionContext::CCC_Namespace
+                          : CodeCompletionContext::CCC_Other,
+                        &ResultBuilder::IsNamespace);
+  
+  if (Ctx && Ctx->isFileContext() && !SuppressedGlobalResults) {
+    // We only want to see those namespaces that have already been defined
+    // within this scope, because its likely that the user is creating an
+    // extended namespace declaration. Keep track of the most recent 
+    // definition of each namespace.
+    std::map<NamespaceDecl *, NamespaceDecl *> OrigToLatest;
+    for (DeclContext::specific_decl_iterator<NamespaceDecl> 
+         NS(Ctx->decls_begin()), NSEnd(Ctx->decls_end());
+         NS != NSEnd; ++NS)
+      OrigToLatest[NS->getOriginalNamespace()] = *NS;
+    
+    // Add the most recent definition (or extended definition) of each 
+    // namespace to the list of results.
+    Results.EnterNewScope();
+    for (std::map<NamespaceDecl *, NamespaceDecl *>::iterator 
+              NS = OrigToLatest.begin(),
+           NSEnd = OrigToLatest.end();
+         NS != NSEnd; ++NS)
+      Results.AddResult(CodeCompletionResult(NS->second, 0),
+                        CurContext, 0, false);
+    Results.ExitScope();
+  }
+  
+  HandleCodeCompleteResults(this, CodeCompleter, 
+                            Results.getCompletionContext(),
+                            Results.data(),Results.size());
+}
+
+void Sema::CodeCompleteNamespaceAliasDecl(Scope *S)  {
+  if (!CodeCompleter)
+    return;
+  
+  // After "namespace", we expect to see a namespace or alias.
+  ResultBuilder Results(*this, CodeCompleter->getAllocator(),
+                        CodeCompleter->getCodeCompletionTUInfo(),
+                        CodeCompletionContext::CCC_Namespace,
+                        &ResultBuilder::IsNamespaceOrAlias);
+  CodeCompletionDeclConsumer Consumer(Results, CurContext);
+  LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
+                     CodeCompleter->includeGlobals());
+  HandleCodeCompleteResults(this, CodeCompleter, 
+                            Results.getCompletionContext(),
+                            Results.data(),Results.size());
+}
+
+void Sema::CodeCompleteOperatorName(Scope *S) {
+  if (!CodeCompleter)
+    return;
+
+  typedef CodeCompletionResult Result;
+  ResultBuilder Results(*this, CodeCompleter->getAllocator(),
+                        CodeCompleter->getCodeCompletionTUInfo(),
+                        CodeCompletionContext::CCC_Type,
+                        &ResultBuilder::IsType);
+  Results.EnterNewScope();
+  
+  // Add the names of overloadable operators.
+#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly)      \
+  if (std::strcmp(Spelling, "?"))                                                  \
+    Results.AddResult(Result(Spelling));
+#include "clang/Basic/OperatorKinds.def"
+  
+  // Add any type names visible from the current scope
+  Results.allowNestedNameSpecifiers();
+  CodeCompletionDeclConsumer Consumer(Results, CurContext);
+  LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
+                     CodeCompleter->includeGlobals());
+  
+  // Add any type specifiers
+  AddTypeSpecifierResults(getLangOpts(), Results);
+  Results.ExitScope();
+  
+  HandleCodeCompleteResults(this, CodeCompleter, 
+                            CodeCompletionContext::CCC_Type,
+                            Results.data(),Results.size());
+}
+
+void Sema::CodeCompleteConstructorInitializer(Decl *ConstructorD,
+                                              CXXCtorInitializer** Initializers,
+                                              unsigned NumInitializers) {
+  PrintingPolicy Policy = getCompletionPrintingPolicy(*this);
+  CXXConstructorDecl *Constructor
+    = static_cast<CXXConstructorDecl *>(ConstructorD);
+  if (!Constructor)
+    return;
+  
+  ResultBuilder Results(*this, CodeCompleter->getAllocator(),
+                        CodeCompleter->getCodeCompletionTUInfo(),
+                        CodeCompletionContext::CCC_PotentiallyQualifiedName);
+  Results.EnterNewScope();
+  
+  // Fill in any already-initialized fields or base classes.
+  llvm::SmallPtrSet<FieldDecl *, 4> InitializedFields;
+  llvm::SmallPtrSet<CanQualType, 4> InitializedBases;
+  for (unsigned I = 0; I != NumInitializers; ++I) {
+    if (Initializers[I]->isBaseInitializer())
+      InitializedBases.insert(
+        Context.getCanonicalType(QualType(Initializers[I]->getBaseClass(), 0)));
+    else
+      InitializedFields.insert(cast<FieldDecl>(
+                               Initializers[I]->getAnyMember()));
+  }
+  
+  // Add completions for base classes.
+  CodeCompletionBuilder Builder(Results.getAllocator(),
+                                Results.getCodeCompletionTUInfo());
+  bool SawLastInitializer = (NumInitializers == 0);
+  CXXRecordDecl *ClassDecl = Constructor->getParent();
+  for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin(),
+                                       BaseEnd = ClassDecl->bases_end();
+       Base != BaseEnd; ++Base) {
+    if (!InitializedBases.insert(Context.getCanonicalType(Base->getType()))) {
+      SawLastInitializer
+        = NumInitializers > 0 && 
+          Initializers[NumInitializers - 1]->isBaseInitializer() &&
+          Context.hasSameUnqualifiedType(Base->getType(),
+               QualType(Initializers[NumInitializers - 1]->getBaseClass(), 0));
+      continue;
+    }
+    
+    Builder.AddTypedTextChunk(
+               Results.getAllocator().CopyString(
+                          Base->getType().getAsString(Policy)));
+    Builder.AddChunk(CodeCompletionString::CK_LeftParen);
+    Builder.AddPlaceholderChunk("args");
+    Builder.AddChunk(CodeCompletionString::CK_RightParen);
+    Results.AddResult(CodeCompletionResult(Builder.TakeString(), 
+                                   SawLastInitializer? CCP_NextInitializer
+                                                     : CCP_MemberDeclaration));
+    SawLastInitializer = false;
+  }
+  
+  // Add completions for virtual base classes.
+  for (CXXRecordDecl::base_class_iterator Base = ClassDecl->vbases_begin(),
+                                       BaseEnd = ClassDecl->vbases_end();
+       Base != BaseEnd; ++Base) {
+    if (!InitializedBases.insert(Context.getCanonicalType(Base->getType()))) {
+      SawLastInitializer
+        = NumInitializers > 0 && 
+          Initializers[NumInitializers - 1]->isBaseInitializer() &&
+          Context.hasSameUnqualifiedType(Base->getType(),
+               QualType(Initializers[NumInitializers - 1]->getBaseClass(), 0));
+      continue;
+    }
+    
+    Builder.AddTypedTextChunk(
+               Builder.getAllocator().CopyString(
+                          Base->getType().getAsString(Policy)));
+    Builder.AddChunk(CodeCompletionString::CK_LeftParen);
+    Builder.AddPlaceholderChunk("args");
+    Builder.AddChunk(CodeCompletionString::CK_RightParen);
+    Results.AddResult(CodeCompletionResult(Builder.TakeString(), 
+                                   SawLastInitializer? CCP_NextInitializer
+                                                     : CCP_MemberDeclaration));
+    SawLastInitializer = false;
+  }
+  
+  // Add completions for members.
+  for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(),
+                                  FieldEnd = ClassDecl->field_end();
+       Field != FieldEnd; ++Field) {
+    if (!InitializedFields.insert(cast<FieldDecl>(Field->getCanonicalDecl()))) {
+      SawLastInitializer
+        = NumInitializers > 0 && 
+          Initializers[NumInitializers - 1]->isAnyMemberInitializer() &&
+          Initializers[NumInitializers - 1]->getAnyMember() == *Field;
+      continue;
+    }
+    
+    if (!Field->getDeclName())
+      continue;
+    
+    Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
+                                         Field->getIdentifier()->getName()));
+    Builder.AddChunk(CodeCompletionString::CK_LeftParen);
+    Builder.AddPlaceholderChunk("args");
+    Builder.AddChunk(CodeCompletionString::CK_RightParen);
+    Results.AddResult(CodeCompletionResult(Builder.TakeString(), 
+                                   SawLastInitializer? CCP_NextInitializer
+                                                     : CCP_MemberDeclaration,
+                                           CXCursor_MemberRef,
+                                           CXAvailability_Available,
+                                           *Field));
+    SawLastInitializer = false;
+  }
+  Results.ExitScope();
+  
+  HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
+                            Results.data(), Results.size());
+}
+
+/// \brief Determine whether this scope denotes a namespace.
+static bool isNamespaceScope(Scope *S) {
+  DeclContext *DC = static_cast<DeclContext *>(S->getEntity());
+  if (!DC)
+    return false;
+
+  return DC->isFileContext();
+}
+
+void Sema::CodeCompleteLambdaIntroducer(Scope *S, LambdaIntroducer &Intro,
+                                        bool AfterAmpersand) {
+  ResultBuilder Results(*this, CodeCompleter->getAllocator(),
+                        CodeCompleter->getCodeCompletionTUInfo(),
+                        CodeCompletionContext::CCC_Other);
+  Results.EnterNewScope();
+
+  // Note what has already been captured.
+  llvm::SmallPtrSet<IdentifierInfo *, 4> Known;
+  bool IncludedThis = false;
+  for (SmallVectorImpl<LambdaCapture>::iterator C = Intro.Captures.begin(),
+                                             CEnd = Intro.Captures.end();
+       C != CEnd; ++C) {
+    if (C->Kind == LCK_This) {
+      IncludedThis = true;
+      continue;
+    }
+    
+    Known.insert(C->Id);
+  }
+  
+  // Look for other capturable variables.
+  for (; S && !isNamespaceScope(S); S = S->getParent()) {
+    for (Scope::decl_iterator D = S->decl_begin(), DEnd = S->decl_end();
+         D != DEnd; ++D) {
+      VarDecl *Var = dyn_cast<VarDecl>(*D);
+      if (!Var ||
+          !Var->hasLocalStorage() ||
+          Var->hasAttr<BlocksAttr>())
+        continue;
+      
+      if (Known.insert(Var->getIdentifier()))
+        Results.AddResult(CodeCompletionResult(Var), CurContext, 0, false);
+    }
+  }
+
+  // Add 'this', if it would be valid.
+  if (!IncludedThis && !AfterAmpersand && Intro.Default != LCD_ByCopy)
+    addThisCompletion(*this, Results);
+  
+  Results.ExitScope();
+  
+  HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
+                            Results.data(), Results.size());
+}
+
+// Macro that expands to @Keyword or Keyword, depending on whether NeedAt is
+// true or false.
+#define OBJC_AT_KEYWORD_NAME(NeedAt,Keyword) NeedAt? "@" #Keyword : #Keyword
+static void AddObjCImplementationResults(const LangOptions &LangOpts,
+                                         ResultBuilder &Results,
+                                         bool NeedAt) {
+  typedef CodeCompletionResult Result;
+  // Since we have an implementation, we can end it.
+  Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,end)));
+  
+  CodeCompletionBuilder Builder(Results.getAllocator(),
+                                Results.getCodeCompletionTUInfo());
+  if (LangOpts.ObjC2) {
+    // @dynamic
+    Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,dynamic));
+    Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
+    Builder.AddPlaceholderChunk("property");
+    Results.AddResult(Result(Builder.TakeString()));
+    
+    // @synthesize
+    Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,synthesize));
+    Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
+    Builder.AddPlaceholderChunk("property");
+    Results.AddResult(Result(Builder.TakeString()));
+  }  
+}
+
+static void AddObjCInterfaceResults(const LangOptions &LangOpts,
+                                    ResultBuilder &Results,
+                                    bool NeedAt) {
+  typedef CodeCompletionResult Result;
+  
+  // Since we have an interface or protocol, we can end it.
+  Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,end)));
+  
+  if (LangOpts.ObjC2) {
+    // @property
+    Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,property)));
+  
+    // @required
+    Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,required)));
+  
+    // @optional
+    Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,optional)));
+  }
+}
+
+static void AddObjCTopLevelResults(ResultBuilder &Results, bool NeedAt) {
+  typedef CodeCompletionResult Result;
+  CodeCompletionBuilder Builder(Results.getAllocator(),
+                                Results.getCodeCompletionTUInfo());
+  
+  // @class name ;
+  Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,class));
+  Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
+  Builder.AddPlaceholderChunk("name");
+  Results.AddResult(Result(Builder.TakeString()));
+  
+  if (Results.includeCodePatterns()) {
+    // @interface name 
+    // FIXME: Could introduce the whole pattern, including superclasses and 
+    // such.
+    Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,interface));
+    Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
+    Builder.AddPlaceholderChunk("class");
+    Results.AddResult(Result(Builder.TakeString()));
+  
+    // @protocol name
+    Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,protocol));
+    Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
+    Builder.AddPlaceholderChunk("protocol");
+    Results.AddResult(Result(Builder.TakeString()));
+    
+    // @implementation name
+    Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,implementation));
+    Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
+    Builder.AddPlaceholderChunk("class");
+    Results.AddResult(Result(Builder.TakeString()));
+  }
+  
+  // @compatibility_alias name
+  Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,compatibility_alias));
+  Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
+  Builder.AddPlaceholderChunk("alias");
+  Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
+  Builder.AddPlaceholderChunk("class");
+  Results.AddResult(Result(Builder.TakeString()));
+}
+
+void Sema::CodeCompleteObjCAtDirective(Scope *S) {
+  typedef CodeCompletionResult Result;
+  ResultBuilder Results(*this, CodeCompleter->getAllocator(),
+                        CodeCompleter->getCodeCompletionTUInfo(),
+                        CodeCompletionContext::CCC_Other);
+  Results.EnterNewScope();
+  if (isa<ObjCImplDecl>(CurContext))
+    AddObjCImplementationResults(getLangOpts(), Results, false);
+  else if (CurContext->isObjCContainer())
+    AddObjCInterfaceResults(getLangOpts(), Results, false);
+  else
+    AddObjCTopLevelResults(Results, false);
+  Results.ExitScope();
+  HandleCodeCompleteResults(this, CodeCompleter, 
+                            CodeCompletionContext::CCC_Other,
+                            Results.data(),Results.size());
+}
+
+static void AddObjCExpressionResults(ResultBuilder &Results, bool NeedAt) {
+  typedef CodeCompletionResult Result;
+  CodeCompletionBuilder Builder(Results.getAllocator(),
+                                Results.getCodeCompletionTUInfo());
+
+  // @encode ( type-name )
+  const char *EncodeType = "char[]";
+  if (Results.getSema().getLangOpts().CPlusPlus ||
+      Results.getSema().getLangOpts().ConstStrings)
+    EncodeType = " const char[]";
+  Builder.AddResultTypeChunk(EncodeType);
+  Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,encode));
+  Builder.AddChunk(CodeCompletionString::CK_LeftParen);
+  Builder.AddPlaceholderChunk("type-name");
+  Builder.AddChunk(CodeCompletionString::CK_RightParen);
+  Results.AddResult(Result(Builder.TakeString()));
+  
+  // @protocol ( protocol-name )
+  Builder.AddResultTypeChunk("Protocol *");
+  Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,protocol));
+  Builder.AddChunk(CodeCompletionString::CK_LeftParen);
+  Builder.AddPlaceholderChunk("protocol-name");
+  Builder.AddChunk(CodeCompletionString::CK_RightParen);
+  Results.AddResult(Result(Builder.TakeString()));
+
+  // @selector ( selector )
+  Builder.AddResultTypeChunk("SEL");
+  Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,selector));
+  Builder.AddChunk(CodeCompletionString::CK_LeftParen);
+  Builder.AddPlaceholderChunk("selector");
+  Builder.AddChunk(CodeCompletionString::CK_RightParen);
+  Results.AddResult(Result(Builder.TakeString()));
+  
+  // @[ objects, ... ]
+  Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,[));
+  Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
+  Builder.AddPlaceholderChunk("objects, ...");
+  Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
+  Builder.AddChunk(CodeCompletionString::CK_RightBracket);
+  Results.AddResult(Result(Builder.TakeString()));
+
+  // @{ key : object, ... }
+  Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,{));
+  Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
+  Builder.AddPlaceholderChunk("key");
+  Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
+  Builder.AddChunk(CodeCompletionString::CK_Colon);
+  Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
+  Builder.AddPlaceholderChunk("object, ...");
+  Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
+  Builder.AddChunk(CodeCompletionString::CK_RightBrace);
+  Results.AddResult(Result(Builder.TakeString()));
+}
+
+static void AddObjCStatementResults(ResultBuilder &Results, bool NeedAt) {
+  typedef CodeCompletionResult Result;
+  CodeCompletionBuilder Builder(Results.getAllocator(),
+                                Results.getCodeCompletionTUInfo());
+  
+  if (Results.includeCodePatterns()) {
+    // @try { statements } @catch ( declaration ) { statements } @finally
+    //   { statements }
+    Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,try));
+    Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
+    Builder.AddPlaceholderChunk("statements");
+    Builder.AddChunk(CodeCompletionString::CK_RightBrace);
+    Builder.AddTextChunk("@catch");
+    Builder.AddChunk(CodeCompletionString::CK_LeftParen);
+    Builder.AddPlaceholderChunk("parameter");
+    Builder.AddChunk(CodeCompletionString::CK_RightParen);
+    Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
+    Builder.AddPlaceholderChunk("statements");
+    Builder.AddChunk(CodeCompletionString::CK_RightBrace);
+    Builder.AddTextChunk("@finally");
+    Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
+    Builder.AddPlaceholderChunk("statements");
+    Builder.AddChunk(CodeCompletionString::CK_RightBrace);
+    Results.AddResult(Result(Builder.TakeString()));
+  }
+  
+  // @throw
+  Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,throw));
+  Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
+  Builder.AddPlaceholderChunk("expression");
+  Results.AddResult(Result(Builder.TakeString()));
+  
+  if (Results.includeCodePatterns()) {
+    // @synchronized ( expression ) { statements }
+    Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,synchronized));
+    Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
+    Builder.AddChunk(CodeCompletionString::CK_LeftParen);
+    Builder.AddPlaceholderChunk("expression");
+    Builder.AddChunk(CodeCompletionString::CK_RightParen);
+    Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
+    Builder.AddPlaceholderChunk("statements");
+    Builder.AddChunk(CodeCompletionString::CK_RightBrace);
+    Results.AddResult(Result(Builder.TakeString()));
+  }
+}
+
+static void AddObjCVisibilityResults(const LangOptions &LangOpts,
+                                     ResultBuilder &Results,
+                                     bool NeedAt) {
+  typedef CodeCompletionResult Result;
+  Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,private)));
+  Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,protected)));
+  Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,public)));
+  if (LangOpts.ObjC2)
+    Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,package)));    
+}
+
+void Sema::CodeCompleteObjCAtVisibility(Scope *S) {
+  ResultBuilder Results(*this, CodeCompleter->getAllocator(),
+                        CodeCompleter->getCodeCompletionTUInfo(),
+                        CodeCompletionContext::CCC_Other);
+  Results.EnterNewScope();
+  AddObjCVisibilityResults(getLangOpts(), Results, false);
+  Results.ExitScope();
+  HandleCodeCompleteResults(this, CodeCompleter, 
+                            CodeCompletionContext::CCC_Other,
+                            Results.data(),Results.size());
+}
+
+void Sema::CodeCompleteObjCAtStatement(Scope *S) {
+  ResultBuilder Results(*this, CodeCompleter->getAllocator(),
+                        CodeCompleter->getCodeCompletionTUInfo(),
+                        CodeCompletionContext::CCC_Other);
+  Results.EnterNewScope();
+  AddObjCStatementResults(Results, false);
+  AddObjCExpressionResults(Results, false);
+  Results.ExitScope();
+  HandleCodeCompleteResults(this, CodeCompleter, 
+                            CodeCompletionContext::CCC_Other,
+                            Results.data(),Results.size());
+}
+
+void Sema::CodeCompleteObjCAtExpression(Scope *S) {
+  ResultBuilder Results(*this, CodeCompleter->getAllocator(),
+                        CodeCompleter->getCodeCompletionTUInfo(),
+                        CodeCompletionContext::CCC_Other);
+  Results.EnterNewScope();
+  AddObjCExpressionResults(Results, false);
+  Results.ExitScope();
+  HandleCodeCompleteResults(this, CodeCompleter, 
+                            CodeCompletionContext::CCC_Other,
+                            Results.data(),Results.size());
+}
+
+/// \brief Determine whether the addition of the given flag to an Objective-C
+/// property's attributes will cause a conflict.
+static bool ObjCPropertyFlagConflicts(unsigned Attributes, unsigned NewFlag) {
+  // Check if we've already added this flag.
+  if (Attributes & NewFlag)
+    return true;
+  
+  Attributes |= NewFlag;
+  
+  // Check for collisions with "readonly".
+  if ((Attributes & ObjCDeclSpec::DQ_PR_readonly) &&
+      (Attributes & (ObjCDeclSpec::DQ_PR_readwrite |
+                     ObjCDeclSpec::DQ_PR_assign |
+                     ObjCDeclSpec::DQ_PR_unsafe_unretained |
+                     ObjCDeclSpec::DQ_PR_copy |
+                     ObjCDeclSpec::DQ_PR_retain |
+                     ObjCDeclSpec::DQ_PR_strong)))
+    return true;
+  
+  // Check for more than one of { assign, copy, retain, strong }.
+  unsigned AssignCopyRetMask = Attributes & (ObjCDeclSpec::DQ_PR_assign |
+                                         ObjCDeclSpec::DQ_PR_unsafe_unretained |
+                                             ObjCDeclSpec::DQ_PR_copy |
+                                             ObjCDeclSpec::DQ_PR_retain|
+                                             ObjCDeclSpec::DQ_PR_strong);
+  if (AssignCopyRetMask &&
+      AssignCopyRetMask != ObjCDeclSpec::DQ_PR_assign &&
+      AssignCopyRetMask != ObjCDeclSpec::DQ_PR_unsafe_unretained &&
+      AssignCopyRetMask != ObjCDeclSpec::DQ_PR_copy &&
+      AssignCopyRetMask != ObjCDeclSpec::DQ_PR_retain &&
+      AssignCopyRetMask != ObjCDeclSpec::DQ_PR_strong)
+    return true;
+  
+  return false;
+}
+
+void Sema::CodeCompleteObjCPropertyFlags(Scope *S, ObjCDeclSpec &ODS) { 
+  if (!CodeCompleter)
+    return;
+  
+  unsigned Attributes = ODS.getPropertyAttributes();
+  
+  typedef CodeCompletionResult Result;
+  ResultBuilder Results(*this, CodeCompleter->getAllocator(),
+                        CodeCompleter->getCodeCompletionTUInfo(),
+                        CodeCompletionContext::CCC_Other);
+  Results.EnterNewScope();
+  if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_readonly))
+    Results.AddResult(CodeCompletionResult("readonly"));
+  if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_assign))
+    Results.AddResult(CodeCompletionResult("assign"));
+  if (!ObjCPropertyFlagConflicts(Attributes,
+                                 ObjCDeclSpec::DQ_PR_unsafe_unretained))
+    Results.AddResult(CodeCompletionResult("unsafe_unretained"));
+  if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_readwrite))
+    Results.AddResult(CodeCompletionResult("readwrite"));
+  if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_retain))
+    Results.AddResult(CodeCompletionResult("retain"));
+  if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_strong))
+    Results.AddResult(CodeCompletionResult("strong"));
+  if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_copy))
+    Results.AddResult(CodeCompletionResult("copy"));
+  if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_nonatomic))
+    Results.AddResult(CodeCompletionResult("nonatomic"));
+  if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_atomic))
+    Results.AddResult(CodeCompletionResult("atomic"));
+  if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_setter)) {
+    CodeCompletionBuilder Setter(Results.getAllocator(),
+                                 Results.getCodeCompletionTUInfo());
+    Setter.AddTypedTextChunk("setter");
+    Setter.AddTextChunk(" = ");
+    Setter.AddPlaceholderChunk("method");
+    Results.AddResult(CodeCompletionResult(Setter.TakeString()));
+  }
+  if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_getter)) {
+    CodeCompletionBuilder Getter(Results.getAllocator(),
+                                 Results.getCodeCompletionTUInfo());
+    Getter.AddTypedTextChunk("getter");
+    Getter.AddTextChunk(" = ");
+    Getter.AddPlaceholderChunk("method");
+    Results.AddResult(CodeCompletionResult(Getter.TakeString()));
+  }
+  Results.ExitScope();
+  HandleCodeCompleteResults(this, CodeCompleter, 
+                            CodeCompletionContext::CCC_Other,
+                            Results.data(),Results.size());
+}
+
+/// \brief Descripts the kind of Objective-C method that we want to find
+/// via code completion.
+enum ObjCMethodKind {
+  MK_Any, //< Any kind of method, provided it means other specified criteria.
+  MK_ZeroArgSelector, //< Zero-argument (unary) selector.
+  MK_OneArgSelector //< One-argument selector.
+};
+
+static bool isAcceptableObjCSelector(Selector Sel,
+                                     ObjCMethodKind WantKind,
+                                     IdentifierInfo **SelIdents,
+                                     unsigned NumSelIdents,
+                                     bool AllowSameLength = true) {
+  if (NumSelIdents > Sel.getNumArgs())
+    return false;
+  
+  switch (WantKind) {
+    case MK_Any:             break;
+    case MK_ZeroArgSelector: return Sel.isUnarySelector();
+    case MK_OneArgSelector:  return Sel.getNumArgs() == 1;
+  }
+  
+  if (!AllowSameLength && NumSelIdents && NumSelIdents == Sel.getNumArgs())
+    return false;
+  
+  for (unsigned I = 0; I != NumSelIdents; ++I)
+    if (SelIdents[I] != Sel.getIdentifierInfoForSlot(I))
+      return false;
+  
+  return true;
+}
+
+static bool isAcceptableObjCMethod(ObjCMethodDecl *Method,
+                                   ObjCMethodKind WantKind,
+                                   IdentifierInfo **SelIdents,
+                                   unsigned NumSelIdents,
+                                   bool AllowSameLength = true) {
+  return isAcceptableObjCSelector(Method->getSelector(), WantKind, SelIdents,
+                                  NumSelIdents, AllowSameLength);
+}
+
+namespace {
+  /// \brief A set of selectors, which is used to avoid introducing multiple 
+  /// completions with the same selector into the result set.
+  typedef llvm::SmallPtrSet<Selector, 16> VisitedSelectorSet;
+}
+
+/// \brief Add all of the Objective-C methods in the given Objective-C 
+/// container to the set of results.
+///
+/// The container will be a class, protocol, category, or implementation of 
+/// any of the above. This mether will recurse to include methods from 
+/// the superclasses of classes along with their categories, protocols, and
+/// implementations.
+///
+/// \param Container the container in which we'll look to find methods.
+///
+/// \param WantInstance whether to add instance methods (only); if false, this
+/// routine will add factory methods (only).
+///
+/// \param CurContext the context in which we're performing the lookup that
+/// finds methods.
+///
+/// \param AllowSameLength Whether we allow a method to be added to the list
+/// when it has the same number of parameters as we have selector identifiers.
+///
+/// \param Results the structure into which we'll add results.
+static void AddObjCMethods(ObjCContainerDecl *Container, 
+                           bool WantInstanceMethods,
+                           ObjCMethodKind WantKind,
+                           IdentifierInfo **SelIdents,
+                           unsigned NumSelIdents,
+                           DeclContext *CurContext,
+                           VisitedSelectorSet &Selectors,
+                           bool AllowSameLength,
+                           ResultBuilder &Results,
+                           bool InOriginalClass = true) {
+  typedef CodeCompletionResult Result;
+  for (ObjCContainerDecl::method_iterator M = Container->meth_begin(),
+                                       MEnd = Container->meth_end();
+       M != MEnd; ++M) {
+    if ((*M)->isInstanceMethod() == WantInstanceMethods) {
+      // Check whether the selector identifiers we've been given are a 
+      // subset of the identifiers for this particular method.
+      if (!isAcceptableObjCMethod(*M, WantKind, SelIdents, NumSelIdents,
+                                  AllowSameLength))
+        continue;
+
+      if (!Selectors.insert((*M)->getSelector()))
+        continue;
+      
+      Result R = Result(*M, 0);
+      R.StartParameter = NumSelIdents;
+      R.AllParametersAreInformative = (WantKind != MK_Any);
+      if (!InOriginalClass)
+        R.Priority += CCD_InBaseClass;
+      Results.MaybeAddResult(R, CurContext);
+    }
+  }
+  
+  // Visit the protocols of protocols.
+  if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
+    if (Protocol->hasDefinition()) {
+      const ObjCList<ObjCProtocolDecl> &Protocols
+        = Protocol->getReferencedProtocols();
+      for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
+                                                E = Protocols.end(); 
+           I != E; ++I)
+        AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents, 
+                       NumSelIdents, CurContext, Selectors, AllowSameLength, 
+                       Results, false);
+    }
+  }
+  
+  ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container);
+  if (!IFace || !IFace->hasDefinition())
+    return;
+  
+  // Add methods in protocols.
+  for (ObjCInterfaceDecl::protocol_iterator I = IFace->protocol_begin(),
+                                            E = IFace->protocol_end();
+       I != E; ++I)
+    AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents, NumSelIdents, 
+                   CurContext, Selectors, AllowSameLength, Results, false);
+  
+  // Add methods in categories.
+  for (ObjCCategoryDecl *CatDecl = IFace->getCategoryList(); CatDecl;
+       CatDecl = CatDecl->getNextClassCategory()) {
+    AddObjCMethods(CatDecl, WantInstanceMethods, WantKind, SelIdents, 
+                   NumSelIdents, CurContext, Selectors, AllowSameLength, 
+                   Results, InOriginalClass);
+    
+    // Add a categories protocol methods.
+    const ObjCList<ObjCProtocolDecl> &Protocols 
+      = CatDecl->getReferencedProtocols();
+    for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
+                                              E = Protocols.end();
+         I != E; ++I)
+      AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents, 
+                     NumSelIdents, CurContext, Selectors, AllowSameLength, 
+                     Results, false);
+    
+    // Add methods in category implementations.
+    if (ObjCCategoryImplDecl *Impl = CatDecl->getImplementation())
+      AddObjCMethods(Impl, WantInstanceMethods, WantKind, SelIdents, 
+                     NumSelIdents, CurContext, Selectors, AllowSameLength, 
+                     Results, InOriginalClass);
+  }
+  
+  // Add methods in superclass.
+  if (IFace->getSuperClass())
+    AddObjCMethods(IFace->getSuperClass(), WantInstanceMethods, WantKind, 
+                   SelIdents, NumSelIdents, CurContext, Selectors, 
+                   AllowSameLength, Results, false);
+
+  // Add methods in our implementation, if any.
+  if (ObjCImplementationDecl *Impl = IFace->getImplementation())
+    AddObjCMethods(Impl, WantInstanceMethods, WantKind, SelIdents,
+                   NumSelIdents, CurContext, Selectors, AllowSameLength, 
+                   Results, InOriginalClass);
+}
+
+
+void Sema::CodeCompleteObjCPropertyGetter(Scope *S) {
+  typedef CodeCompletionResult Result;
+
+  // Try to find the interface where getters might live.
+  ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurContext);
+  if (!Class) {
+    if (ObjCCategoryDecl *Category
+          = dyn_cast_or_null<ObjCCategoryDecl>(CurContext))
+      Class = Category->getClassInterface();
+
+    if (!Class)
+      return;
+  }
+
+  // Find all of the potential getters.
+  ResultBuilder Results(*this, CodeCompleter->getAllocator(),
+                        CodeCompleter->getCodeCompletionTUInfo(),
+                        CodeCompletionContext::CCC_Other);
+  Results.EnterNewScope();
+
+  VisitedSelectorSet Selectors;
+  AddObjCMethods(Class, true, MK_ZeroArgSelector, 0, 0, CurContext, Selectors,
+                 /*AllowSameLength=*/true, Results);
+  Results.ExitScope();
+  HandleCodeCompleteResults(this, CodeCompleter,
+                            CodeCompletionContext::CCC_Other,
+                            Results.data(),Results.size());
+}
+
+void Sema::CodeCompleteObjCPropertySetter(Scope *S) {
+  typedef CodeCompletionResult Result;
+
+  // Try to find the interface where setters might live.
+  ObjCInterfaceDecl *Class
+    = dyn_cast_or_null<ObjCInterfaceDecl>(CurContext);
+  if (!Class) {
+    if (ObjCCategoryDecl *Category
+          = dyn_cast_or_null<ObjCCategoryDecl>(CurContext))
+      Class = Category->getClassInterface();
+
+    if (!Class)
+      return;
+  }
+
+  // Find all of the potential getters.
+  ResultBuilder Results(*this, CodeCompleter->getAllocator(),
+                        CodeCompleter->getCodeCompletionTUInfo(),
+                        CodeCompletionContext::CCC_Other);
+  Results.EnterNewScope();
+
+  VisitedSelectorSet Selectors;
+  AddObjCMethods(Class, true, MK_OneArgSelector, 0, 0, CurContext, 
+                 Selectors, /*AllowSameLength=*/true, Results);
+
+  Results.ExitScope();
+  HandleCodeCompleteResults(this, CodeCompleter,
+                            CodeCompletionContext::CCC_Other,
+                            Results.data(),Results.size());
+}
+
+void Sema::CodeCompleteObjCPassingType(Scope *S, ObjCDeclSpec &DS,
+                                       bool IsParameter) {
+  typedef CodeCompletionResult Result;
+  ResultBuilder Results(*this, CodeCompleter->getAllocator(),
+                        CodeCompleter->getCodeCompletionTUInfo(),
+                        CodeCompletionContext::CCC_Type);
+  Results.EnterNewScope();
+  
+  // Add context-sensitive, Objective-C parameter-passing keywords.
+  bool AddedInOut = false;
+  if ((DS.getObjCDeclQualifier() & 
+       (ObjCDeclSpec::DQ_In | ObjCDeclSpec::DQ_Inout)) == 0) {
+    Results.AddResult("in");
+    Results.AddResult("inout");
+    AddedInOut = true;
+  }
+  if ((DS.getObjCDeclQualifier() & 
+       (ObjCDeclSpec::DQ_Out | ObjCDeclSpec::DQ_Inout)) == 0) {
+    Results.AddResult("out");
+    if (!AddedInOut)
+      Results.AddResult("inout");
+  }
+  if ((DS.getObjCDeclQualifier() & 
+       (ObjCDeclSpec::DQ_Bycopy | ObjCDeclSpec::DQ_Byref |
+        ObjCDeclSpec::DQ_Oneway)) == 0) {
+     Results.AddResult("bycopy");
+     Results.AddResult("byref");
+     Results.AddResult("oneway");
+  }
+  
+  // If we're completing the return type of an Objective-C method and the 
+  // identifier IBAction refers to a macro, provide a completion item for
+  // an action, e.g.,
+  //   IBAction)<#selector#>:(id)sender
+  if (DS.getObjCDeclQualifier() == 0 && !IsParameter &&
+      Context.Idents.get("IBAction").hasMacroDefinition()) {
+    CodeCompletionBuilder Builder(Results.getAllocator(),
+                                  Results.getCodeCompletionTUInfo(),
+                                  CCP_CodePattern, CXAvailability_Available);
+    Builder.AddTypedTextChunk("IBAction");
+    Builder.AddChunk(CodeCompletionString::CK_RightParen);
+    Builder.AddPlaceholderChunk("selector");
+    Builder.AddChunk(CodeCompletionString::CK_Colon);
+    Builder.AddChunk(CodeCompletionString::CK_LeftParen);
+    Builder.AddTextChunk("id");
+    Builder.AddChunk(CodeCompletionString::CK_RightParen);
+    Builder.AddTextChunk("sender");
+    Results.AddResult(CodeCompletionResult(Builder.TakeString()));
+  }
+  
+  // Add various builtin type names and specifiers.
+  AddOrdinaryNameResults(PCC_Type, S, *this, Results);
+  Results.ExitScope();
+  
+  // Add the various type names
+  Results.setFilter(&ResultBuilder::IsOrdinaryNonValueName);
+  CodeCompletionDeclConsumer Consumer(Results, CurContext);
+  LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
+                     CodeCompleter->includeGlobals());
+  
+  if (CodeCompleter->includeMacros())
+    AddMacroResults(PP, Results);
+
+  HandleCodeCompleteResults(this, CodeCompleter,
+                            CodeCompletionContext::CCC_Type,
+                            Results.data(), Results.size());
+}
+
+/// \brief When we have an expression with type "id", we may assume
+/// that it has some more-specific class type based on knowledge of
+/// common uses of Objective-C. This routine returns that class type,
+/// or NULL if no better result could be determined.
+static ObjCInterfaceDecl *GetAssumedMessageSendExprType(Expr *E) {
+  ObjCMessageExpr *Msg = dyn_cast_or_null<ObjCMessageExpr>(E);
+  if (!Msg)
+    return 0;
+
+  Selector Sel = Msg->getSelector();
+  if (Sel.isNull())
+    return 0;
+
+  IdentifierInfo *Id = Sel.getIdentifierInfoForSlot(0);
+  if (!Id)
+    return 0;
+
+  ObjCMethodDecl *Method = Msg->getMethodDecl();
+  if (!Method)
+    return 0;
+
+  // Determine the class that we're sending the message to.
+  ObjCInterfaceDecl *IFace = 0;
+  switch (Msg->getReceiverKind()) {
+  case ObjCMessageExpr::Class:
+    if (const ObjCObjectType *ObjType
+                           = Msg->getClassReceiver()->getAs<ObjCObjectType>())
+      IFace = ObjType->getInterface();
+    break;
+
+  case ObjCMessageExpr::Instance: {
+    QualType T = Msg->getInstanceReceiver()->getType();
+    if (const ObjCObjectPointerType *Ptr = T->getAs<ObjCObjectPointerType>())
+      IFace = Ptr->getInterfaceDecl();
+    break;
+  }
+
+  case ObjCMessageExpr::SuperInstance:
+  case ObjCMessageExpr::SuperClass:
+    break;
+  }
+
+  if (!IFace)
+    return 0;
+
+  ObjCInterfaceDecl *Super = IFace->getSuperClass();
+  if (Method->isInstanceMethod())
+    return llvm::StringSwitch<ObjCInterfaceDecl *>(Id->getName())
+      .Case("retain", IFace)
+      .Case("strong", IFace)
+      .Case("autorelease", IFace)
+      .Case("copy", IFace)
+      .Case("copyWithZone", IFace)
+      .Case("mutableCopy", IFace)
+      .Case("mutableCopyWithZone", IFace)
+      .Case("awakeFromCoder", IFace)
+      .Case("replacementObjectFromCoder", IFace)
+      .Case("class", IFace)
+      .Case("classForCoder", IFace)
+      .Case("superclass", Super)
+      .Default(0);
+
+  return llvm::StringSwitch<ObjCInterfaceDecl *>(Id->getName())
+    .Case("new", IFace)
+    .Case("alloc", IFace)
+    .Case("allocWithZone", IFace)
+    .Case("class", IFace)
+    .Case("superclass", Super)
+    .Default(0);
+}
+
+// Add a special completion for a message send to "super", which fills in the
+// most likely case of forwarding all of our arguments to the superclass 
+// function.
+///
+/// \param S The semantic analysis object.
+///
+/// \param S NeedSuperKeyword Whether we need to prefix this completion with
+/// the "super" keyword. Otherwise, we just need to provide the arguments.
+///
+/// \param SelIdents The identifiers in the selector that have already been
+/// provided as arguments for a send to "super".
+///
+/// \param NumSelIdents The number of identifiers in \p SelIdents.
+///
+/// \param Results The set of results to augment.
+///
+/// \returns the Objective-C method declaration that would be invoked by 
+/// this "super" completion. If NULL, no completion was added.
+static ObjCMethodDecl *AddSuperSendCompletion(Sema &S, bool NeedSuperKeyword,
+                                              IdentifierInfo **SelIdents,
+                                              unsigned NumSelIdents,
+                                              ResultBuilder &Results) {
+  ObjCMethodDecl *CurMethod = S.getCurMethodDecl();
+  if (!CurMethod)
+    return 0;
+  
+  ObjCInterfaceDecl *Class = CurMethod->getClassInterface();
+  if (!Class)
+    return 0;
+  
+  // Try to find a superclass method with the same selector.
+  ObjCMethodDecl *SuperMethod = 0;
+  while ((Class = Class->getSuperClass()) && !SuperMethod) {
+    // Check in the class
+    SuperMethod = Class->getMethod(CurMethod->getSelector(), 
+                                   CurMethod->isInstanceMethod());
+
+    // Check in categories or class extensions.
+    if (!SuperMethod) {
+      for (ObjCCategoryDecl *Category = Class->getCategoryList(); Category;
+           Category = Category->getNextClassCategory())
+        if ((SuperMethod = Category->getMethod(CurMethod->getSelector(), 
+                                               CurMethod->isInstanceMethod())))
+          break;
+    }
+  }
+
+  if (!SuperMethod)
+    return 0;
+  
+  // Check whether the superclass method has the same signature.
+  if (CurMethod->param_size() != SuperMethod->param_size() ||
+      CurMethod->isVariadic() != SuperMethod->isVariadic())
+    return 0;
+      
+  for (ObjCMethodDecl::param_iterator CurP = CurMethod->param_begin(),
+                                   CurPEnd = CurMethod->param_end(),
+                                    SuperP = SuperMethod->param_begin();
+       CurP != CurPEnd; ++CurP, ++SuperP) {
+    // Make sure the parameter types are compatible.
+    if (!S.Context.hasSameUnqualifiedType((*CurP)->getType(), 
+                                          (*SuperP)->getType()))
+      return 0;
+    
+    // Make sure we have a parameter name to forward!
+    if (!(*CurP)->getIdentifier())
+      return 0;
+  }
+  
+  // We have a superclass method. Now, form the send-to-super completion.
+  CodeCompletionBuilder Builder(Results.getAllocator(),
+                                Results.getCodeCompletionTUInfo());
+  
+  // Give this completion a return type.
+  AddResultTypeChunk(S.Context, getCompletionPrintingPolicy(S), SuperMethod, 
+                     Builder);
+
+  // If we need the "super" keyword, add it (plus some spacing).
+  if (NeedSuperKeyword) {
+    Builder.AddTypedTextChunk("super");
+    Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
+  }
+  
+  Selector Sel = CurMethod->getSelector();
+  if (Sel.isUnarySelector()) {
+    if (NeedSuperKeyword)
+      Builder.AddTextChunk(Builder.getAllocator().CopyString(
+                                  Sel.getNameForSlot(0)));
+    else
+      Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
+                                   Sel.getNameForSlot(0)));
+  } else {
+    ObjCMethodDecl::param_iterator CurP = CurMethod->param_begin();
+    for (unsigned I = 0, N = Sel.getNumArgs(); I != N; ++I, ++CurP) {
+      if (I > NumSelIdents)
+        Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
+      
+      if (I < NumSelIdents)
+        Builder.AddInformativeChunk(
+                   Builder.getAllocator().CopyString(
+                                                 Sel.getNameForSlot(I) + ":"));
+      else if (NeedSuperKeyword || I > NumSelIdents) {
+        Builder.AddTextChunk(
+                 Builder.getAllocator().CopyString(
+                                                  Sel.getNameForSlot(I) + ":"));
+        Builder.AddPlaceholderChunk(Builder.getAllocator().CopyString(
+                                         (*CurP)->getIdentifier()->getName()));
+      } else {
+        Builder.AddTypedTextChunk(
+                  Builder.getAllocator().CopyString(
+                                                  Sel.getNameForSlot(I) + ":"));
+        Builder.AddPlaceholderChunk(Builder.getAllocator().CopyString(
+                                         (*CurP)->getIdentifier()->getName())); 
+      }
+    }
+  }
+  
+  Results.AddResult(CodeCompletionResult(Builder.TakeString(), SuperMethod,
+                                         CCP_SuperCompletion));
+  return SuperMethod;
+}
+                                   
+void Sema::CodeCompleteObjCMessageReceiver(Scope *S) {
+  typedef CodeCompletionResult Result;
+  ResultBuilder Results(*this, CodeCompleter->getAllocator(),
+                        CodeCompleter->getCodeCompletionTUInfo(),
+                        CodeCompletionContext::CCC_ObjCMessageReceiver,
+                        getLangOpts().CPlusPlus0x
+                          ? &ResultBuilder::IsObjCMessageReceiverOrLambdaCapture
+                          : &ResultBuilder::IsObjCMessageReceiver);
+  
+  CodeCompletionDeclConsumer Consumer(Results, CurContext);
+  Results.EnterNewScope();
+  LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
+                     CodeCompleter->includeGlobals());
+  
+  // If we are in an Objective-C method inside a class that has a superclass,
+  // add "super" as an option.
+  if (ObjCMethodDecl *Method = getCurMethodDecl())
+    if (ObjCInterfaceDecl *Iface = Method->getClassInterface())
+      if (Iface->getSuperClass()) {
+        Results.AddResult(Result("super"));
+        
+        AddSuperSendCompletion(*this, /*NeedSuperKeyword=*/true, 0, 0, Results);
+      }
+  
+  if (getLangOpts().CPlusPlus0x)
+    addThisCompletion(*this, Results);
+  
+  Results.ExitScope();
+  
+  if (CodeCompleter->includeMacros())
+    AddMacroResults(PP, Results);
+  HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
+                            Results.data(), Results.size());
+  
+}
+
+void Sema::CodeCompleteObjCSuperMessage(Scope *S, SourceLocation SuperLoc,
+                                        IdentifierInfo **SelIdents,
+                                        unsigned NumSelIdents,
+                                        bool AtArgumentExpression) {
+  ObjCInterfaceDecl *CDecl = 0;
+  if (ObjCMethodDecl *CurMethod = getCurMethodDecl()) {
+    // Figure out which interface we're in.
+    CDecl = CurMethod->getClassInterface();
+    if (!CDecl)
+      return;
+    
+    // Find the superclass of this class.
+    CDecl = CDecl->getSuperClass();
+    if (!CDecl)
+      return;
+
+    if (CurMethod->isInstanceMethod()) {
+      // We are inside an instance method, which means that the message
+      // send [super ...] is actually calling an instance method on the
+      // current object.
+      return CodeCompleteObjCInstanceMessage(S, 0,
+                                             SelIdents, NumSelIdents,
+                                             AtArgumentExpression,
+                                             CDecl);
+    }
+
+    // Fall through to send to the superclass in CDecl.
+  } else {
+    // "super" may be the name of a type or variable. Figure out which
+    // it is.
+    IdentifierInfo *Super = &Context.Idents.get("super");
+    NamedDecl *ND = LookupSingleName(S, Super, SuperLoc, 
+                                     LookupOrdinaryName);
+    if ((CDecl = dyn_cast_or_null<ObjCInterfaceDecl>(ND))) {
+      // "super" names an interface. Use it.
+    } else if (TypeDecl *TD = dyn_cast_or_null<TypeDecl>(ND)) {
+      if (const ObjCObjectType *Iface
+            = Context.getTypeDeclType(TD)->getAs<ObjCObjectType>())
+        CDecl = Iface->getInterface();
+    } else if (ND && isa<UnresolvedUsingTypenameDecl>(ND)) {
+      // "super" names an unresolved type; we can't be more specific.
+    } else {
+      // Assume that "super" names some kind of value and parse that way.
+      CXXScopeSpec SS;
+      SourceLocation TemplateKWLoc;
+      UnqualifiedId id;
+      id.setIdentifier(Super, SuperLoc);
+      ExprResult SuperExpr = ActOnIdExpression(S, SS, TemplateKWLoc, id,
+                                               false, false);
+      return CodeCompleteObjCInstanceMessage(S, (Expr *)SuperExpr.get(),
+                                             SelIdents, NumSelIdents,
+                                             AtArgumentExpression);
+    }
+
+    // Fall through
+  }
+
+  ParsedType Receiver;
+  if (CDecl)
+    Receiver = ParsedType::make(Context.getObjCInterfaceType(CDecl));
+  return CodeCompleteObjCClassMessage(S, Receiver, SelIdents, 
+                                      NumSelIdents, AtArgumentExpression,
+                                      /*IsSuper=*/true);
+}
+
+/// \brief Given a set of code-completion results for the argument of a message
+/// send, determine the preferred type (if any) for that argument expression.
+static QualType getPreferredArgumentTypeForMessageSend(ResultBuilder &Results,
+                                                       unsigned NumSelIdents) {
+  typedef CodeCompletionResult Result;  
+  ASTContext &Context = Results.getSema().Context;
+  
+  QualType PreferredType;
+  unsigned BestPriority = CCP_Unlikely * 2;
+  Result *ResultsData = Results.data();
+  for (unsigned I = 0, N = Results.size(); I != N; ++I) {
+    Result &R = ResultsData[I];
+    if (R.Kind == Result::RK_Declaration && 
+        isa<ObjCMethodDecl>(R.Declaration)) {
+      if (R.Priority <= BestPriority) {
+        ObjCMethodDecl *Method = cast<ObjCMethodDecl>(R.Declaration);
+        if (NumSelIdents <= Method->param_size()) {
+          QualType MyPreferredType = Method->param_begin()[NumSelIdents - 1]
+                                       ->getType();
+          if (R.Priority < BestPriority || PreferredType.isNull()) {
+            BestPriority = R.Priority;
+            PreferredType = MyPreferredType;
+          } else if (!Context.hasSameUnqualifiedType(PreferredType,
+                                                     MyPreferredType)) {
+            PreferredType = QualType();
+          }
+        }
+      }
+    }
+  }
+
+  return PreferredType;
+}
+
+static void AddClassMessageCompletions(Sema &SemaRef, Scope *S, 
+                                       ParsedType Receiver,
+                                       IdentifierInfo **SelIdents,
+                                       unsigned NumSelIdents,
+                                       bool AtArgumentExpression,
+                                       bool IsSuper,
+                                       ResultBuilder &Results) {
+  typedef CodeCompletionResult Result;
+  ObjCInterfaceDecl *CDecl = 0;
+  
+  // If the given name refers to an interface type, retrieve the
+  // corresponding declaration.
+  if (Receiver) {
+    QualType T = SemaRef.GetTypeFromParser(Receiver, 0);
+    if (!T.isNull()) 
+      if (const ObjCObjectType *Interface = T->getAs<ObjCObjectType>())
+        CDecl = Interface->getInterface();
+  }
+  
+  // Add all of the factory methods in this Objective-C class, its protocols,
+  // superclasses, categories, implementation, etc.
+  Results.EnterNewScope();
+  
+  // If this is a send-to-super, try to add the special "super" send 
+  // completion.
+  if (IsSuper) {
+    if (ObjCMethodDecl *SuperMethod
+        = AddSuperSendCompletion(SemaRef, false, SelIdents, NumSelIdents, 
+                                 Results))
+      Results.Ignore(SuperMethod);
+  }
+  
+  // If we're inside an Objective-C method definition, prefer its selector to
+  // others.
+  if (ObjCMethodDecl *CurMethod = SemaRef.getCurMethodDecl())
+    Results.setPreferredSelector(CurMethod->getSelector());
+  
+  VisitedSelectorSet Selectors;
+  if (CDecl) 
+    AddObjCMethods(CDecl, false, MK_Any, SelIdents, NumSelIdents, 
+                   SemaRef.CurContext, Selectors, AtArgumentExpression,
+                   Results);  
+  else {
+    // We're messaging "id" as a type; provide all class/factory methods.
+    
+    // If we have an external source, load the entire class method
+    // pool from the AST file.
+    if (SemaRef.ExternalSource) {
+      for (uint32_t I = 0, 
+                    N = SemaRef.ExternalSource->GetNumExternalSelectors();
+           I != N; ++I) {
+        Selector Sel = SemaRef.ExternalSource->GetExternalSelector(I);
+        if (Sel.isNull() || SemaRef.MethodPool.count(Sel))
+          continue;
+        
+        SemaRef.ReadMethodPool(Sel);
+      }
+    }
+    
+    for (Sema::GlobalMethodPool::iterator M = SemaRef.MethodPool.begin(),
+                                       MEnd = SemaRef.MethodPool.end();
+         M != MEnd; ++M) {
+      for (ObjCMethodList *MethList = &M->second.second;
+           MethList && MethList->Method; 
+           MethList = MethList->Next) {
+        if (!isAcceptableObjCMethod(MethList->Method, MK_Any, SelIdents, 
+                                    NumSelIdents))
+          continue;
+        
+        Result R(MethList->Method, 0);
+        R.StartParameter = NumSelIdents;
+        R.AllParametersAreInformative = false;
+        Results.MaybeAddResult(R, SemaRef.CurContext);
+      }
+    }
+  }
+  
+  Results.ExitScope();  
+}
+
+void Sema::CodeCompleteObjCClassMessage(Scope *S, ParsedType Receiver,
+                                        IdentifierInfo **SelIdents,
+                                        unsigned NumSelIdents,
+                                        bool AtArgumentExpression,
+                                        bool IsSuper) {
+  
+  QualType T = this->GetTypeFromParser(Receiver);
+  
+  ResultBuilder Results(*this, CodeCompleter->getAllocator(),
+                        CodeCompleter->getCodeCompletionTUInfo(),
+              CodeCompletionContext(CodeCompletionContext::CCC_ObjCClassMessage,
+                                    T, SelIdents, NumSelIdents));
+    
+  AddClassMessageCompletions(*this, S, Receiver, SelIdents, NumSelIdents, 
+                             AtArgumentExpression, IsSuper, Results);
+  
+  // If we're actually at the argument expression (rather than prior to the 
+  // selector), we're actually performing code completion for an expression.
+  // Determine whether we have a single, best method. If so, we can 
+  // code-complete the expression using the corresponding parameter type as
+  // our preferred type, improving completion results.
+  if (AtArgumentExpression) {
+    QualType PreferredType = getPreferredArgumentTypeForMessageSend(Results, 
+                                                                  NumSelIdents);
+    if (PreferredType.isNull())
+      CodeCompleteOrdinaryName(S, PCC_Expression);
+    else
+      CodeCompleteExpression(S, PreferredType);
+    return;
+  }
+
+  HandleCodeCompleteResults(this, CodeCompleter, 
+                            Results.getCompletionContext(),
+                            Results.data(), Results.size());
+}
+
+void Sema::CodeCompleteObjCInstanceMessage(Scope *S, Expr *Receiver,
+                                           IdentifierInfo **SelIdents,
+                                           unsigned NumSelIdents,
+                                           bool AtArgumentExpression,
+                                           ObjCInterfaceDecl *Super) {
+  typedef CodeCompletionResult Result;
+  
+  Expr *RecExpr = static_cast<Expr *>(Receiver);
+  
+  // If necessary, apply function/array conversion to the receiver.
+  // C99 6.7.5.3p[7,8].
+  if (RecExpr) {
+    ExprResult Conv = DefaultFunctionArrayLvalueConversion(RecExpr);
+    if (Conv.isInvalid()) // conversion failed. bail.
+      return;
+    RecExpr = Conv.take();
+  }
+  QualType ReceiverType = RecExpr? RecExpr->getType() 
+                          : Super? Context.getObjCObjectPointerType(
+                                            Context.getObjCInterfaceType(Super))
+                                 : Context.getObjCIdType();
+  
+  // If we're messaging an expression with type "id" or "Class", check
+  // whether we know something special about the receiver that allows
+  // us to assume a more-specific receiver type.
+  if (ReceiverType->isObjCIdType() || ReceiverType->isObjCClassType())
+    if (ObjCInterfaceDecl *IFace = GetAssumedMessageSendExprType(RecExpr)) {
+      if (ReceiverType->isObjCClassType())
+        return CodeCompleteObjCClassMessage(S, 
+                       ParsedType::make(Context.getObjCInterfaceType(IFace)),
+                                            SelIdents, NumSelIdents,
+                                            AtArgumentExpression, Super);
+
+      ReceiverType = Context.getObjCObjectPointerType(
+                                          Context.getObjCInterfaceType(IFace));
+    }
+
+  // Build the set of methods we can see.
+  ResultBuilder Results(*this, CodeCompleter->getAllocator(),
+                        CodeCompleter->getCodeCompletionTUInfo(),
+           CodeCompletionContext(CodeCompletionContext::CCC_ObjCInstanceMessage,
+                                 ReceiverType, SelIdents, NumSelIdents));
+  
+  Results.EnterNewScope();
+
+  // If this is a send-to-super, try to add the special "super" send 
+  // completion.
+  if (Super) {
+    if (ObjCMethodDecl *SuperMethod
+          = AddSuperSendCompletion(*this, false, SelIdents, NumSelIdents, 
+                                   Results))
+      Results.Ignore(SuperMethod);
+  }
+  
+  // If we're inside an Objective-C method definition, prefer its selector to
+  // others.
+  if (ObjCMethodDecl *CurMethod = getCurMethodDecl())
+    Results.setPreferredSelector(CurMethod->getSelector());
+  
+  // Keep track of the selectors we've already added.
+  VisitedSelectorSet Selectors;
+  
+  // Handle messages to Class. This really isn't a message to an instance
+  // method, so we treat it the same way we would treat a message send to a
+  // class method.
+  if (ReceiverType->isObjCClassType() || 
+      ReceiverType->isObjCQualifiedClassType()) {
+    if (ObjCMethodDecl *CurMethod = getCurMethodDecl()) {
+      if (ObjCInterfaceDecl *ClassDecl = CurMethod->getClassInterface())
+        AddObjCMethods(ClassDecl, false, MK_Any, SelIdents, NumSelIdents, 
+                       CurContext, Selectors, AtArgumentExpression, Results);
+    }
+  } 
+  // Handle messages to a qualified ID ("id<foo>").
+  else if (const ObjCObjectPointerType *QualID
+             = ReceiverType->getAsObjCQualifiedIdType()) {
+    // Search protocols for instance methods.
+    for (ObjCObjectPointerType::qual_iterator I = QualID->qual_begin(),
+                                              E = QualID->qual_end(); 
+         I != E; ++I)
+      AddObjCMethods(*I, true, MK_Any, SelIdents, NumSelIdents, CurContext, 
+                     Selectors, AtArgumentExpression, Results);
+  }
+  // Handle messages to a pointer to interface type.
+  else if (const ObjCObjectPointerType *IFacePtr
+                              = ReceiverType->getAsObjCInterfacePointerType()) {
+    // Search the class, its superclasses, etc., for instance methods.
+    AddObjCMethods(IFacePtr->getInterfaceDecl(), true, MK_Any, SelIdents,
+                   NumSelIdents, CurContext, Selectors, AtArgumentExpression, 
+                   Results);
+    
+    // Search protocols for instance methods.
+    for (ObjCObjectPointerType::qual_iterator I = IFacePtr->qual_begin(),
+         E = IFacePtr->qual_end(); 
+         I != E; ++I)
+      AddObjCMethods(*I, true, MK_Any, SelIdents, NumSelIdents, CurContext, 
+                     Selectors, AtArgumentExpression, Results);
+  }
+  // Handle messages to "id".
+  else if (ReceiverType->isObjCIdType()) {
+    // We're messaging "id", so provide all instance methods we know
+    // about as code-completion results.
+
+    // If we have an external source, load the entire class method
+    // pool from the AST file.
+    if (ExternalSource) {
+      for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors();
+           I != N; ++I) {
+        Selector Sel = ExternalSource->GetExternalSelector(I);
+        if (Sel.isNull() || MethodPool.count(Sel))
+          continue;
+
+        ReadMethodPool(Sel);
+      }
+    }
+
+    for (GlobalMethodPool::iterator M = MethodPool.begin(),
+                                    MEnd = MethodPool.end();
+         M != MEnd; ++M) {
+      for (ObjCMethodList *MethList = &M->second.first;
+           MethList && MethList->Method; 
+           MethList = MethList->Next) {
+        if (!isAcceptableObjCMethod(MethList->Method, MK_Any, SelIdents, 
+                                    NumSelIdents))
+          continue;
+        
+        if (!Selectors.insert(MethList->Method->getSelector()))
+          continue;
+        
+        Result R(MethList->Method, 0);
+        R.StartParameter = NumSelIdents;
+        R.AllParametersAreInformative = false;
+        Results.MaybeAddResult(R, CurContext);
+      }
+    }
+  }
+  Results.ExitScope();
+  
+  
+  // If we're actually at the argument expression (rather than prior to the 
+  // selector), we're actually performing code completion for an expression.
+  // Determine whether we have a single, best method. If so, we can 
+  // code-complete the expression using the corresponding parameter type as
+  // our preferred type, improving completion results.
+  if (AtArgumentExpression) {
+    QualType PreferredType = getPreferredArgumentTypeForMessageSend(Results, 
+                                                                  NumSelIdents);
+    if (PreferredType.isNull())
+      CodeCompleteOrdinaryName(S, PCC_Expression);
+    else
+      CodeCompleteExpression(S, PreferredType);
+    return;
+  }
+  
+  HandleCodeCompleteResults(this, CodeCompleter, 
+                            Results.getCompletionContext(),
+                            Results.data(),Results.size());
+}
+
+void Sema::CodeCompleteObjCForCollection(Scope *S, 
+                                         DeclGroupPtrTy IterationVar) {
+  CodeCompleteExpressionData Data;
+  Data.ObjCCollection = true;
+  
+  if (IterationVar.getAsOpaquePtr()) {
+    DeclGroupRef DG = IterationVar.getAsVal<DeclGroupRef>();
+    for (DeclGroupRef::iterator I = DG.begin(), End = DG.end(); I != End; ++I) {
+      if (*I)
+        Data.IgnoreDecls.push_back(*I);
+    }
+  }
+  
+  CodeCompleteExpression(S, Data);
+}
+
+void Sema::CodeCompleteObjCSelector(Scope *S, IdentifierInfo **SelIdents,
+                                    unsigned NumSelIdents) {
+  // If we have an external source, load the entire class method
+  // pool from the AST file.
+  if (ExternalSource) {
+    for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors();
+         I != N; ++I) {
+      Selector Sel = ExternalSource->GetExternalSelector(I);
+      if (Sel.isNull() || MethodPool.count(Sel))
+        continue;
+      
+      ReadMethodPool(Sel);
+    }
+  }
+  
+  ResultBuilder Results(*this, CodeCompleter->getAllocator(),
+                        CodeCompleter->getCodeCompletionTUInfo(),
+                        CodeCompletionContext::CCC_SelectorName);
+  Results.EnterNewScope();
+  for (GlobalMethodPool::iterator M = MethodPool.begin(),
+                               MEnd = MethodPool.end();
+       M != MEnd; ++M) {
+    
+    Selector Sel = M->first;
+    if (!isAcceptableObjCSelector(Sel, MK_Any, SelIdents, NumSelIdents))
+      continue;
+
+    CodeCompletionBuilder Builder(Results.getAllocator(),
+                                  Results.getCodeCompletionTUInfo());
+    if (Sel.isUnarySelector()) {
+      Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
+                                                       Sel.getNameForSlot(0)));
+      Results.AddResult(Builder.TakeString());
+      continue;
+    }
+    
+    std::string Accumulator;
+    for (unsigned I = 0, N = Sel.getNumArgs(); I != N; ++I) {
+      if (I == NumSelIdents) {
+        if (!Accumulator.empty()) {
+          Builder.AddInformativeChunk(Builder.getAllocator().CopyString(
+                                                 Accumulator));
+          Accumulator.clear();
+        }
+      }
+      
+      Accumulator += Sel.getNameForSlot(I);
+      Accumulator += ':';
+    }
+    Builder.AddTypedTextChunk(Builder.getAllocator().CopyString( Accumulator));
+    Results.AddResult(Builder.TakeString());
+  }
+  Results.ExitScope();
+  
+  HandleCodeCompleteResults(this, CodeCompleter, 
+                            CodeCompletionContext::CCC_SelectorName,
+                            Results.data(), Results.size());
+}
+
+/// \brief Add all of the protocol declarations that we find in the given
+/// (translation unit) context.
+static void AddProtocolResults(DeclContext *Ctx, DeclContext *CurContext,
+                               bool OnlyForwardDeclarations,
+                               ResultBuilder &Results) {
+  typedef CodeCompletionResult Result;
+  
+  for (DeclContext::decl_iterator D = Ctx->decls_begin(), 
+                               DEnd = Ctx->decls_end();
+       D != DEnd; ++D) {
+    // Record any protocols we find.
+    if (ObjCProtocolDecl *Proto = dyn_cast<ObjCProtocolDecl>(*D))
+      if (!OnlyForwardDeclarations || !Proto->hasDefinition())
+        Results.AddResult(Result(Proto, 0), CurContext, 0, false);
+  }
+}
+
+void Sema::CodeCompleteObjCProtocolReferences(IdentifierLocPair *Protocols,
+                                              unsigned NumProtocols) {
+  ResultBuilder Results(*this, CodeCompleter->getAllocator(),
+                        CodeCompleter->getCodeCompletionTUInfo(),
+                        CodeCompletionContext::CCC_ObjCProtocolName);
+  
+  if (CodeCompleter && CodeCompleter->includeGlobals()) {
+    Results.EnterNewScope();
+    
+    // Tell the result set to ignore all of the protocols we have
+    // already seen.
+    // FIXME: This doesn't work when caching code-completion results.
+    for (unsigned I = 0; I != NumProtocols; ++I)
+      if (ObjCProtocolDecl *Protocol = LookupProtocol(Protocols[I].first,
+                                                      Protocols[I].second))
+        Results.Ignore(Protocol);
+
+    // Add all protocols.
+    AddProtocolResults(Context.getTranslationUnitDecl(), CurContext, false,
+                       Results);
+
+    Results.ExitScope();
+  }
+  
+  HandleCodeCompleteResults(this, CodeCompleter, 
+                            CodeCompletionContext::CCC_ObjCProtocolName,
+                            Results.data(),Results.size());
+}
+
+void Sema::CodeCompleteObjCProtocolDecl(Scope *) {
+  ResultBuilder Results(*this, CodeCompleter->getAllocator(),
+                        CodeCompleter->getCodeCompletionTUInfo(),
+                        CodeCompletionContext::CCC_ObjCProtocolName);
+  
+  if (CodeCompleter && CodeCompleter->includeGlobals()) {
+    Results.EnterNewScope();
+    
+    // Add all protocols.
+    AddProtocolResults(Context.getTranslationUnitDecl(), CurContext, true,
+                       Results);
+
+    Results.ExitScope();
+  }
+  
+  HandleCodeCompleteResults(this, CodeCompleter, 
+                            CodeCompletionContext::CCC_ObjCProtocolName,
+                            Results.data(),Results.size());
+}
+
+/// \brief Add all of the Objective-C interface declarations that we find in
+/// the given (translation unit) context.
+static void AddInterfaceResults(DeclContext *Ctx, DeclContext *CurContext,
+                                bool OnlyForwardDeclarations,
+                                bool OnlyUnimplemented,
+                                ResultBuilder &Results) {
+  typedef CodeCompletionResult Result;
+  
+  for (DeclContext::decl_iterator D = Ctx->decls_begin(), 
+                               DEnd = Ctx->decls_end();
+       D != DEnd; ++D) {
+    // Record any interfaces we find.
+    if (ObjCInterfaceDecl *Class = dyn_cast<ObjCInterfaceDecl>(*D))
+      if ((!OnlyForwardDeclarations || !Class->hasDefinition()) &&
+          (!OnlyUnimplemented || !Class->getImplementation()))
+        Results.AddResult(Result(Class, 0), CurContext, 0, false);
+  }
+}
+
+void Sema::CodeCompleteObjCInterfaceDecl(Scope *S) { 
+  ResultBuilder Results(*this, CodeCompleter->getAllocator(),
+                        CodeCompleter->getCodeCompletionTUInfo(),
+                        CodeCompletionContext::CCC_Other);
+  Results.EnterNewScope();
+  
+  if (CodeCompleter->includeGlobals()) {
+    // Add all classes.
+    AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, false,
+                        false, Results);
+  }
+  
+  Results.ExitScope();
+
+  HandleCodeCompleteResults(this, CodeCompleter,
+                            CodeCompletionContext::CCC_ObjCInterfaceName,
+                            Results.data(),Results.size());
+}
+
+void Sema::CodeCompleteObjCSuperclass(Scope *S, IdentifierInfo *ClassName,
+                                      SourceLocation ClassNameLoc) { 
+  ResultBuilder Results(*this, CodeCompleter->getAllocator(),
+                        CodeCompleter->getCodeCompletionTUInfo(),
+                        CodeCompletionContext::CCC_ObjCInterfaceName);
+  Results.EnterNewScope();
+  
+  // Make sure that we ignore the class we're currently defining.
+  NamedDecl *CurClass
+    = LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName);
+  if (CurClass && isa<ObjCInterfaceDecl>(CurClass))
+    Results.Ignore(CurClass);
+
+  if (CodeCompleter->includeGlobals()) {
+    // Add all classes.
+    AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, false,
+                        false, Results);
+  }
+  
+  Results.ExitScope();
+
+  HandleCodeCompleteResults(this, CodeCompleter, 
+                            CodeCompletionContext::CCC_ObjCInterfaceName,
+                            Results.data(),Results.size());
+}
+
+void Sema::CodeCompleteObjCImplementationDecl(Scope *S) { 
+  ResultBuilder Results(*this, CodeCompleter->getAllocator(),
+                        CodeCompleter->getCodeCompletionTUInfo(),
+                        CodeCompletionContext::CCC_Other);
+  Results.EnterNewScope();
+
+  if (CodeCompleter->includeGlobals()) {
+    // Add all unimplemented classes.
+    AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, false,
+                        true, Results);
+  }
+  
+  Results.ExitScope();
+
+  HandleCodeCompleteResults(this, CodeCompleter, 
+                            CodeCompletionContext::CCC_ObjCInterfaceName,
+                            Results.data(),Results.size());
+}
+
+void Sema::CodeCompleteObjCInterfaceCategory(Scope *S, 
+                                             IdentifierInfo *ClassName,
+                                             SourceLocation ClassNameLoc) {
+  typedef CodeCompletionResult Result;
+  
+  ResultBuilder Results(*this, CodeCompleter->getAllocator(),
+                        CodeCompleter->getCodeCompletionTUInfo(),
+                        CodeCompletionContext::CCC_ObjCCategoryName);
+  
+  // Ignore any categories we find that have already been implemented by this
+  // interface.
+  llvm::SmallPtrSet<IdentifierInfo *, 16> CategoryNames;
+  NamedDecl *CurClass
+    = LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName);
+  if (ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurClass))
+    for (ObjCCategoryDecl *Category = Class->getCategoryList(); Category;
+         Category = Category->getNextClassCategory())
+      CategoryNames.insert(Category->getIdentifier());
+  
+  // Add all of the categories we know about.
+  Results.EnterNewScope();
+  TranslationUnitDecl *TU = Context.getTranslationUnitDecl();
+  for (DeclContext::decl_iterator D = TU->decls_begin(), 
+                               DEnd = TU->decls_end();
+       D != DEnd; ++D) 
+    if (ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(*D))
+      if (CategoryNames.insert(Category->getIdentifier()))
+        Results.AddResult(Result(Category, 0), CurContext, 0, false);
+  Results.ExitScope();
+  
+  HandleCodeCompleteResults(this, CodeCompleter, 
+                            CodeCompletionContext::CCC_ObjCCategoryName,
+                            Results.data(),Results.size());  
+}
+
+void Sema::CodeCompleteObjCImplementationCategory(Scope *S, 
+                                                  IdentifierInfo *ClassName,
+                                                  SourceLocation ClassNameLoc) {
+  typedef CodeCompletionResult Result;
+  
+  // Find the corresponding interface. If we couldn't find the interface, the
+  // program itself is ill-formed. However, we'll try to be helpful still by
+  // providing the list of all of the categories we know about.
+  NamedDecl *CurClass
+    = LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName);
+  ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurClass);
+  if (!Class)
+    return CodeCompleteObjCInterfaceCategory(S, ClassName, ClassNameLoc);
+    
+  ResultBuilder Results(*this, CodeCompleter->getAllocator(),
+                        CodeCompleter->getCodeCompletionTUInfo(),
+                        CodeCompletionContext::CCC_ObjCCategoryName);
+  
+  // Add all of the categories that have have corresponding interface 
+  // declarations in this class and any of its superclasses, except for
+  // already-implemented categories in the class itself.
+  llvm::SmallPtrSet<IdentifierInfo *, 16> CategoryNames;
+  Results.EnterNewScope();
+  bool IgnoreImplemented = true;
+  while (Class) {
+    for (ObjCCategoryDecl *Category = Class->getCategoryList(); Category;
+         Category = Category->getNextClassCategory())
+      if ((!IgnoreImplemented || !Category->getImplementation()) &&
+          CategoryNames.insert(Category->getIdentifier()))
+        Results.AddResult(Result(Category, 0), CurContext, 0, false);
+    
+    Class = Class->getSuperClass();
+    IgnoreImplemented = false;
+  }
+  Results.ExitScope();
+  
+  HandleCodeCompleteResults(this, CodeCompleter, 
+                            CodeCompletionContext::CCC_ObjCCategoryName,
+                            Results.data(),Results.size());  
+}
+
+void Sema::CodeCompleteObjCPropertyDefinition(Scope *S) {
+  typedef CodeCompletionResult Result;
+  ResultBuilder Results(*this, CodeCompleter->getAllocator(),
+                        CodeCompleter->getCodeCompletionTUInfo(),
+                        CodeCompletionContext::CCC_Other);
+
+  // Figure out where this @synthesize lives.
+  ObjCContainerDecl *Container
+    = dyn_cast_or_null<ObjCContainerDecl>(CurContext);
+  if (!Container || 
+      (!isa<ObjCImplementationDecl>(Container) && 
+       !isa<ObjCCategoryImplDecl>(Container)))
+    return; 
+
+  // Ignore any properties that have already been implemented.
+  for (DeclContext::decl_iterator D = Container->decls_begin(), 
+                               DEnd = Container->decls_end();
+       D != DEnd; ++D)
+    if (ObjCPropertyImplDecl *PropertyImpl = dyn_cast<ObjCPropertyImplDecl>(*D))
+      Results.Ignore(PropertyImpl->getPropertyDecl());
+  
+  // Add any properties that we find.
+  AddedPropertiesSet AddedProperties;
+  Results.EnterNewScope();
+  if (ObjCImplementationDecl *ClassImpl
+        = dyn_cast<ObjCImplementationDecl>(Container))
+    AddObjCProperties(ClassImpl->getClassInterface(), false, 
+                      /*AllowNullaryMethods=*/false, CurContext, 
+                      AddedProperties, Results);
+  else
+    AddObjCProperties(cast<ObjCCategoryImplDecl>(Container)->getCategoryDecl(),
+                      false, /*AllowNullaryMethods=*/false, CurContext, 
+                      AddedProperties, Results);
+  Results.ExitScope();
+  
+  HandleCodeCompleteResults(this, CodeCompleter, 
+                            CodeCompletionContext::CCC_Other,
+                            Results.data(),Results.size());  
+}
+
+void Sema::CodeCompleteObjCPropertySynthesizeIvar(Scope *S, 
+                                                  IdentifierInfo *PropertyName) {
+  typedef CodeCompletionResult Result;
+  ResultBuilder Results(*this, CodeCompleter->getAllocator(),
+                        CodeCompleter->getCodeCompletionTUInfo(),
+                        CodeCompletionContext::CCC_Other);
+
+  // Figure out where this @synthesize lives.
+  ObjCContainerDecl *Container
+    = dyn_cast_or_null<ObjCContainerDecl>(CurContext);
+  if (!Container || 
+      (!isa<ObjCImplementationDecl>(Container) && 
+       !isa<ObjCCategoryImplDecl>(Container)))
+    return; 
+  
+  // Figure out which interface we're looking into.
+  ObjCInterfaceDecl *Class = 0;
+  if (ObjCImplementationDecl *ClassImpl
+                                 = dyn_cast<ObjCImplementationDecl>(Container))  
+    Class = ClassImpl->getClassInterface();
+  else
+    Class = cast<ObjCCategoryImplDecl>(Container)->getCategoryDecl()
+                                                          ->getClassInterface();
+
+  // Determine the type of the property we're synthesizing.
+  QualType PropertyType = Context.getObjCIdType();
+  if (Class) {
+    if (ObjCPropertyDecl *Property
+                              = Class->FindPropertyDeclaration(PropertyName)) {
+      PropertyType 
+        = Property->getType().getNonReferenceType().getUnqualifiedType();
+      
+      // Give preference to ivars 
+      Results.setPreferredType(PropertyType);
+    }
+  }
+
+  // Add all of the instance variables in this class and its superclasses.
+  Results.EnterNewScope();
+  bool SawSimilarlyNamedIvar = false;
+  std::string NameWithPrefix;
+  NameWithPrefix += '_';
+  NameWithPrefix += PropertyName->getName();
+  std::string NameWithSuffix = PropertyName->getName().str();
+  NameWithSuffix += '_';
+  for(; Class; Class = Class->getSuperClass()) {
+    for (ObjCIvarDecl *Ivar = Class->all_declared_ivar_begin(); Ivar; 
+         Ivar = Ivar->getNextIvar()) {
+      Results.AddResult(Result(Ivar, 0), CurContext, 0, false);
+      
+      // Determine whether we've seen an ivar with a name similar to the 
+      // property.
+      if ((PropertyName == Ivar->getIdentifier() ||
+           NameWithPrefix == Ivar->getName() ||
+           NameWithSuffix == Ivar->getName())) {
+        SawSimilarlyNamedIvar = true;
+       
+        // Reduce the priority of this result by one, to give it a slight
+        // advantage over other results whose names don't match so closely.
+        if (Results.size() && 
+            Results.data()[Results.size() - 1].Kind 
+                                      == CodeCompletionResult::RK_Declaration &&
+            Results.data()[Results.size() - 1].Declaration == Ivar)
+          Results.data()[Results.size() - 1].Priority--;
+      }
+    }
+  }
+  
+  if (!SawSimilarlyNamedIvar) {
+    // Create ivar result _propName, that the user can use to synthesize
+    // an ivar of the appropriate type.    
+    unsigned Priority = CCP_MemberDeclaration + 1;
+    typedef CodeCompletionResult Result;
+    CodeCompletionAllocator &Allocator = Results.getAllocator();
+    CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo(),
+                                  Priority,CXAvailability_Available);
+
+    PrintingPolicy Policy = getCompletionPrintingPolicy(*this);
+    Builder.AddResultTypeChunk(GetCompletionTypeString(PropertyType, Context,
+                                                       Policy, Allocator));
+    Builder.AddTypedTextChunk(Allocator.CopyString(NameWithPrefix));
+    Results.AddResult(Result(Builder.TakeString(), Priority, 
+                             CXCursor_ObjCIvarDecl));
+  }
+  
+  Results.ExitScope();
+  
+  HandleCodeCompleteResults(this, CodeCompleter, 
+                            CodeCompletionContext::CCC_Other,
+                            Results.data(),Results.size());
+}
+
+// Mapping from selectors to the methods that implement that selector, along
+// with the "in original class" flag.
+typedef llvm::DenseMap<Selector, std::pair<ObjCMethodDecl *, bool> > 
+  KnownMethodsMap;
+
+/// \brief Find all of the methods that reside in the given container
+/// (and its superclasses, protocols, etc.) that meet the given
+/// criteria. Insert those methods into the map of known methods,
+/// indexed by selector so they can be easily found.
+static void FindImplementableMethods(ASTContext &Context,
+                                     ObjCContainerDecl *Container,
+                                     bool WantInstanceMethods,
+                                     QualType ReturnType,
+                                     KnownMethodsMap &KnownMethods,
+                                     bool InOriginalClass = true) {
+  if (ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container)) {
+    // Recurse into protocols.
+    if (!IFace->hasDefinition())
+      return;
+    
+    const ObjCList<ObjCProtocolDecl> &Protocols
+      = IFace->getReferencedProtocols();
+    for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
+                                              E = Protocols.end(); 
+         I != E; ++I)
+      FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType,
+                               KnownMethods, InOriginalClass);
+
+    // Add methods from any class extensions and categories.
+    for (const ObjCCategoryDecl *Cat = IFace->getCategoryList(); Cat;
+         Cat = Cat->getNextClassCategory())
+      FindImplementableMethods(Context, const_cast<ObjCCategoryDecl*>(Cat), 
+                               WantInstanceMethods, ReturnType,
+                               KnownMethods, false);      
+    
+    // Visit the superclass.
+    if (IFace->getSuperClass())
+      FindImplementableMethods(Context, IFace->getSuperClass(), 
+                               WantInstanceMethods, ReturnType,
+                               KnownMethods, false);
+  }
+
+  if (ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(Container)) {
+    // Recurse into protocols.
+    const ObjCList<ObjCProtocolDecl> &Protocols
+      = Category->getReferencedProtocols();
+    for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
+                                              E = Protocols.end(); 
+         I != E; ++I)
+      FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType,
+                               KnownMethods, InOriginalClass);
+    
+    // If this category is the original class, jump to the interface.
+    if (InOriginalClass && Category->getClassInterface())
+      FindImplementableMethods(Context, Category->getClassInterface(), 
+                               WantInstanceMethods, ReturnType, KnownMethods,
+                               false);
+  }
+
+  if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
+    if (Protocol->hasDefinition()) {
+      // Recurse into protocols.
+      const ObjCList<ObjCProtocolDecl> &Protocols
+        = Protocol->getReferencedProtocols();
+      for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
+             E = Protocols.end(); 
+           I != E; ++I)
+        FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType,
+                                 KnownMethods, false);
+    }
+  }
+
+  // Add methods in this container. This operation occurs last because
+  // we want the methods from this container to override any methods
+  // we've previously seen with the same selector.
+  for (ObjCContainerDecl::method_iterator M = Container->meth_begin(),
+                                       MEnd = Container->meth_end();
+       M != MEnd; ++M) {
+    if ((*M)->isInstanceMethod() == WantInstanceMethods) {
+      if (!ReturnType.isNull() &&
+          !Context.hasSameUnqualifiedType(ReturnType, (*M)->getResultType()))
+        continue;
+
+      KnownMethods[(*M)->getSelector()] = std::make_pair(*M, InOriginalClass);
+    }
+  }
+}
+
+/// \brief Add the parenthesized return or parameter type chunk to a code 
+/// completion string.
+static void AddObjCPassingTypeChunk(QualType Type,
+                                    unsigned ObjCDeclQuals,
+                                    ASTContext &Context,
+                                    const PrintingPolicy &Policy,
+                                    CodeCompletionBuilder &Builder) {
+  Builder.AddChunk(CodeCompletionString::CK_LeftParen);
+  std::string Quals = formatObjCParamQualifiers(ObjCDeclQuals);
+  if (!Quals.empty())
+    Builder.AddTextChunk(Builder.getAllocator().CopyString(Quals));
+  Builder.AddTextChunk(GetCompletionTypeString(Type, Context, Policy,
+                                               Builder.getAllocator()));
+  Builder.AddChunk(CodeCompletionString::CK_RightParen);
+}
+
+/// \brief Determine whether the given class is or inherits from a class by
+/// the given name.
+static bool InheritsFromClassNamed(ObjCInterfaceDecl *Class, 
+                                   StringRef Name) {
+  if (!Class)
+    return false;
+  
+  if (Class->getIdentifier() && Class->getIdentifier()->getName() == Name)
+    return true;
+  
+  return InheritsFromClassNamed(Class->getSuperClass(), Name);
+}
+                  
+/// \brief Add code completions for Objective-C Key-Value Coding (KVC) and
+/// Key-Value Observing (KVO).
+static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,
+                                       bool IsInstanceMethod,
+                                       QualType ReturnType,
+                                       ASTContext &Context,
+                                       VisitedSelectorSet &KnownSelectors,
+                                       ResultBuilder &Results) {
+  IdentifierInfo *PropName = Property->getIdentifier();
+  if (!PropName || PropName->getLength() == 0)
+    return;
+  
+  PrintingPolicy Policy = getCompletionPrintingPolicy(Results.getSema());
+
+  // Builder that will create each code completion.
+  typedef CodeCompletionResult Result;
+  CodeCompletionAllocator &Allocator = Results.getAllocator();
+  CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo());
+  
+  // The selector table.
+  SelectorTable &Selectors = Context.Selectors;
+  
+  // The property name, copied into the code completion allocation region
+  // on demand.
+  struct KeyHolder {
+    CodeCompletionAllocator &Allocator;
+    StringRef Key;
+    const char *CopiedKey;
+    
+    KeyHolder(CodeCompletionAllocator &Allocator, StringRef Key)
+    : Allocator(Allocator), Key(Key), CopiedKey(0) { }
+    
+    operator const char *() {
+      if (CopiedKey)
+        return CopiedKey;
+      
+      return CopiedKey = Allocator.CopyString(Key);
+    }
+  } Key(Allocator, PropName->getName());
+  
+  // The uppercased name of the property name.
+  std::string UpperKey = PropName->getName();
+  if (!UpperKey.empty())
+    UpperKey[0] = toupper(UpperKey[0]);      
+  
+  bool ReturnTypeMatchesProperty = ReturnType.isNull() ||
+    Context.hasSameUnqualifiedType(ReturnType.getNonReferenceType(), 
+                                   Property->getType());
+  bool ReturnTypeMatchesVoid 
+    = ReturnType.isNull() || ReturnType->isVoidType();
+  
+  // Add the normal accessor -(type)key.
+  if (IsInstanceMethod &&
+      KnownSelectors.insert(Selectors.getNullarySelector(PropName)) &&
+      ReturnTypeMatchesProperty && !Property->getGetterMethodDecl()) {
+    if (ReturnType.isNull())
+      AddObjCPassingTypeChunk(Property->getType(), /*Quals=*/0,
+                              Context, Policy, Builder);
+    
+    Builder.AddTypedTextChunk(Key);
+    Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern, 
+                             CXCursor_ObjCInstanceMethodDecl));
+  }
+  
+  // If we have an integral or boolean property (or the user has provided
+  // an integral or boolean return type), add the accessor -(type)isKey.
+  if (IsInstanceMethod &&
+      ((!ReturnType.isNull() && 
+        (ReturnType->isIntegerType() || ReturnType->isBooleanType())) ||
+       (ReturnType.isNull() && 
+        (Property->getType()->isIntegerType() || 
+         Property->getType()->isBooleanType())))) {
+    std::string SelectorName = (Twine("is") + UpperKey).str();
+    IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
+    if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))) {
+      if (ReturnType.isNull()) {
+        Builder.AddChunk(CodeCompletionString::CK_LeftParen);
+        Builder.AddTextChunk("BOOL");
+        Builder.AddChunk(CodeCompletionString::CK_RightParen);
+      }
+      
+      Builder.AddTypedTextChunk(
+                                Allocator.CopyString(SelectorId->getName()));
+      Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern, 
+                               CXCursor_ObjCInstanceMethodDecl));
+    }
+  }
+  
+  // Add the normal mutator.
+  if (IsInstanceMethod && ReturnTypeMatchesVoid && 
+      !Property->getSetterMethodDecl()) {
+    std::string SelectorName = (Twine("set") + UpperKey).str();
+    IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
+    if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
+      if (ReturnType.isNull()) {
+        Builder.AddChunk(CodeCompletionString::CK_LeftParen);
+        Builder.AddTextChunk("void");
+        Builder.AddChunk(CodeCompletionString::CK_RightParen);
+      }
+      
+      Builder.AddTypedTextChunk(
+                                Allocator.CopyString(SelectorId->getName()));
+      Builder.AddTypedTextChunk(":");
+      AddObjCPassingTypeChunk(Property->getType(), /*Quals=*/0,
+                              Context, Policy, Builder);
+      Builder.AddTextChunk(Key);
+      Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern, 
+                               CXCursor_ObjCInstanceMethodDecl));
+    }
+  }
+  
+  // Indexed and unordered accessors
+  unsigned IndexedGetterPriority = CCP_CodePattern;
+  unsigned IndexedSetterPriority = CCP_CodePattern;
+  unsigned UnorderedGetterPriority = CCP_CodePattern;
+  unsigned UnorderedSetterPriority = CCP_CodePattern;
+  if (const ObjCObjectPointerType *ObjCPointer 
+                    = Property->getType()->getAs<ObjCObjectPointerType>()) {
+    if (ObjCInterfaceDecl *IFace = ObjCPointer->getInterfaceDecl()) {
+      // If this interface type is not provably derived from a known
+      // collection, penalize the corresponding completions.
+      if (!InheritsFromClassNamed(IFace, "NSMutableArray")) {
+        IndexedSetterPriority += CCD_ProbablyNotObjCCollection;            
+        if (!InheritsFromClassNamed(IFace, "NSArray"))
+          IndexedGetterPriority += CCD_ProbablyNotObjCCollection;
+      }
+
+      if (!InheritsFromClassNamed(IFace, "NSMutableSet")) {
+        UnorderedSetterPriority += CCD_ProbablyNotObjCCollection;            
+        if (!InheritsFromClassNamed(IFace, "NSSet"))
+          UnorderedGetterPriority += CCD_ProbablyNotObjCCollection;
+      }
+    }
+  } else {
+    IndexedGetterPriority += CCD_ProbablyNotObjCCollection;
+    IndexedSetterPriority += CCD_ProbablyNotObjCCollection;
+    UnorderedGetterPriority += CCD_ProbablyNotObjCCollection;
+    UnorderedSetterPriority += CCD_ProbablyNotObjCCollection;
+  }
+  
+  // Add -(NSUInteger)countOf<key>
+  if (IsInstanceMethod &&  
+      (ReturnType.isNull() || ReturnType->isIntegerType())) {
+    std::string SelectorName = (Twine("countOf") + UpperKey).str();
+    IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
+    if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))) {
+      if (ReturnType.isNull()) {
+        Builder.AddChunk(CodeCompletionString::CK_LeftParen);
+        Builder.AddTextChunk("NSUInteger");
+        Builder.AddChunk(CodeCompletionString::CK_RightParen);
+      }
+      
+      Builder.AddTypedTextChunk(
+                                Allocator.CopyString(SelectorId->getName()));
+      Results.AddResult(Result(Builder.TakeString(), 
+                               std::min(IndexedGetterPriority, 
+                                        UnorderedGetterPriority),
+                               CXCursor_ObjCInstanceMethodDecl));
+    }
+  }
+  
+  // Indexed getters
+  // Add -(id)objectInKeyAtIndex:(NSUInteger)index
+  if (IsInstanceMethod &&
+      (ReturnType.isNull() || ReturnType->isObjCObjectPointerType())) {
+    std::string SelectorName
+      = (Twine("objectIn") + UpperKey + "AtIndex").str();
+    IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
+    if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
+      if (ReturnType.isNull()) {
+        Builder.AddChunk(CodeCompletionString::CK_LeftParen);
+        Builder.AddTextChunk("id");
+        Builder.AddChunk(CodeCompletionString::CK_RightParen);
+      }
+      
+      Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
+      Builder.AddChunk(CodeCompletionString::CK_LeftParen);
+      Builder.AddTextChunk("NSUInteger");
+      Builder.AddChunk(CodeCompletionString::CK_RightParen);
+      Builder.AddTextChunk("index");
+      Results.AddResult(Result(Builder.TakeString(), IndexedGetterPriority, 
+                               CXCursor_ObjCInstanceMethodDecl));
+    }
+  }
+  
+  // Add -(NSArray *)keyAtIndexes:(NSIndexSet *)indexes
+  if (IsInstanceMethod &&
+      (ReturnType.isNull() || 
+       (ReturnType->isObjCObjectPointerType() &&
+        ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl() &&
+        ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl()
+                                                ->getName() == "NSArray"))) {
+    std::string SelectorName
+      = (Twine(Property->getName()) + "AtIndexes").str();
+    IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
+    if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
+      if (ReturnType.isNull()) {
+        Builder.AddChunk(CodeCompletionString::CK_LeftParen);
+        Builder.AddTextChunk("NSArray *");
+        Builder.AddChunk(CodeCompletionString::CK_RightParen);
+      }
+       
+      Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
+      Builder.AddChunk(CodeCompletionString::CK_LeftParen);
+      Builder.AddTextChunk("NSIndexSet *");
+      Builder.AddChunk(CodeCompletionString::CK_RightParen);
+      Builder.AddTextChunk("indexes");
+      Results.AddResult(Result(Builder.TakeString(), IndexedGetterPriority, 
+                               CXCursor_ObjCInstanceMethodDecl));
+    }
+  }
+  
+  // Add -(void)getKey:(type **)buffer range:(NSRange)inRange
+  if (IsInstanceMethod && ReturnTypeMatchesVoid) {
+    std::string SelectorName = (Twine("get") + UpperKey).str();
+    IdentifierInfo *SelectorIds[2] = {
+      &Context.Idents.get(SelectorName),
+      &Context.Idents.get("range")
+    };
+    
+    if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds))) {
+      if (ReturnType.isNull()) {
+        Builder.AddChunk(CodeCompletionString::CK_LeftParen);
+        Builder.AddTextChunk("void");
+        Builder.AddChunk(CodeCompletionString::CK_RightParen);
+      }
+      
+      Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
+      Builder.AddChunk(CodeCompletionString::CK_LeftParen);
+      Builder.AddPlaceholderChunk("object-type");
+      Builder.AddTextChunk(" **");
+      Builder.AddChunk(CodeCompletionString::CK_RightParen);
+      Builder.AddTextChunk("buffer");
+      Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
+      Builder.AddTypedTextChunk("range:");
+      Builder.AddChunk(CodeCompletionString::CK_LeftParen);
+      Builder.AddTextChunk("NSRange");
+      Builder.AddChunk(CodeCompletionString::CK_RightParen);
+      Builder.AddTextChunk("inRange");
+      Results.AddResult(Result(Builder.TakeString(), IndexedGetterPriority, 
+                               CXCursor_ObjCInstanceMethodDecl));
+    }
+  }
+  
+  // Mutable indexed accessors
+  
+  // - (void)insertObject:(type *)object inKeyAtIndex:(NSUInteger)index
+  if (IsInstanceMethod && ReturnTypeMatchesVoid) {
+    std::string SelectorName = (Twine("in") + UpperKey + "AtIndex").str();
+    IdentifierInfo *SelectorIds[2] = {
+      &Context.Idents.get("insertObject"),
+      &Context.Idents.get(SelectorName)
+    };
+    
+    if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds))) {
+      if (ReturnType.isNull()) {
+        Builder.AddChunk(CodeCompletionString::CK_LeftParen);
+        Builder.AddTextChunk("void");
+        Builder.AddChunk(CodeCompletionString::CK_RightParen);
+      }
+      
+      Builder.AddTypedTextChunk("insertObject:");
+      Builder.AddChunk(CodeCompletionString::CK_LeftParen);
+      Builder.AddPlaceholderChunk("object-type");
+      Builder.AddTextChunk(" *");
+      Builder.AddChunk(CodeCompletionString::CK_RightParen);
+      Builder.AddTextChunk("object");
+      Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
+      Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
+      Builder.AddChunk(CodeCompletionString::CK_LeftParen);
+      Builder.AddPlaceholderChunk("NSUInteger");
+      Builder.AddChunk(CodeCompletionString::CK_RightParen);
+      Builder.AddTextChunk("index");
+      Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority, 
+                               CXCursor_ObjCInstanceMethodDecl));
+    }
+  }
+  
+  // - (void)insertKey:(NSArray *)array atIndexes:(NSIndexSet *)indexes
+  if (IsInstanceMethod && ReturnTypeMatchesVoid) {
+    std::string SelectorName = (Twine("insert") + UpperKey).str();
+    IdentifierInfo *SelectorIds[2] = {
+      &Context.Idents.get(SelectorName),
+      &Context.Idents.get("atIndexes")
+    };
+    
+    if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds))) {
+      if (ReturnType.isNull()) {
+        Builder.AddChunk(CodeCompletionString::CK_LeftParen);
+        Builder.AddTextChunk("void");
+        Builder.AddChunk(CodeCompletionString::CK_RightParen);
+      }
+      
+      Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
+      Builder.AddChunk(CodeCompletionString::CK_LeftParen);
+      Builder.AddTextChunk("NSArray *");
+      Builder.AddChunk(CodeCompletionString::CK_RightParen);
+      Builder.AddTextChunk("array");
+      Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
+      Builder.AddTypedTextChunk("atIndexes:");
+      Builder.AddChunk(CodeCompletionString::CK_LeftParen);
+      Builder.AddPlaceholderChunk("NSIndexSet *");
+      Builder.AddChunk(CodeCompletionString::CK_RightParen);
+      Builder.AddTextChunk("indexes");
+      Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority, 
+                               CXCursor_ObjCInstanceMethodDecl));
+    }
+  }
+  
+  // -(void)removeObjectFromKeyAtIndex:(NSUInteger)index
+  if (IsInstanceMethod && ReturnTypeMatchesVoid) {
+    std::string SelectorName
+      = (Twine("removeObjectFrom") + UpperKey + "AtIndex").str();
+    IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);        
+    if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
+      if (ReturnType.isNull()) {
+        Builder.AddChunk(CodeCompletionString::CK_LeftParen);
+        Builder.AddTextChunk("void");
+        Builder.AddChunk(CodeCompletionString::CK_RightParen);
+      }
+      
+      Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
+      Builder.AddChunk(CodeCompletionString::CK_LeftParen);
+      Builder.AddTextChunk("NSUInteger");
+      Builder.AddChunk(CodeCompletionString::CK_RightParen);
+      Builder.AddTextChunk("index");
+      Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority, 
+                               CXCursor_ObjCInstanceMethodDecl));
+    }
+  }
+  
+  // -(void)removeKeyAtIndexes:(NSIndexSet *)indexes
+  if (IsInstanceMethod && ReturnTypeMatchesVoid) {
+    std::string SelectorName
+      = (Twine("remove") + UpperKey + "AtIndexes").str();
+    IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);        
+    if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
+      if (ReturnType.isNull()) {
+        Builder.AddChunk(CodeCompletionString::CK_LeftParen);
+        Builder.AddTextChunk("void");
+        Builder.AddChunk(CodeCompletionString::CK_RightParen);
+      }
+      
+      Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
+      Builder.AddChunk(CodeCompletionString::CK_LeftParen);
+      Builder.AddTextChunk("NSIndexSet *");
+      Builder.AddChunk(CodeCompletionString::CK_RightParen);
+      Builder.AddTextChunk("indexes");
+      Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority, 
+                               CXCursor_ObjCInstanceMethodDecl));
+    }
+  }
+  
+  // - (void)replaceObjectInKeyAtIndex:(NSUInteger)index withObject:(id)object
+  if (IsInstanceMethod && ReturnTypeMatchesVoid) {
+    std::string SelectorName
+      = (Twine("replaceObjectIn") + UpperKey + "AtIndex").str();
+    IdentifierInfo *SelectorIds[2] = {
+      &Context.Idents.get(SelectorName),
+      &Context.Idents.get("withObject")
+    };
+    
+    if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds))) {
+      if (ReturnType.isNull()) {
+        Builder.AddChunk(CodeCompletionString::CK_LeftParen);
+        Builder.AddTextChunk("void");
+        Builder.AddChunk(CodeCompletionString::CK_RightParen);
+      }
+      
+      Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
+      Builder.AddChunk(CodeCompletionString::CK_LeftParen);
+      Builder.AddPlaceholderChunk("NSUInteger");
+      Builder.AddChunk(CodeCompletionString::CK_RightParen);
+      Builder.AddTextChunk("index");
+      Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
+      Builder.AddTypedTextChunk("withObject:");
+      Builder.AddChunk(CodeCompletionString::CK_LeftParen);
+      Builder.AddTextChunk("id");
+      Builder.AddChunk(CodeCompletionString::CK_RightParen);
+      Builder.AddTextChunk("object");
+      Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority, 
+                               CXCursor_ObjCInstanceMethodDecl));
+    }
+  }
+  
+  // - (void)replaceKeyAtIndexes:(NSIndexSet *)indexes withKey:(NSArray *)array
+  if (IsInstanceMethod && ReturnTypeMatchesVoid) {
+    std::string SelectorName1 
+      = (Twine("replace") + UpperKey + "AtIndexes").str();
+    std::string SelectorName2 = (Twine("with") + UpperKey).str();
+    IdentifierInfo *SelectorIds[2] = {
+      &Context.Idents.get(SelectorName1),
+      &Context.Idents.get(SelectorName2)
+    };
+    
+    if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds))) {
+      if (ReturnType.isNull()) {
+        Builder.AddChunk(CodeCompletionString::CK_LeftParen);
+        Builder.AddTextChunk("void");
+        Builder.AddChunk(CodeCompletionString::CK_RightParen);
+      }
+      
+      Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName1 + ":"));
+      Builder.AddChunk(CodeCompletionString::CK_LeftParen);
+      Builder.AddPlaceholderChunk("NSIndexSet *");
+      Builder.AddChunk(CodeCompletionString::CK_RightParen);
+      Builder.AddTextChunk("indexes");
+      Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
+      Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName2 + ":"));
+      Builder.AddChunk(CodeCompletionString::CK_LeftParen);
+      Builder.AddTextChunk("NSArray *");
+      Builder.AddChunk(CodeCompletionString::CK_RightParen);
+      Builder.AddTextChunk("array");
+      Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority, 
+                               CXCursor_ObjCInstanceMethodDecl));
+    }
+  }  
+  
+  // Unordered getters
+  // - (NSEnumerator *)enumeratorOfKey
+  if (IsInstanceMethod && 
+      (ReturnType.isNull() || 
+       (ReturnType->isObjCObjectPointerType() &&
+        ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl() &&
+        ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl()
+          ->getName() == "NSEnumerator"))) {
+    std::string SelectorName = (Twine("enumeratorOf") + UpperKey).str();
+    IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
+    if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))) {
+      if (ReturnType.isNull()) {
+        Builder.AddChunk(CodeCompletionString::CK_LeftParen);
+        Builder.AddTextChunk("NSEnumerator *");
+        Builder.AddChunk(CodeCompletionString::CK_RightParen);
+      }
+       
+      Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName));
+      Results.AddResult(Result(Builder.TakeString(), UnorderedGetterPriority, 
+                              CXCursor_ObjCInstanceMethodDecl));
+    }
+  }
+
+  // - (type *)memberOfKey:(type *)object
+  if (IsInstanceMethod && 
+      (ReturnType.isNull() || ReturnType->isObjCObjectPointerType())) {
+    std::string SelectorName = (Twine("memberOf") + UpperKey).str();
+    IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
+    if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
+      if (ReturnType.isNull()) {
+        Builder.AddChunk(CodeCompletionString::CK_LeftParen);
+        Builder.AddPlaceholderChunk("object-type");
+        Builder.AddTextChunk(" *");
+        Builder.AddChunk(CodeCompletionString::CK_RightParen);
+      }
+      
+      Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
+      Builder.AddChunk(CodeCompletionString::CK_LeftParen);
+      if (ReturnType.isNull()) {
+        Builder.AddPlaceholderChunk("object-type");
+        Builder.AddTextChunk(" *");
+      } else {
+        Builder.AddTextChunk(GetCompletionTypeString(ReturnType, Context, 
+                                                     Policy,
+                                                     Builder.getAllocator()));
+      }
+      Builder.AddChunk(CodeCompletionString::CK_RightParen);
+      Builder.AddTextChunk("object");
+      Results.AddResult(Result(Builder.TakeString(), UnorderedGetterPriority, 
+                               CXCursor_ObjCInstanceMethodDecl));
+    }
+  }
+  
+  // Mutable unordered accessors
+  // - (void)addKeyObject:(type *)object
+  if (IsInstanceMethod && ReturnTypeMatchesVoid) {
+    std::string SelectorName
+      = (Twine("add") + UpperKey + Twine("Object")).str();
+    IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
+    if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
+      if (ReturnType.isNull()) {
+        Builder.AddChunk(CodeCompletionString::CK_LeftParen);
+        Builder.AddTextChunk("void");
+        Builder.AddChunk(CodeCompletionString::CK_RightParen);
+      }
+      
+      Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
+      Builder.AddChunk(CodeCompletionString::CK_LeftParen);
+      Builder.AddPlaceholderChunk("object-type");
+      Builder.AddTextChunk(" *");
+      Builder.AddChunk(CodeCompletionString::CK_RightParen);
+      Builder.AddTextChunk("object");
+      Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority, 
+                               CXCursor_ObjCInstanceMethodDecl));
+    }
+  }  
+
+  // - (void)addKey:(NSSet *)objects
+  if (IsInstanceMethod && ReturnTypeMatchesVoid) {
+    std::string SelectorName = (Twine("add") + UpperKey).str();
+    IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
+    if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
+      if (ReturnType.isNull()) {
+        Builder.AddChunk(CodeCompletionString::CK_LeftParen);
+        Builder.AddTextChunk("void");
+        Builder.AddChunk(CodeCompletionString::CK_RightParen);
+      }
+      
+      Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
+      Builder.AddChunk(CodeCompletionString::CK_LeftParen);
+      Builder.AddTextChunk("NSSet *");
+      Builder.AddChunk(CodeCompletionString::CK_RightParen);
+      Builder.AddTextChunk("objects");
+      Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority, 
+                               CXCursor_ObjCInstanceMethodDecl));
+    }
+  }  
+  
+  // - (void)removeKeyObject:(type *)object
+  if (IsInstanceMethod && ReturnTypeMatchesVoid) {
+    std::string SelectorName
+      = (Twine("remove") + UpperKey + Twine("Object")).str();
+    IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
+    if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
+      if (ReturnType.isNull()) {
+        Builder.AddChunk(CodeCompletionString::CK_LeftParen);
+        Builder.AddTextChunk("void");
+        Builder.AddChunk(CodeCompletionString::CK_RightParen);
+      }
+      
+      Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
+      Builder.AddChunk(CodeCompletionString::CK_LeftParen);
+      Builder.AddPlaceholderChunk("object-type");
+      Builder.AddTextChunk(" *");
+      Builder.AddChunk(CodeCompletionString::CK_RightParen);
+      Builder.AddTextChunk("object");
+      Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority, 
+                               CXCursor_ObjCInstanceMethodDecl));
+    }
+  }  
+  
+  // - (void)removeKey:(NSSet *)objects
+  if (IsInstanceMethod && ReturnTypeMatchesVoid) {
+    std::string SelectorName = (Twine("remove") + UpperKey).str();
+    IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
+    if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
+      if (ReturnType.isNull()) {
+        Builder.AddChunk(CodeCompletionString::CK_LeftParen);
+        Builder.AddTextChunk("void");
+        Builder.AddChunk(CodeCompletionString::CK_RightParen);
+      }
+      
+      Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
+      Builder.AddChunk(CodeCompletionString::CK_LeftParen);
+      Builder.AddTextChunk("NSSet *");
+      Builder.AddChunk(CodeCompletionString::CK_RightParen);
+      Builder.AddTextChunk("objects");
+      Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority, 
+                               CXCursor_ObjCInstanceMethodDecl));
+    }
+  }    
+
+  // - (void)intersectKey:(NSSet *)objects
+  if (IsInstanceMethod && ReturnTypeMatchesVoid) {
+    std::string SelectorName = (Twine("intersect") + UpperKey).str();
+    IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
+    if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
+      if (ReturnType.isNull()) {
+        Builder.AddChunk(CodeCompletionString::CK_LeftParen);
+        Builder.AddTextChunk("void");
+        Builder.AddChunk(CodeCompletionString::CK_RightParen);
+      }
+      
+      Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
+      Builder.AddChunk(CodeCompletionString::CK_LeftParen);
+      Builder.AddTextChunk("NSSet *");
+      Builder.AddChunk(CodeCompletionString::CK_RightParen);
+      Builder.AddTextChunk("objects");
+      Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority, 
+                               CXCursor_ObjCInstanceMethodDecl));
+    }
+  }  
+  
+  // Key-Value Observing
+  // + (NSSet *)keyPathsForValuesAffectingKey
+  if (!IsInstanceMethod && 
+      (ReturnType.isNull() || 
+       (ReturnType->isObjCObjectPointerType() &&
+        ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl() &&
+        ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl()
+                                                    ->getName() == "NSSet"))) {
+    std::string SelectorName 
+      = (Twine("keyPathsForValuesAffecting") + UpperKey).str();
+    IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
+    if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))) {
+      if (ReturnType.isNull()) {
+        Builder.AddChunk(CodeCompletionString::CK_LeftParen);
+        Builder.AddTextChunk("NSSet *");
+        Builder.AddChunk(CodeCompletionString::CK_RightParen);
+      }
+       
+      Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName));
+      Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern, 
+                              CXCursor_ObjCClassMethodDecl));
+    }
+  }
+
+  // + (BOOL)automaticallyNotifiesObserversForKey
+  if (!IsInstanceMethod &&
+      (ReturnType.isNull() ||
+       ReturnType->isIntegerType() || 
+       ReturnType->isBooleanType())) {
+    std::string SelectorName 
+      = (Twine("automaticallyNotifiesObserversOf") + UpperKey).str();
+    IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
+    if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))) {
+      if (ReturnType.isNull()) {
+        Builder.AddChunk(CodeCompletionString::CK_LeftParen);
+        Builder.AddTextChunk("BOOL");
+        Builder.AddChunk(CodeCompletionString::CK_RightParen);
+      }
+       
+      Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName));
+      Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern, 
+                              CXCursor_ObjCClassMethodDecl));
+    }
+  }
+}
+
+void Sema::CodeCompleteObjCMethodDecl(Scope *S, 
+                                      bool IsInstanceMethod,
+                                      ParsedType ReturnTy) {
+  // Determine the return type of the method we're declaring, if
+  // provided.
+  QualType ReturnType = GetTypeFromParser(ReturnTy);
+  Decl *IDecl = 0;
+  if (CurContext->isObjCContainer()) {
+      ObjCContainerDecl *OCD = dyn_cast<ObjCContainerDecl>(CurContext);
+      IDecl = cast<Decl>(OCD);
+  }
+  // Determine where we should start searching for methods.
+  ObjCContainerDecl *SearchDecl = 0;
+  bool IsInImplementation = false;
+  if (Decl *D = IDecl) {
+    if (ObjCImplementationDecl *Impl = dyn_cast<ObjCImplementationDecl>(D)) {
+      SearchDecl = Impl->getClassInterface();
+      IsInImplementation = true;
+    } else if (ObjCCategoryImplDecl *CatImpl 
+                                         = dyn_cast<ObjCCategoryImplDecl>(D)) {
+      SearchDecl = CatImpl->getCategoryDecl();
+      IsInImplementation = true;
+    } else
+      SearchDecl = dyn_cast<ObjCContainerDecl>(D);
+  }
+
+  if (!SearchDecl && S) {
+    if (DeclContext *DC = static_cast<DeclContext *>(S->getEntity()))
+      SearchDecl = dyn_cast<ObjCContainerDecl>(DC);
+  }
+
+  if (!SearchDecl) {
+    HandleCodeCompleteResults(this, CodeCompleter, 
+                              CodeCompletionContext::CCC_Other,
+                              0, 0);
+    return;
+  }
+    
+  // Find all of the methods that we could declare/implement here.
+  KnownMethodsMap KnownMethods;
+  FindImplementableMethods(Context, SearchDecl, IsInstanceMethod, 
+                           ReturnType, KnownMethods);
+  
+  // Add declarations or definitions for each of the known methods.
+  typedef CodeCompletionResult Result;
+  ResultBuilder Results(*this, CodeCompleter->getAllocator(),
+                        CodeCompleter->getCodeCompletionTUInfo(),
+                        CodeCompletionContext::CCC_Other);
+  Results.EnterNewScope();
+  PrintingPolicy Policy = getCompletionPrintingPolicy(*this);
+  for (KnownMethodsMap::iterator M = KnownMethods.begin(), 
+                              MEnd = KnownMethods.end();
+       M != MEnd; ++M) {
+    ObjCMethodDecl *Method = M->second.first;
+    CodeCompletionBuilder Builder(Results.getAllocator(),
+                                  Results.getCodeCompletionTUInfo());
+    
+    // If the result type was not already provided, add it to the
+    // pattern as (type).
+    if (ReturnType.isNull())
+      AddObjCPassingTypeChunk(Method->getResultType(),
+                              Method->getObjCDeclQualifier(),
+                              Context, Policy,
+                              Builder); 
+
+    Selector Sel = Method->getSelector();
+
+    // Add the first part of the selector to the pattern.
+    Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
+                                                       Sel.getNameForSlot(0)));
+
+    // Add parameters to the pattern.
+    unsigned I = 0;
+    for (ObjCMethodDecl::param_iterator P = Method->param_begin(), 
+                                     PEnd = Method->param_end();
+         P != PEnd; (void)++P, ++I) {
+      // Add the part of the selector name.
+      if (I == 0)
+        Builder.AddTypedTextChunk(":");
+      else if (I < Sel.getNumArgs()) {
+        Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
+        Builder.AddTypedTextChunk(
+                Builder.getAllocator().CopyString(Sel.getNameForSlot(I) + ":"));
+      } else
+        break;
+
+      // Add the parameter type.
+      AddObjCPassingTypeChunk((*P)->getOriginalType(),
+                              (*P)->getObjCDeclQualifier(),
+                              Context, Policy,
+                              Builder);
+      
+      if (IdentifierInfo *Id = (*P)->getIdentifier())
+        Builder.AddTextChunk(Builder.getAllocator().CopyString( Id->getName())); 
+    }
+
+    if (Method->isVariadic()) {
+      if (Method->param_size() > 0)
+        Builder.AddChunk(CodeCompletionString::CK_Comma);
+      Builder.AddTextChunk("...");
+    }        
+
+    if (IsInImplementation && Results.includeCodePatterns()) {
+      // We will be defining the method here, so add a compound statement.
+      Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
+      Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
+      Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
+      if (!Method->getResultType()->isVoidType()) {
+        // If the result type is not void, add a return clause.
+        Builder.AddTextChunk("return");
+        Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
+        Builder.AddPlaceholderChunk("expression");
+        Builder.AddChunk(CodeCompletionString::CK_SemiColon);
+      } else
+        Builder.AddPlaceholderChunk("statements");
+        
+      Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
+      Builder.AddChunk(CodeCompletionString::CK_RightBrace);
+    }
+
+    unsigned Priority = CCP_CodePattern;
+    if (!M->second.second)
+      Priority += CCD_InBaseClass;
+    
+    Results.AddResult(Result(Builder.TakeString(), Method, Priority));
+  }
+
+  // Add Key-Value-Coding and Key-Value-Observing accessor methods for all of 
+  // the properties in this class and its categories.
+  if (Context.getLangOpts().ObjC2) {
+    SmallVector<ObjCContainerDecl *, 4> Containers;
+    Containers.push_back(SearchDecl);
+    
+    VisitedSelectorSet KnownSelectors;
+    for (KnownMethodsMap::iterator M = KnownMethods.begin(), 
+                                MEnd = KnownMethods.end();
+         M != MEnd; ++M)
+      KnownSelectors.insert(M->first);
+
+    
+    ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(SearchDecl);
+    if (!IFace)
+      if (ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(SearchDecl))
+        IFace = Category->getClassInterface();
+    
+    if (IFace) {
+      for (ObjCCategoryDecl *Category = IFace->getCategoryList(); Category;
+           Category = Category->getNextClassCategory())
+        Containers.push_back(Category);
+    }
+    
+    for (unsigned I = 0, N = Containers.size(); I != N; ++I) {
+      for (ObjCContainerDecl::prop_iterator P = Containers[I]->prop_begin(),
+                                         PEnd = Containers[I]->prop_end(); 
+           P != PEnd; ++P) {
+        AddObjCKeyValueCompletions(*P, IsInstanceMethod, ReturnType, Context, 
+                                   KnownSelectors, Results);
+      }
+    }
+  }
+  
+  Results.ExitScope();
+  
+  HandleCodeCompleteResults(this, CodeCompleter, 
+                            CodeCompletionContext::CCC_Other,
+                            Results.data(),Results.size());
+}
+
+void Sema::CodeCompleteObjCMethodDeclSelector(Scope *S, 
+                                              bool IsInstanceMethod,
+                                              bool AtParameterName,
+                                              ParsedType ReturnTy,
+                                              IdentifierInfo **SelIdents,
+                                              unsigned NumSelIdents) {
+  // If we have an external source, load the entire class method
+  // pool from the AST file.
+  if (ExternalSource) {
+    for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors();
+         I != N; ++I) {
+      Selector Sel = ExternalSource->GetExternalSelector(I);
+      if (Sel.isNull() || MethodPool.count(Sel))
+        continue;
+
+      ReadMethodPool(Sel);
+    }
+  }
+
+  // Build the set of methods we can see.
+  typedef CodeCompletionResult Result;
+  ResultBuilder Results(*this, CodeCompleter->getAllocator(),
+                        CodeCompleter->getCodeCompletionTUInfo(),
+                        CodeCompletionContext::CCC_Other);
+  
+  if (ReturnTy)
+    Results.setPreferredType(GetTypeFromParser(ReturnTy).getNonReferenceType());
+
+  Results.EnterNewScope();  
+  for (GlobalMethodPool::iterator M = MethodPool.begin(),
+                                  MEnd = MethodPool.end();
+       M != MEnd; ++M) {
+    for (ObjCMethodList *MethList = IsInstanceMethod ? &M->second.first :
+                                                       &M->second.second;
+         MethList && MethList->Method; 
+         MethList = MethList->Next) {
+      if (!isAcceptableObjCMethod(MethList->Method, MK_Any, SelIdents, 
+                                  NumSelIdents))
+        continue;
+      
+      if (AtParameterName) {
+        // Suggest parameter names we've seen before.
+        if (NumSelIdents && NumSelIdents <= MethList->Method->param_size()) {
+          ParmVarDecl *Param = MethList->Method->param_begin()[NumSelIdents-1];
+          if (Param->getIdentifier()) {
+            CodeCompletionBuilder Builder(Results.getAllocator(),
+                                          Results.getCodeCompletionTUInfo());
+            Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
+                                           Param->getIdentifier()->getName()));
+            Results.AddResult(Builder.TakeString());
+          }
+        }
+        
+        continue;
+      }
+      
+      Result R(MethList->Method, 0);
+      R.StartParameter = NumSelIdents;
+      R.AllParametersAreInformative = false;
+      R.DeclaringEntity = true;
+      Results.MaybeAddResult(R, CurContext);
+    }
+  }
+  
+  Results.ExitScope();
+  HandleCodeCompleteResults(this, CodeCompleter, 
+                            CodeCompletionContext::CCC_Other,
+                            Results.data(),Results.size());
+}
+
+void Sema::CodeCompletePreprocessorDirective(bool InConditional) {
+  ResultBuilder Results(*this, CodeCompleter->getAllocator(),
+                        CodeCompleter->getCodeCompletionTUInfo(),
+                        CodeCompletionContext::CCC_PreprocessorDirective);
+  Results.EnterNewScope();
+  
+  // #if <condition>
+  CodeCompletionBuilder Builder(Results.getAllocator(),
+                                Results.getCodeCompletionTUInfo());
+  Builder.AddTypedTextChunk("if");
+  Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
+  Builder.AddPlaceholderChunk("condition");
+  Results.AddResult(Builder.TakeString());
+  
+  // #ifdef <macro>
+  Builder.AddTypedTextChunk("ifdef");
+  Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
+  Builder.AddPlaceholderChunk("macro");
+  Results.AddResult(Builder.TakeString());
+  
+  // #ifndef <macro>
+  Builder.AddTypedTextChunk("ifndef");
+  Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
+  Builder.AddPlaceholderChunk("macro");
+  Results.AddResult(Builder.TakeString());
+
+  if (InConditional) {
+    // #elif <condition>
+    Builder.AddTypedTextChunk("elif");
+    Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
+    Builder.AddPlaceholderChunk("condition");
+    Results.AddResult(Builder.TakeString());
+
+    // #else
+    Builder.AddTypedTextChunk("else");
+    Results.AddResult(Builder.TakeString());
+
+    // #endif
+    Builder.AddTypedTextChunk("endif");
+    Results.AddResult(Builder.TakeString());
+  }
+  
+  // #include "header"
+  Builder.AddTypedTextChunk("include");
+  Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
+  Builder.AddTextChunk("\"");
+  Builder.AddPlaceholderChunk("header");
+  Builder.AddTextChunk("\"");
+  Results.AddResult(Builder.TakeString());
+
+  // #include <header>
+  Builder.AddTypedTextChunk("include");
+  Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
+  Builder.AddTextChunk("<");
+  Builder.AddPlaceholderChunk("header");
+  Builder.AddTextChunk(">");
+  Results.AddResult(Builder.TakeString());
+  
+  // #define <macro>
+  Builder.AddTypedTextChunk("define");
+  Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
+  Builder.AddPlaceholderChunk("macro");
+  Results.AddResult(Builder.TakeString());
+  
+  // #define <macro>(<args>)
+  Builder.AddTypedTextChunk("define");
+  Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
+  Builder.AddPlaceholderChunk("macro");
+  Builder.AddChunk(CodeCompletionString::CK_LeftParen);
+  Builder.AddPlaceholderChunk("args");
+  Builder.AddChunk(CodeCompletionString::CK_RightParen);
+  Results.AddResult(Builder.TakeString());
+  
+  // #undef <macro>
+  Builder.AddTypedTextChunk("undef");
+  Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
+  Builder.AddPlaceholderChunk("macro");
+  Results.AddResult(Builder.TakeString());
+
+  // #line <number>
+  Builder.AddTypedTextChunk("line");
+  Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
+  Builder.AddPlaceholderChunk("number");
+  Results.AddResult(Builder.TakeString());
+  
+  // #line <number> "filename"
+  Builder.AddTypedTextChunk("line");
+  Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
+  Builder.AddPlaceholderChunk("number");
+  Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
+  Builder.AddTextChunk("\"");
+  Builder.AddPlaceholderChunk("filename");
+  Builder.AddTextChunk("\"");
+  Results.AddResult(Builder.TakeString());
+  
+  // #error <message>
+  Builder.AddTypedTextChunk("error");
+  Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
+  Builder.AddPlaceholderChunk("message");
+  Results.AddResult(Builder.TakeString());
+
+  // #pragma <arguments>
+  Builder.AddTypedTextChunk("pragma");
+  Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
+  Builder.AddPlaceholderChunk("arguments");
+  Results.AddResult(Builder.TakeString());
+
+  if (getLangOpts().ObjC1) {
+    // #import "header"
+    Builder.AddTypedTextChunk("import");
+    Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
+    Builder.AddTextChunk("\"");
+    Builder.AddPlaceholderChunk("header");
+    Builder.AddTextChunk("\"");
+    Results.AddResult(Builder.TakeString());
+    
+    // #import <header>
+    Builder.AddTypedTextChunk("import");
+    Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
+    Builder.AddTextChunk("<");
+    Builder.AddPlaceholderChunk("header");
+    Builder.AddTextChunk(">");
+    Results.AddResult(Builder.TakeString());
+  }
+  
+  // #include_next "header"
+  Builder.AddTypedTextChunk("include_next");
+  Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
+  Builder.AddTextChunk("\"");
+  Builder.AddPlaceholderChunk("header");
+  Builder.AddTextChunk("\"");
+  Results.AddResult(Builder.TakeString());
+  
+  // #include_next <header>
+  Builder.AddTypedTextChunk("include_next");
+  Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
+  Builder.AddTextChunk("<");
+  Builder.AddPlaceholderChunk("header");
+  Builder.AddTextChunk(">");
+  Results.AddResult(Builder.TakeString());
+
+  // #warning <message>
+  Builder.AddTypedTextChunk("warning");
+  Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
+  Builder.AddPlaceholderChunk("message");
+  Results.AddResult(Builder.TakeString());
+
+  // Note: #ident and #sccs are such crazy anachronisms that we don't provide
+  // completions for them. And __include_macros is a Clang-internal extension
+  // that we don't want to encourage anyone to use.
+
+  // FIXME: we don't support #assert or #unassert, so don't suggest them.
+  Results.ExitScope();
+  
+  HandleCodeCompleteResults(this, CodeCompleter, 
+                            CodeCompletionContext::CCC_PreprocessorDirective,
+                            Results.data(), Results.size());
+}
+
+void Sema::CodeCompleteInPreprocessorConditionalExclusion(Scope *S) {
+  CodeCompleteOrdinaryName(S,
+                           S->getFnParent()? Sema::PCC_RecoveryInFunction 
+                                           : Sema::PCC_Namespace);
+}
+
+void Sema::CodeCompletePreprocessorMacroName(bool IsDefinition) {
+  ResultBuilder Results(*this, CodeCompleter->getAllocator(),
+                        CodeCompleter->getCodeCompletionTUInfo(),
+                        IsDefinition? CodeCompletionContext::CCC_MacroName
+                                    : CodeCompletionContext::CCC_MacroNameUse);
+  if (!IsDefinition && (!CodeCompleter || CodeCompleter->includeMacros())) {
+    // Add just the names of macros, not their arguments.    
+    CodeCompletionBuilder Builder(Results.getAllocator(),
+                                  Results.getCodeCompletionTUInfo());
+    Results.EnterNewScope();
+    for (Preprocessor::macro_iterator M = PP.macro_begin(), 
+                                   MEnd = PP.macro_end();
+         M != MEnd; ++M) {
+      Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
+                                           M->first->getName()));
+      Results.AddResult(Builder.TakeString());
+    }
+    Results.ExitScope();
+  } else if (IsDefinition) {
+    // FIXME: Can we detect when the user just wrote an include guard above?
+  }
+  
+  HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
+                            Results.data(), Results.size()); 
+}
+
+void Sema::CodeCompletePreprocessorExpression() {
+  ResultBuilder Results(*this, CodeCompleter->getAllocator(),
+                        CodeCompleter->getCodeCompletionTUInfo(),
+                        CodeCompletionContext::CCC_PreprocessorExpression);
+  
+  if (!CodeCompleter || CodeCompleter->includeMacros())
+    AddMacroResults(PP, Results);
+  
+    // defined (<macro>)
+  Results.EnterNewScope();
+  CodeCompletionBuilder Builder(Results.getAllocator(),
+                                Results.getCodeCompletionTUInfo());
+  Builder.AddTypedTextChunk("defined");
+  Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
+  Builder.AddChunk(CodeCompletionString::CK_LeftParen);
+  Builder.AddPlaceholderChunk("macro");
+  Builder.AddChunk(CodeCompletionString::CK_RightParen);
+  Results.AddResult(Builder.TakeString());
+  Results.ExitScope();
+  
+  HandleCodeCompleteResults(this, CodeCompleter, 
+                            CodeCompletionContext::CCC_PreprocessorExpression,
+                            Results.data(), Results.size()); 
+}
+
+void Sema::CodeCompletePreprocessorMacroArgument(Scope *S,
+                                                 IdentifierInfo *Macro,
+                                                 MacroInfo *MacroInfo,
+                                                 unsigned Argument) {
+  // FIXME: In the future, we could provide "overload" results, much like we
+  // do for function calls.
+  
+  // Now just ignore this. There will be another code-completion callback
+  // for the expanded tokens.
+}
+
+void Sema::CodeCompleteNaturalLanguage() {
+  HandleCodeCompleteResults(this, CodeCompleter,
+                            CodeCompletionContext::CCC_NaturalLanguage,
+                            0, 0);
+}
+
+void Sema::GatherGlobalCodeCompletions(CodeCompletionAllocator &Allocator,
+                                       CodeCompletionTUInfo &CCTUInfo,
+                 SmallVectorImpl<CodeCompletionResult> &Results) {
+  ResultBuilder Builder(*this, Allocator, CCTUInfo,
+                        CodeCompletionContext::CCC_Recovery);
+  if (!CodeCompleter || CodeCompleter->includeGlobals()) {
+    CodeCompletionDeclConsumer Consumer(Builder, 
+                                        Context.getTranslationUnitDecl());
+    LookupVisibleDecls(Context.getTranslationUnitDecl(), LookupAnyName, 
+                       Consumer);
+  }
+  
+  if (!CodeCompleter || CodeCompleter->includeMacros())
+    AddMacroResults(PP, Builder);
+  
+  Results.clear();
+  Results.insert(Results.end(), 
+                 Builder.data(), Builder.data() + Builder.size());
+}
diff --git a/clang/lib/Sema/SemaConsumer.cpp b/clang/lib/Sema/SemaConsumer.cpp
new file mode 100644
index 0000000..d83a13e
--- /dev/null
+++ b/clang/lib/Sema/SemaConsumer.cpp
@@ -0,0 +1,14 @@
+//===-- SemaConsumer.cpp - Abstract interface for AST semantics -*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Sema/SemaConsumer.h"
+
+using namespace clang;
+
+void SemaConsumer::anchor() { }
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
new file mode 100644
index 0000000..1227e92
--- /dev/null
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -0,0 +1,10462 @@
+//===--- SemaDecl.cpp - Semantic Analysis for Declarations ----------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+//  This file implements semantic analysis for declarations.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Sema/SemaInternal.h"
+#include "clang/Sema/Initialization.h"
+#include "clang/Sema/Lookup.h"
+#include "clang/Sema/CXXFieldCollector.h"
+#include "clang/Sema/Scope.h"
+#include "clang/Sema/ScopeInfo.h"
+#include "TypeLocBuilder.h"
+#include "clang/AST/ASTConsumer.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/CXXInheritance.h"
+#include "clang/AST/DeclCXX.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/AST/DeclTemplate.h"
+#include "clang/AST/EvaluatedExprVisitor.h"
+#include "clang/AST/ExprCXX.h"
+#include "clang/AST/StmtCXX.h"
+#include "clang/AST/CharUnits.h"
+#include "clang/Sema/DeclSpec.h"
+#include "clang/Sema/ParsedTemplate.h"
+#include "clang/Parse/ParseDiagnostic.h"
+#include "clang/Basic/PartialDiagnostic.h"
+#include "clang/Sema/DelayedDiagnostic.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Basic/TargetInfo.h"
+// FIXME: layering (ideally, Sema shouldn't be dependent on Lex API's)
+#include "clang/Lex/Preprocessor.h"
+#include "clang/Lex/HeaderSearch.h"
+#include "clang/Lex/ModuleLoader.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/Triple.h"
+#include <algorithm>
+#include <cstring>
+#include <functional>
+using namespace clang;
+using namespace sema;
+
+Sema::DeclGroupPtrTy Sema::ConvertDeclToDeclGroup(Decl *Ptr, Decl *OwnedType) {
+  if (OwnedType) {
+    Decl *Group[2] = { OwnedType, Ptr };
+    return DeclGroupPtrTy::make(DeclGroupRef::Create(Context, Group, 2));
+  }
+
+  return DeclGroupPtrTy::make(DeclGroupRef(Ptr));
+}
+
+namespace {
+
+class TypeNameValidatorCCC : public CorrectionCandidateCallback {
+ public:
+  TypeNameValidatorCCC(bool AllowInvalid) : AllowInvalidDecl(AllowInvalid) {
+    WantExpressionKeywords = false;
+    WantCXXNamedCasts = false;
+    WantRemainingKeywords = false;
+  }
+
+  virtual bool ValidateCandidate(const TypoCorrection &candidate) {
+    if (NamedDecl *ND = candidate.getCorrectionDecl())
+      return (isa<TypeDecl>(ND) || isa<ObjCInterfaceDecl>(ND)) &&
+          (AllowInvalidDecl || !ND->isInvalidDecl());
+    else
+      return candidate.isKeyword();
+  }
+
+ private:
+  bool AllowInvalidDecl;
+};
+
+}
+
+/// \brief If the identifier refers to a type name within this scope,
+/// return the declaration of that type.
+///
+/// This routine performs ordinary name lookup of the identifier II
+/// within the given scope, with optional C++ scope specifier SS, to
+/// determine whether the name refers to a type. If so, returns an
+/// opaque pointer (actually a QualType) corresponding to that
+/// type. Otherwise, returns NULL.
+///
+/// If name lookup results in an ambiguity, this routine will complain
+/// and then return NULL.
+ParsedType Sema::getTypeName(IdentifierInfo &II, SourceLocation NameLoc,
+                             Scope *S, CXXScopeSpec *SS,
+                             bool isClassName, bool HasTrailingDot,
+                             ParsedType ObjectTypePtr,
+                             bool IsCtorOrDtorName,
+                             bool WantNontrivialTypeSourceInfo,
+                             IdentifierInfo **CorrectedII) {
+  // Determine where we will perform name lookup.
+  DeclContext *LookupCtx = 0;
+  if (ObjectTypePtr) {
+    QualType ObjectType = ObjectTypePtr.get();
+    if (ObjectType->isRecordType())
+      LookupCtx = computeDeclContext(ObjectType);
+  } else if (SS && SS->isNotEmpty()) {
+    LookupCtx = computeDeclContext(*SS, false);
+
+    if (!LookupCtx) {
+      if (isDependentScopeSpecifier(*SS)) {
+        // C++ [temp.res]p3:
+        //   A qualified-id that refers to a type and in which the
+        //   nested-name-specifier depends on a template-parameter (14.6.2)
+        //   shall be prefixed by the keyword typename to indicate that the
+        //   qualified-id denotes a type, forming an
+        //   elaborated-type-specifier (7.1.5.3).
+        //
+        // We therefore do not perform any name lookup if the result would
+        // refer to a member of an unknown specialization.
+        if (!isClassName && !IsCtorOrDtorName)
+          return ParsedType();
+        
+        // We know from the grammar that this name refers to a type,
+        // so build a dependent node to describe the type.
+        if (WantNontrivialTypeSourceInfo)
+          return ActOnTypenameType(S, SourceLocation(), *SS, II, NameLoc).get();
+        
+        NestedNameSpecifierLoc QualifierLoc = SS->getWithLocInContext(Context);
+        QualType T =
+          CheckTypenameType(ETK_None, SourceLocation(), QualifierLoc,
+                            II, NameLoc);
+        
+          return ParsedType::make(T);
+      }
+      
+      return ParsedType();
+    }
+    
+    if (!LookupCtx->isDependentContext() &&
+        RequireCompleteDeclContext(*SS, LookupCtx))
+      return ParsedType();
+  }
+
+  // FIXME: LookupNestedNameSpecifierName isn't the right kind of
+  // lookup for class-names.
+  LookupNameKind Kind = isClassName ? LookupNestedNameSpecifierName :
+                                      LookupOrdinaryName;
+  LookupResult Result(*this, &II, NameLoc, Kind);
+  if (LookupCtx) {
+    // Perform "qualified" name lookup into the declaration context we
+    // computed, which is either the type of the base of a member access
+    // expression or the declaration context associated with a prior
+    // nested-name-specifier.
+    LookupQualifiedName(Result, LookupCtx);
+
+    if (ObjectTypePtr && Result.empty()) {
+      // C++ [basic.lookup.classref]p3:
+      //   If the unqualified-id is ~type-name, the type-name is looked up
+      //   in the context of the entire postfix-expression. If the type T of 
+      //   the object expression is of a class type C, the type-name is also
+      //   looked up in the scope of class C. At least one of the lookups shall
+      //   find a name that refers to (possibly cv-qualified) T.
+      LookupName(Result, S);
+    }
+  } else {
+    // Perform unqualified name lookup.
+    LookupName(Result, S);
+  }
+  
+  NamedDecl *IIDecl = 0;
+  switch (Result.getResultKind()) {
+  case LookupResult::NotFound:
+  case LookupResult::NotFoundInCurrentInstantiation:
+    if (CorrectedII) {
+      TypeNameValidatorCCC Validator(true);
+      TypoCorrection Correction = CorrectTypo(Result.getLookupNameInfo(),
+                                              Kind, S, SS, Validator);
+      IdentifierInfo *NewII = Correction.getCorrectionAsIdentifierInfo();
+      TemplateTy Template;
+      bool MemberOfUnknownSpecialization;
+      UnqualifiedId TemplateName;
+      TemplateName.setIdentifier(NewII, NameLoc);
+      NestedNameSpecifier *NNS = Correction.getCorrectionSpecifier();
+      CXXScopeSpec NewSS, *NewSSPtr = SS;
+      if (SS && NNS) {
+        NewSS.MakeTrivial(Context, NNS, SourceRange(NameLoc));
+        NewSSPtr = &NewSS;
+      }
+      if (Correction && (NNS || NewII != &II) &&
+          // Ignore a correction to a template type as the to-be-corrected
+          // identifier is not a template (typo correction for template names
+          // is handled elsewhere).
+          !(getLangOpts().CPlusPlus && NewSSPtr &&
+            isTemplateName(S, *NewSSPtr, false, TemplateName, ParsedType(),
+                           false, Template, MemberOfUnknownSpecialization))) {
+        ParsedType Ty = getTypeName(*NewII, NameLoc, S, NewSSPtr,
+                                    isClassName, HasTrailingDot, ObjectTypePtr,
+                                    IsCtorOrDtorName,
+                                    WantNontrivialTypeSourceInfo);
+        if (Ty) {
+          std::string CorrectedStr(Correction.getAsString(getLangOpts()));
+          std::string CorrectedQuotedStr(
+              Correction.getQuoted(getLangOpts()));
+          Diag(NameLoc, diag::err_unknown_typename_suggest)
+              << Result.getLookupName() << CorrectedQuotedStr
+              << FixItHint::CreateReplacement(SourceRange(NameLoc),
+                                              CorrectedStr);
+          if (NamedDecl *FirstDecl = Correction.getCorrectionDecl())
+            Diag(FirstDecl->getLocation(), diag::note_previous_decl)
+              << CorrectedQuotedStr;
+
+          if (SS && NNS)
+            SS->MakeTrivial(Context, NNS, SourceRange(NameLoc));
+          *CorrectedII = NewII;
+          return Ty;
+        }
+      }
+    }
+    // If typo correction failed or was not performed, fall through
+  case LookupResult::FoundOverloaded:
+  case LookupResult::FoundUnresolvedValue:
+    Result.suppressDiagnostics();
+    return ParsedType();
+
+  case LookupResult::Ambiguous:
+    // Recover from type-hiding ambiguities by hiding the type.  We'll
+    // do the lookup again when looking for an object, and we can
+    // diagnose the error then.  If we don't do this, then the error
+    // about hiding the type will be immediately followed by an error
+    // that only makes sense if the identifier was treated like a type.
+    if (Result.getAmbiguityKind() == LookupResult::AmbiguousTagHiding) {
+      Result.suppressDiagnostics();
+      return ParsedType();
+    }
+
+    // Look to see if we have a type anywhere in the list of results.
+    for (LookupResult::iterator Res = Result.begin(), ResEnd = Result.end();
+         Res != ResEnd; ++Res) {
+      if (isa<TypeDecl>(*Res) || isa<ObjCInterfaceDecl>(*Res)) {
+        if (!IIDecl ||
+            (*Res)->getLocation().getRawEncoding() <
+              IIDecl->getLocation().getRawEncoding())
+          IIDecl = *Res;
+      }
+    }
+
+    if (!IIDecl) {
+      // None of the entities we found is a type, so there is no way
+      // to even assume that the result is a type. In this case, don't
+      // complain about the ambiguity. The parser will either try to
+      // perform this lookup again (e.g., as an object name), which
+      // will produce the ambiguity, or will complain that it expected
+      // a type name.
+      Result.suppressDiagnostics();
+      return ParsedType();
+    }
+
+    // We found a type within the ambiguous lookup; diagnose the
+    // ambiguity and then return that type. This might be the right
+    // answer, or it might not be, but it suppresses any attempt to
+    // perform the name lookup again.
+    break;
+
+  case LookupResult::Found:
+    IIDecl = Result.getFoundDecl();
+    break;
+  }
+
+  assert(IIDecl && "Didn't find decl");
+
+  QualType T;
+  if (TypeDecl *TD = dyn_cast<TypeDecl>(IIDecl)) {
+    DiagnoseUseOfDecl(IIDecl, NameLoc);
+
+    if (T.isNull())
+      T = Context.getTypeDeclType(TD);
+
+    // NOTE: avoid constructing an ElaboratedType(Loc) if this is a
+    // constructor or destructor name (in such a case, the scope specifier
+    // will be attached to the enclosing Expr or Decl node).
+    if (SS && SS->isNotEmpty() && !IsCtorOrDtorName) {
+      if (WantNontrivialTypeSourceInfo) {
+        // Construct a type with type-source information.
+        TypeLocBuilder Builder;
+        Builder.pushTypeSpec(T).setNameLoc(NameLoc);
+        
+        T = getElaboratedType(ETK_None, *SS, T);
+        ElaboratedTypeLoc ElabTL = Builder.push<ElaboratedTypeLoc>(T);
+        ElabTL.setElaboratedKeywordLoc(SourceLocation());
+        ElabTL.setQualifierLoc(SS->getWithLocInContext(Context));
+        return CreateParsedType(T, Builder.getTypeSourceInfo(Context, T));
+      } else {
+        T = getElaboratedType(ETK_None, *SS, T);
+      }
+    }
+  } else if (ObjCInterfaceDecl *IDecl = dyn_cast<ObjCInterfaceDecl>(IIDecl)) {
+    (void)DiagnoseUseOfDecl(IDecl, NameLoc);
+    if (!HasTrailingDot)
+      T = Context.getObjCInterfaceType(IDecl);
+  }
+
+  if (T.isNull()) {
+    // If it's not plausibly a type, suppress diagnostics.
+    Result.suppressDiagnostics();
+    return ParsedType();
+  }
+  return ParsedType::make(T);
+}
+
+/// isTagName() - This method is called *for error recovery purposes only*
+/// to determine if the specified name is a valid tag name ("struct foo").  If
+/// so, this returns the TST for the tag corresponding to it (TST_enum,
+/// TST_union, TST_struct, TST_class).  This is used to diagnose cases in C
+/// where the user forgot to specify the tag.
+DeclSpec::TST Sema::isTagName(IdentifierInfo &II, Scope *S) {
+  // Do a tag name lookup in this scope.
+  LookupResult R(*this, &II, SourceLocation(), LookupTagName);
+  LookupName(R, S, false);
+  R.suppressDiagnostics();
+  if (R.getResultKind() == LookupResult::Found)
+    if (const TagDecl *TD = R.getAsSingle<TagDecl>()) {
+      switch (TD->getTagKind()) {
+      case TTK_Struct: return DeclSpec::TST_struct;
+      case TTK_Union:  return DeclSpec::TST_union;
+      case TTK_Class:  return DeclSpec::TST_class;
+      case TTK_Enum:   return DeclSpec::TST_enum;
+      }
+    }
+
+  return DeclSpec::TST_unspecified;
+}
+
+/// isMicrosoftMissingTypename - In Microsoft mode, within class scope,
+/// if a CXXScopeSpec's type is equal to the type of one of the base classes
+/// then downgrade the missing typename error to a warning.
+/// This is needed for MSVC compatibility; Example:
+/// @code
+/// template<class T> class A {
+/// public:
+///   typedef int TYPE;
+/// };
+/// template<class T> class B : public A<T> {
+/// public:
+///   A<T>::TYPE a; // no typename required because A<T> is a base class.
+/// };
+/// @endcode
+bool Sema::isMicrosoftMissingTypename(const CXXScopeSpec *SS, Scope *S) {
+  if (CurContext->isRecord()) {
+    const Type *Ty = SS->getScopeRep()->getAsType();
+
+    CXXRecordDecl *RD = cast<CXXRecordDecl>(CurContext);
+    for (CXXRecordDecl::base_class_const_iterator Base = RD->bases_begin(),
+          BaseEnd = RD->bases_end(); Base != BaseEnd; ++Base)
+      if (Context.hasSameUnqualifiedType(QualType(Ty, 1), Base->getType()))
+        return true;
+    return S->isFunctionPrototypeScope();
+  } 
+  return CurContext->isFunctionOrMethod() || S->isFunctionPrototypeScope();
+}
+
+bool Sema::DiagnoseUnknownTypeName(const IdentifierInfo &II, 
+                                   SourceLocation IILoc,
+                                   Scope *S,
+                                   CXXScopeSpec *SS,
+                                   ParsedType &SuggestedType) {
+  // We don't have anything to suggest (yet).
+  SuggestedType = ParsedType();
+  
+  // There may have been a typo in the name of the type. Look up typo
+  // results, in case we have something that we can suggest.
+  TypeNameValidatorCCC Validator(false);
+  if (TypoCorrection Corrected = CorrectTypo(DeclarationNameInfo(&II, IILoc),
+                                             LookupOrdinaryName, S, SS,
+                                             Validator)) {
+    std::string CorrectedStr(Corrected.getAsString(getLangOpts()));
+    std::string CorrectedQuotedStr(Corrected.getQuoted(getLangOpts()));
+
+    if (Corrected.isKeyword()) {
+      // We corrected to a keyword.
+      // FIXME: Actually recover with the keyword we suggest, and emit a fix-it.
+      Diag(IILoc, diag::err_unknown_typename_suggest)
+        << &II << CorrectedQuotedStr;
+    } else {
+      NamedDecl *Result = Corrected.getCorrectionDecl();
+      // We found a similarly-named type or interface; suggest that.
+      if (!SS || !SS->isSet())
+        Diag(IILoc, diag::err_unknown_typename_suggest)
+          << &II << CorrectedQuotedStr
+          << FixItHint::CreateReplacement(SourceRange(IILoc), CorrectedStr);
+      else if (DeclContext *DC = computeDeclContext(*SS, false))
+        Diag(IILoc, diag::err_unknown_nested_typename_suggest)
+          << &II << DC << CorrectedQuotedStr << SS->getRange()
+          << FixItHint::CreateReplacement(SourceRange(IILoc), CorrectedStr);
+      else
+        llvm_unreachable("could not have corrected a typo here");
+
+      Diag(Result->getLocation(), diag::note_previous_decl)
+        << CorrectedQuotedStr;
+
+      SuggestedType = getTypeName(*Result->getIdentifier(), IILoc, S, SS,
+                                  false, false, ParsedType(),
+                                  /*IsCtorOrDtorName=*/false,
+                                  /*NonTrivialTypeSourceInfo=*/true);
+    }
+    return true;
+  }
+
+  if (getLangOpts().CPlusPlus) {
+    // See if II is a class template that the user forgot to pass arguments to.
+    UnqualifiedId Name;
+    Name.setIdentifier(&II, IILoc);
+    CXXScopeSpec EmptySS;
+    TemplateTy TemplateResult;
+    bool MemberOfUnknownSpecialization;
+    if (isTemplateName(S, SS ? *SS : EmptySS, /*hasTemplateKeyword=*/false,
+                       Name, ParsedType(), true, TemplateResult,
+                       MemberOfUnknownSpecialization) == TNK_Type_template) {
+      TemplateName TplName = TemplateResult.getAsVal<TemplateName>();
+      Diag(IILoc, diag::err_template_missing_args) << TplName;
+      if (TemplateDecl *TplDecl = TplName.getAsTemplateDecl()) {
+        Diag(TplDecl->getLocation(), diag::note_template_decl_here)
+          << TplDecl->getTemplateParameters()->getSourceRange();
+      }
+      return true;
+    }
+  }
+
+  // FIXME: Should we move the logic that tries to recover from a missing tag
+  // (struct, union, enum) from Parser::ParseImplicitInt here, instead?
+  
+  if (!SS || (!SS->isSet() && !SS->isInvalid()))
+    Diag(IILoc, diag::err_unknown_typename) << &II;
+  else if (DeclContext *DC = computeDeclContext(*SS, false))
+    Diag(IILoc, diag::err_typename_nested_not_found) 
+      << &II << DC << SS->getRange();
+  else if (isDependentScopeSpecifier(*SS)) {
+    unsigned DiagID = diag::err_typename_missing;
+    if (getLangOpts().MicrosoftMode && isMicrosoftMissingTypename(SS, S))
+      DiagID = diag::warn_typename_missing;
+
+    Diag(SS->getRange().getBegin(), DiagID)
+      << (NestedNameSpecifier *)SS->getScopeRep() << II.getName()
+      << SourceRange(SS->getRange().getBegin(), IILoc)
+      << FixItHint::CreateInsertion(SS->getRange().getBegin(), "typename ");
+    SuggestedType = ActOnTypenameType(S, SourceLocation(), *SS, II, IILoc)
+                                                                         .get();
+  } else {
+    assert(SS && SS->isInvalid() && 
+           "Invalid scope specifier has already been diagnosed");
+  }
+  
+  return true;
+}
+
+/// \brief Determine whether the given result set contains either a type name
+/// or 
+static bool isResultTypeOrTemplate(LookupResult &R, const Token &NextToken) {
+  bool CheckTemplate = R.getSema().getLangOpts().CPlusPlus &&
+                       NextToken.is(tok::less);
+  
+  for (LookupResult::iterator I = R.begin(), IEnd = R.end(); I != IEnd; ++I) {
+    if (isa<TypeDecl>(*I) || isa<ObjCInterfaceDecl>(*I))
+      return true;
+    
+    if (CheckTemplate && isa<TemplateDecl>(*I))
+      return true;
+  }
+  
+  return false;
+}
+
+Sema::NameClassification Sema::ClassifyName(Scope *S,
+                                            CXXScopeSpec &SS,
+                                            IdentifierInfo *&Name,
+                                            SourceLocation NameLoc,
+                                            const Token &NextToken) {
+  DeclarationNameInfo NameInfo(Name, NameLoc);
+  ObjCMethodDecl *CurMethod = getCurMethodDecl();
+  
+  if (NextToken.is(tok::coloncolon)) {
+    BuildCXXNestedNameSpecifier(S, *Name, NameLoc, NextToken.getLocation(),
+                                QualType(), false, SS, 0, false);
+    
+  }
+      
+  LookupResult Result(*this, Name, NameLoc, LookupOrdinaryName);
+  LookupParsedName(Result, S, &SS, !CurMethod);
+  
+  // Perform lookup for Objective-C instance variables (including automatically 
+  // synthesized instance variables), if we're in an Objective-C method.
+  // FIXME: This lookup really, really needs to be folded in to the normal
+  // unqualified lookup mechanism.
+  if (!SS.isSet() && CurMethod && !isResultTypeOrTemplate(Result, NextToken)) {
+    ExprResult E = LookupInObjCMethod(Result, S, Name, true);
+    if (E.get() || E.isInvalid())
+      return E;
+  }
+  
+  bool SecondTry = false;
+  bool IsFilteredTemplateName = false;
+  
+Corrected:
+  switch (Result.getResultKind()) {
+  case LookupResult::NotFound:
+    // If an unqualified-id is followed by a '(', then we have a function
+    // call.
+    if (!SS.isSet() && NextToken.is(tok::l_paren)) {
+      // In C++, this is an ADL-only call.
+      // FIXME: Reference?
+      if (getLangOpts().CPlusPlus)
+        return BuildDeclarationNameExpr(SS, Result, /*ADL=*/true);
+      
+      // C90 6.3.2.2:
+      //   If the expression that precedes the parenthesized argument list in a 
+      //   function call consists solely of an identifier, and if no 
+      //   declaration is visible for this identifier, the identifier is 
+      //   implicitly declared exactly as if, in the innermost block containing
+      //   the function call, the declaration
+      //
+      //     extern int identifier (); 
+      //
+      //   appeared. 
+      // 
+      // We also allow this in C99 as an extension.
+      if (NamedDecl *D = ImplicitlyDefineFunction(NameLoc, *Name, S)) {
+        Result.addDecl(D);
+        Result.resolveKind();
+        return BuildDeclarationNameExpr(SS, Result, /*ADL=*/false);
+      }
+    }
+    
+    // In C, we first see whether there is a tag type by the same name, in 
+    // which case it's likely that the user just forget to write "enum", 
+    // "struct", or "union".
+    if (!getLangOpts().CPlusPlus && !SecondTry) {
+      Result.clear(LookupTagName);
+      LookupParsedName(Result, S, &SS);
+      if (TagDecl *Tag = Result.getAsSingle<TagDecl>()) {
+        const char *TagName = 0;
+        const char *FixItTagName = 0;
+        switch (Tag->getTagKind()) {
+          case TTK_Class:
+            TagName = "class";
+            FixItTagName = "class ";
+            break;
+
+          case TTK_Enum:
+            TagName = "enum";
+            FixItTagName = "enum ";
+            break;
+            
+          case TTK_Struct:
+            TagName = "struct";
+            FixItTagName = "struct ";
+            break;
+            
+          case TTK_Union:
+            TagName = "union";
+            FixItTagName = "union ";
+            break;
+        }
+
+        Diag(NameLoc, diag::err_use_of_tag_name_without_tag)
+          << Name << TagName << getLangOpts().CPlusPlus
+          << FixItHint::CreateInsertion(NameLoc, FixItTagName);
+        break;
+      }
+      
+      Result.clear(LookupOrdinaryName);
+    }
+
+    // Perform typo correction to determine if there is another name that is
+    // close to this name.
+    if (!SecondTry) {
+      SecondTry = true;
+      CorrectionCandidateCallback DefaultValidator;
+      if (TypoCorrection Corrected = CorrectTypo(Result.getLookupNameInfo(),
+                                                 Result.getLookupKind(), S, 
+                                                 &SS, DefaultValidator)) {
+        unsigned UnqualifiedDiag = diag::err_undeclared_var_use_suggest;
+        unsigned QualifiedDiag = diag::err_no_member_suggest;
+        std::string CorrectedStr(Corrected.getAsString(getLangOpts()));
+        std::string CorrectedQuotedStr(Corrected.getQuoted(getLangOpts()));
+        
+        NamedDecl *FirstDecl = Corrected.getCorrectionDecl();
+        NamedDecl *UnderlyingFirstDecl
+          = FirstDecl? FirstDecl->getUnderlyingDecl() : 0;
+        if (getLangOpts().CPlusPlus && NextToken.is(tok::less) &&
+            UnderlyingFirstDecl && isa<TemplateDecl>(UnderlyingFirstDecl)) {
+          UnqualifiedDiag = diag::err_no_template_suggest;
+          QualifiedDiag = diag::err_no_member_template_suggest;
+        } else if (UnderlyingFirstDecl && 
+                   (isa<TypeDecl>(UnderlyingFirstDecl) || 
+                    isa<ObjCInterfaceDecl>(UnderlyingFirstDecl) ||
+                    isa<ObjCCompatibleAliasDecl>(UnderlyingFirstDecl))) {
+           UnqualifiedDiag = diag::err_unknown_typename_suggest;
+           QualifiedDiag = diag::err_unknown_nested_typename_suggest;
+         }
+
+        if (SS.isEmpty())
+          Diag(NameLoc, UnqualifiedDiag)
+            << Name << CorrectedQuotedStr
+            << FixItHint::CreateReplacement(NameLoc, CorrectedStr);
+        else
+          Diag(NameLoc, QualifiedDiag)
+            << Name << computeDeclContext(SS, false) << CorrectedQuotedStr
+            << SS.getRange()
+            << FixItHint::CreateReplacement(NameLoc, CorrectedStr);
+
+        // Update the name, so that the caller has the new name.
+        Name = Corrected.getCorrectionAsIdentifierInfo();
+        
+        // Typo correction corrected to a keyword.
+        if (Corrected.isKeyword())
+          return Corrected.getCorrectionAsIdentifierInfo();
+
+        // Also update the LookupResult...
+        // FIXME: This should probably go away at some point
+        Result.clear();
+        Result.setLookupName(Corrected.getCorrection());
+        if (FirstDecl) {
+          Result.addDecl(FirstDecl);
+          Diag(FirstDecl->getLocation(), diag::note_previous_decl)
+            << CorrectedQuotedStr;
+        }
+
+        // If we found an Objective-C instance variable, let
+        // LookupInObjCMethod build the appropriate expression to
+        // reference the ivar.
+        // FIXME: This is a gross hack.
+        if (ObjCIvarDecl *Ivar = Result.getAsSingle<ObjCIvarDecl>()) {
+          Result.clear();
+          ExprResult E(LookupInObjCMethod(Result, S, Ivar->getIdentifier()));
+          return move(E);
+        }
+        
+        goto Corrected;
+      }
+    }
+      
+    // We failed to correct; just fall through and let the parser deal with it.
+    Result.suppressDiagnostics();
+    return NameClassification::Unknown();
+      
+  case LookupResult::NotFoundInCurrentInstantiation: {
+    // We performed name lookup into the current instantiation, and there were 
+    // dependent bases, so we treat this result the same way as any other
+    // dependent nested-name-specifier.
+      
+    // C++ [temp.res]p2:
+    //   A name used in a template declaration or definition and that is 
+    //   dependent on a template-parameter is assumed not to name a type 
+    //   unless the applicable name lookup finds a type name or the name is 
+    //   qualified by the keyword typename.
+    //
+    // FIXME: If the next token is '<', we might want to ask the parser to
+    // perform some heroics to see if we actually have a 
+    // template-argument-list, which would indicate a missing 'template'
+    // keyword here.
+    return BuildDependentDeclRefExpr(SS, /*TemplateKWLoc=*/SourceLocation(),
+                                     NameInfo, /*TemplateArgs=*/0);
+  }
+
+  case LookupResult::Found:
+  case LookupResult::FoundOverloaded:
+  case LookupResult::FoundUnresolvedValue:
+    break;
+      
+  case LookupResult::Ambiguous:
+    if (getLangOpts().CPlusPlus && NextToken.is(tok::less) &&
+        hasAnyAcceptableTemplateNames(Result)) {
+      // C++ [temp.local]p3:
+      //   A lookup that finds an injected-class-name (10.2) can result in an
+      //   ambiguity in certain cases (for example, if it is found in more than
+      //   one base class). If all of the injected-class-names that are found
+      //   refer to specializations of the same class template, and if the name
+      //   is followed by a template-argument-list, the reference refers to the
+      //   class template itself and not a specialization thereof, and is not
+      //   ambiguous.
+      //
+      // This filtering can make an ambiguous result into an unambiguous one,
+      // so try again after filtering out template names.
+      FilterAcceptableTemplateNames(Result);
+      if (!Result.isAmbiguous()) {
+        IsFilteredTemplateName = true;
+        break;
+      }
+    }
+      
+    // Diagnose the ambiguity and return an error.
+    return NameClassification::Error();
+  }
+  
+  if (getLangOpts().CPlusPlus && NextToken.is(tok::less) &&
+      (IsFilteredTemplateName || hasAnyAcceptableTemplateNames(Result))) {
+    // C++ [temp.names]p3:
+    //   After name lookup (3.4) finds that a name is a template-name or that
+    //   an operator-function-id or a literal- operator-id refers to a set of
+    //   overloaded functions any member of which is a function template if 
+    //   this is followed by a <, the < is always taken as the delimiter of a
+    //   template-argument-list and never as the less-than operator.
+    if (!IsFilteredTemplateName)
+      FilterAcceptableTemplateNames(Result);
+    
+    if (!Result.empty()) {
+      bool IsFunctionTemplate;
+      TemplateName Template;
+      if (Result.end() - Result.begin() > 1) {
+        IsFunctionTemplate = true;
+        Template = Context.getOverloadedTemplateName(Result.begin(), 
+                                                     Result.end());
+      } else {
+        TemplateDecl *TD
+          = cast<TemplateDecl>((*Result.begin())->getUnderlyingDecl());
+        IsFunctionTemplate = isa<FunctionTemplateDecl>(TD);
+        
+        if (SS.isSet() && !SS.isInvalid())
+          Template = Context.getQualifiedTemplateName(SS.getScopeRep(), 
+                                                    /*TemplateKeyword=*/false,
+                                                      TD);
+        else
+          Template = TemplateName(TD);
+      }
+      
+      if (IsFunctionTemplate) {
+        // Function templates always go through overload resolution, at which
+        // point we'll perform the various checks (e.g., accessibility) we need
+        // to based on which function we selected.
+        Result.suppressDiagnostics();
+        
+        return NameClassification::FunctionTemplate(Template);
+      }
+      
+      return NameClassification::TypeTemplate(Template);
+    }
+  }
+  
+  NamedDecl *FirstDecl = (*Result.begin())->getUnderlyingDecl();
+  if (TypeDecl *Type = dyn_cast<TypeDecl>(FirstDecl)) {
+    DiagnoseUseOfDecl(Type, NameLoc);
+    QualType T = Context.getTypeDeclType(Type);
+    return ParsedType::make(T);    
+  }
+  
+  ObjCInterfaceDecl *Class = dyn_cast<ObjCInterfaceDecl>(FirstDecl);
+  if (!Class) {
+    // FIXME: It's unfortunate that we don't have a Type node for handling this.
+    if (ObjCCompatibleAliasDecl *Alias 
+                                = dyn_cast<ObjCCompatibleAliasDecl>(FirstDecl))
+      Class = Alias->getClassInterface();
+  }
+  
+  if (Class) {
+    DiagnoseUseOfDecl(Class, NameLoc);
+    
+    if (NextToken.is(tok::period)) {
+      // Interface. <something> is parsed as a property reference expression.
+      // Just return "unknown" as a fall-through for now.
+      Result.suppressDiagnostics();
+      return NameClassification::Unknown();
+    }
+    
+    QualType T = Context.getObjCInterfaceType(Class);
+    return ParsedType::make(T);
+  }
+  
+  if (!Result.empty() && (*Result.begin())->isCXXClassMember())
+    return BuildPossibleImplicitMemberExpr(SS, SourceLocation(), Result, 0);
+
+  bool ADL = UseArgumentDependentLookup(SS, Result, NextToken.is(tok::l_paren));
+  return BuildDeclarationNameExpr(SS, Result, ADL);
+}
+
+// Determines the context to return to after temporarily entering a
+// context.  This depends in an unnecessarily complicated way on the
+// exact ordering of callbacks from the parser.
+DeclContext *Sema::getContainingDC(DeclContext *DC) {
+
+  // Functions defined inline within classes aren't parsed until we've
+  // finished parsing the top-level class, so the top-level class is
+  // the context we'll need to return to.
+  if (isa<FunctionDecl>(DC)) {
+    DC = DC->getLexicalParent();
+
+    // A function not defined within a class will always return to its
+    // lexical context.
+    if (!isa<CXXRecordDecl>(DC))
+      return DC;
+
+    // A C++ inline method/friend is parsed *after* the topmost class
+    // it was declared in is fully parsed ("complete");  the topmost
+    // class is the context we need to return to.
+    while (CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(DC->getLexicalParent()))
+      DC = RD;
+
+    // Return the declaration context of the topmost class the inline method is
+    // declared in.
+    return DC;
+  }
+
+  return DC->getLexicalParent();
+}
+
+void Sema::PushDeclContext(Scope *S, DeclContext *DC) {
+  assert(getContainingDC(DC) == CurContext &&
+      "The next DeclContext should be lexically contained in the current one.");
+  CurContext = DC;
+  S->setEntity(DC);
+}
+
+void Sema::PopDeclContext() {
+  assert(CurContext && "DeclContext imbalance!");
+
+  CurContext = getContainingDC(CurContext);
+  assert(CurContext && "Popped translation unit!");
+}
+
+/// EnterDeclaratorContext - Used when we must lookup names in the context
+/// of a declarator's nested name specifier.
+///
+void Sema::EnterDeclaratorContext(Scope *S, DeclContext *DC) {
+  // C++0x [basic.lookup.unqual]p13:
+  //   A name used in the definition of a static data member of class
+  //   X (after the qualified-id of the static member) is looked up as
+  //   if the name was used in a member function of X.
+  // C++0x [basic.lookup.unqual]p14:
+  //   If a variable member of a namespace is defined outside of the
+  //   scope of its namespace then any name used in the definition of
+  //   the variable member (after the declarator-id) is looked up as
+  //   if the definition of the variable member occurred in its
+  //   namespace.
+  // Both of these imply that we should push a scope whose context
+  // is the semantic context of the declaration.  We can't use
+  // PushDeclContext here because that context is not necessarily
+  // lexically contained in the current context.  Fortunately,
+  // the containing scope should have the appropriate information.
+
+  assert(!S->getEntity() && "scope already has entity");
+
+#ifndef NDEBUG
+  Scope *Ancestor = S->getParent();
+  while (!Ancestor->getEntity()) Ancestor = Ancestor->getParent();
+  assert(Ancestor->getEntity() == CurContext && "ancestor context mismatch");
+#endif
+
+  CurContext = DC;
+  S->setEntity(DC);
+}
+
+void Sema::ExitDeclaratorContext(Scope *S) {
+  assert(S->getEntity() == CurContext && "Context imbalance!");
+
+  // Switch back to the lexical context.  The safety of this is
+  // enforced by an assert in EnterDeclaratorContext.
+  Scope *Ancestor = S->getParent();
+  while (!Ancestor->getEntity()) Ancestor = Ancestor->getParent();
+  CurContext = (DeclContext*) Ancestor->getEntity();
+
+  // We don't need to do anything with the scope, which is going to
+  // disappear.
+}
+
+
+void Sema::ActOnReenterFunctionContext(Scope* S, Decl *D) {
+  FunctionDecl *FD = dyn_cast<FunctionDecl>(D);
+  if (FunctionTemplateDecl *TFD = dyn_cast_or_null<FunctionTemplateDecl>(D)) {
+    // We assume that the caller has already called
+    // ActOnReenterTemplateScope
+    FD = TFD->getTemplatedDecl();
+  }
+  if (!FD)
+    return;
+
+  // Same implementation as PushDeclContext, but enters the context
+  // from the lexical parent, rather than the top-level class.
+  assert(CurContext == FD->getLexicalParent() &&
+    "The next DeclContext should be lexically contained in the current one.");
+  CurContext = FD;
+  S->setEntity(CurContext);
+
+  for (unsigned P = 0, NumParams = FD->getNumParams(); P < NumParams; ++P) {
+    ParmVarDecl *Param = FD->getParamDecl(P);
+    // If the parameter has an identifier, then add it to the scope
+    if (Param->getIdentifier()) {
+      S->AddDecl(Param);
+      IdResolver.AddDecl(Param);
+    }
+  }
+}
+
+
+void Sema::ActOnExitFunctionContext() {
+  // Same implementation as PopDeclContext, but returns to the lexical parent,
+  // rather than the top-level class.
+  assert(CurContext && "DeclContext imbalance!");
+  CurContext = CurContext->getLexicalParent();
+  assert(CurContext && "Popped translation unit!");
+}
+
+
+/// \brief Determine whether we allow overloading of the function
+/// PrevDecl with another declaration.
+///
+/// This routine determines whether overloading is possible, not
+/// whether some new function is actually an overload. It will return
+/// true in C++ (where we can always provide overloads) or, as an
+/// extension, in C when the previous function is already an
+/// overloaded function declaration or has the "overloadable"
+/// attribute.
+static bool AllowOverloadingOfFunction(LookupResult &Previous,
+                                       ASTContext &Context) {
+  if (Context.getLangOpts().CPlusPlus)
+    return true;
+
+  if (Previous.getResultKind() == LookupResult::FoundOverloaded)
+    return true;
+
+  return (Previous.getResultKind() == LookupResult::Found
+          && Previous.getFoundDecl()->hasAttr<OverloadableAttr>());
+}
+
+/// Add this decl to the scope shadowed decl chains.
+void Sema::PushOnScopeChains(NamedDecl *D, Scope *S, bool AddToContext) {
+  // Move up the scope chain until we find the nearest enclosing
+  // non-transparent context. The declaration will be introduced into this
+  // scope.
+  while (S->getEntity() &&
+         ((DeclContext *)S->getEntity())->isTransparentContext())
+    S = S->getParent();
+
+  // Add scoped declarations into their context, so that they can be
+  // found later. Declarations without a context won't be inserted
+  // into any context.
+  if (AddToContext)
+    CurContext->addDecl(D);
+
+  // Out-of-line definitions shouldn't be pushed into scope in C++.
+  // Out-of-line variable and function definitions shouldn't even in C.
+  if ((getLangOpts().CPlusPlus || isa<VarDecl>(D) || isa<FunctionDecl>(D)) &&
+      D->isOutOfLine() &&
+      !D->getDeclContext()->getRedeclContext()->Equals(
+        D->getLexicalDeclContext()->getRedeclContext()))
+    return;
+
+  // Template instantiations should also not be pushed into scope.
+  if (isa<FunctionDecl>(D) &&
+      cast<FunctionDecl>(D)->isFunctionTemplateSpecialization())
+    return;
+
+  // If this replaces anything in the current scope, 
+  IdentifierResolver::iterator I = IdResolver.begin(D->getDeclName()),
+                               IEnd = IdResolver.end();
+  for (; I != IEnd; ++I) {
+    if (S->isDeclScope(*I) && D->declarationReplaces(*I)) {
+      S->RemoveDecl(*I);
+      IdResolver.RemoveDecl(*I);
+
+      // Should only need to replace one decl.
+      break;
+    }
+  }
+
+  S->AddDecl(D);
+  
+  if (isa<LabelDecl>(D) && !cast<LabelDecl>(D)->isGnuLocal()) {
+    // Implicitly-generated labels may end up getting generated in an order that
+    // isn't strictly lexical, which breaks name lookup. Be careful to insert
+    // the label at the appropriate place in the identifier chain.
+    for (I = IdResolver.begin(D->getDeclName()); I != IEnd; ++I) {
+      DeclContext *IDC = (*I)->getLexicalDeclContext()->getRedeclContext();
+      if (IDC == CurContext) {
+        if (!S->isDeclScope(*I))
+          continue;
+      } else if (IDC->Encloses(CurContext))
+        break;
+    }
+    
+    IdResolver.InsertDeclAfter(I, D);
+  } else {
+    IdResolver.AddDecl(D);
+  }
+}
+
+void Sema::pushExternalDeclIntoScope(NamedDecl *D, DeclarationName Name) {
+  if (IdResolver.tryAddTopLevelDecl(D, Name) && TUScope)
+    TUScope->AddDecl(D);
+}
+
+bool Sema::isDeclInScope(NamedDecl *&D, DeclContext *Ctx, Scope *S,
+                         bool ExplicitInstantiationOrSpecialization) {
+  return IdResolver.isDeclInScope(D, Ctx, Context, S,
+                                  ExplicitInstantiationOrSpecialization);
+}
+
+Scope *Sema::getScopeForDeclContext(Scope *S, DeclContext *DC) {
+  DeclContext *TargetDC = DC->getPrimaryContext();
+  do {
+    if (DeclContext *ScopeDC = (DeclContext*) S->getEntity())
+      if (ScopeDC->getPrimaryContext() == TargetDC)
+        return S;
+  } while ((S = S->getParent()));
+
+  return 0;
+}
+
+static bool isOutOfScopePreviousDeclaration(NamedDecl *,
+                                            DeclContext*,
+                                            ASTContext&);
+
+/// Filters out lookup results that don't fall within the given scope
+/// as determined by isDeclInScope.
+void Sema::FilterLookupForScope(LookupResult &R,
+                                DeclContext *Ctx, Scope *S,
+                                bool ConsiderLinkage,
+                                bool ExplicitInstantiationOrSpecialization) {
+  LookupResult::Filter F = R.makeFilter();
+  while (F.hasNext()) {
+    NamedDecl *D = F.next();
+
+    if (isDeclInScope(D, Ctx, S, ExplicitInstantiationOrSpecialization))
+      continue;
+
+    if (ConsiderLinkage &&
+        isOutOfScopePreviousDeclaration(D, Ctx, Context))
+      continue;
+    
+    F.erase();
+  }
+
+  F.done();
+}
+
+static bool isUsingDecl(NamedDecl *D) {
+  return isa<UsingShadowDecl>(D) ||
+         isa<UnresolvedUsingTypenameDecl>(D) ||
+         isa<UnresolvedUsingValueDecl>(D);
+}
+
+/// Removes using shadow declarations from the lookup results.
+static void RemoveUsingDecls(LookupResult &R) {
+  LookupResult::Filter F = R.makeFilter();
+  while (F.hasNext())
+    if (isUsingDecl(F.next()))
+      F.erase();
+
+  F.done();
+}
+
+/// \brief Check for this common pattern:
+/// @code
+/// class S {
+///   S(const S&); // DO NOT IMPLEMENT
+///   void operator=(const S&); // DO NOT IMPLEMENT
+/// };
+/// @endcode
+static bool IsDisallowedCopyOrAssign(const CXXMethodDecl *D) {
+  // FIXME: Should check for private access too but access is set after we get
+  // the decl here.
+  if (D->doesThisDeclarationHaveABody())
+    return false;
+
+  if (const CXXConstructorDecl *CD = dyn_cast<CXXConstructorDecl>(D))
+    return CD->isCopyConstructor();
+  if (const CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(D))
+    return Method->isCopyAssignmentOperator();
+  return false;
+}
+
+bool Sema::ShouldWarnIfUnusedFileScopedDecl(const DeclaratorDecl *D) const {
+  assert(D);
+
+  if (D->isInvalidDecl() || D->isUsed() || D->hasAttr<UnusedAttr>())
+    return false;
+
+  // Ignore class templates.
+  if (D->getDeclContext()->isDependentContext() ||
+      D->getLexicalDeclContext()->isDependentContext())
+    return false;
+
+  if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
+    if (FD->getTemplateSpecializationKind() == TSK_ImplicitInstantiation)
+      return false;
+
+    if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD)) {
+      if (MD->isVirtual() || IsDisallowedCopyOrAssign(MD))
+        return false;
+    } else {
+      // 'static inline' functions are used in headers; don't warn.
+      if (FD->getStorageClass() == SC_Static &&
+          FD->isInlineSpecified())
+        return false;
+    }
+
+    if (FD->doesThisDeclarationHaveABody() &&
+        Context.DeclMustBeEmitted(FD))
+      return false;
+  } else if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
+    if (!VD->isFileVarDecl() ||
+        VD->getType().isConstant(Context) ||
+        Context.DeclMustBeEmitted(VD))
+      return false;
+
+    if (VD->isStaticDataMember() &&
+        VD->getTemplateSpecializationKind() == TSK_ImplicitInstantiation)
+      return false;
+
+  } else {
+    return false;
+  }
+
+  // Only warn for unused decls internal to the translation unit.
+  if (D->getLinkage() == ExternalLinkage)
+    return false;
+
+  return true;
+}
+
+void Sema::MarkUnusedFileScopedDecl(const DeclaratorDecl *D) {
+  if (!D)
+    return;
+
+  if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
+    const FunctionDecl *First = FD->getFirstDeclaration();
+    if (FD != First && ShouldWarnIfUnusedFileScopedDecl(First))
+      return; // First should already be in the vector.
+  }
+
+  if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
+    const VarDecl *First = VD->getFirstDeclaration();
+    if (VD != First && ShouldWarnIfUnusedFileScopedDecl(First))
+      return; // First should already be in the vector.
+  }
+
+   if (ShouldWarnIfUnusedFileScopedDecl(D))
+     UnusedFileScopedDecls.push_back(D);
+ }
+
+static bool ShouldDiagnoseUnusedDecl(const NamedDecl *D) {
+  if (D->isInvalidDecl())
+    return false;
+
+  if (D->isReferenced() || D->isUsed() || D->hasAttr<UnusedAttr>())
+    return false;
+
+  if (isa<LabelDecl>(D))
+    return true;
+  
+  // White-list anything that isn't a local variable.
+  if (!isa<VarDecl>(D) || isa<ParmVarDecl>(D) || isa<ImplicitParamDecl>(D) ||
+      !D->getDeclContext()->isFunctionOrMethod())
+    return false;
+
+  // Types of valid local variables should be complete, so this should succeed.
+  if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
+
+    // White-list anything with an __attribute__((unused)) type.
+    QualType Ty = VD->getType();
+
+    // Only look at the outermost level of typedef.
+    if (const TypedefType *TT = dyn_cast<TypedefType>(Ty)) {
+      if (TT->getDecl()->hasAttr<UnusedAttr>())
+        return false;
+    }
+
+    // If we failed to complete the type for some reason, or if the type is
+    // dependent, don't diagnose the variable. 
+    if (Ty->isIncompleteType() || Ty->isDependentType())
+      return false;
+
+    if (const TagType *TT = Ty->getAs<TagType>()) {
+      const TagDecl *Tag = TT->getDecl();
+      if (Tag->hasAttr<UnusedAttr>())
+        return false;
+
+      if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(Tag)) {
+        if (!RD->hasTrivialDestructor())
+          return false;
+
+        if (const Expr *Init = VD->getInit()) {
+          const CXXConstructExpr *Construct =
+            dyn_cast<CXXConstructExpr>(Init);
+          if (Construct && !Construct->isElidable()) {
+            CXXConstructorDecl *CD = Construct->getConstructor();
+            if (!CD->isTrivial())
+              return false;
+          }
+        }
+      }
+    }
+
+    // TODO: __attribute__((unused)) templates?
+  }
+  
+  return true;
+}
+
+static void GenerateFixForUnusedDecl(const NamedDecl *D, ASTContext &Ctx,
+                                     FixItHint &Hint) {
+  if (isa<LabelDecl>(D)) {
+    SourceLocation AfterColon = Lexer::findLocationAfterToken(D->getLocEnd(),
+                tok::colon, Ctx.getSourceManager(), Ctx.getLangOpts(), true);
+    if (AfterColon.isInvalid())
+      return;
+    Hint = FixItHint::CreateRemoval(CharSourceRange::
+                                    getCharRange(D->getLocStart(), AfterColon));
+  }
+  return;
+}
+
+/// DiagnoseUnusedDecl - Emit warnings about declarations that are not used
+/// unless they are marked attr(unused).
+void Sema::DiagnoseUnusedDecl(const NamedDecl *D) {
+  FixItHint Hint;
+  if (!ShouldDiagnoseUnusedDecl(D))
+    return;
+  
+  GenerateFixForUnusedDecl(D, Context, Hint);
+
+  unsigned DiagID;
+  if (isa<VarDecl>(D) && cast<VarDecl>(D)->isExceptionVariable())
+    DiagID = diag::warn_unused_exception_param;
+  else if (isa<LabelDecl>(D))
+    DiagID = diag::warn_unused_label;
+  else
+    DiagID = diag::warn_unused_variable;
+
+  Diag(D->getLocation(), DiagID) << D->getDeclName() << Hint;
+}
+
+static void CheckPoppedLabel(LabelDecl *L, Sema &S) {
+  // Verify that we have no forward references left.  If so, there was a goto
+  // or address of a label taken, but no definition of it.  Label fwd
+  // definitions are indicated with a null substmt.
+  if (L->getStmt() == 0)
+    S.Diag(L->getLocation(), diag::err_undeclared_label_use) <<L->getDeclName();
+}
+
+void Sema::ActOnPopScope(SourceLocation Loc, Scope *S) {
+  if (S->decl_empty()) return;
+  assert((S->getFlags() & (Scope::DeclScope | Scope::TemplateParamScope)) &&
+         "Scope shouldn't contain decls!");
+
+  for (Scope::decl_iterator I = S->decl_begin(), E = S->decl_end();
+       I != E; ++I) {
+    Decl *TmpD = (*I);
+    assert(TmpD && "This decl didn't get pushed??");
+
+    assert(isa<NamedDecl>(TmpD) && "Decl isn't NamedDecl?");
+    NamedDecl *D = cast<NamedDecl>(TmpD);
+
+    if (!D->getDeclName()) continue;
+
+    // Diagnose unused variables in this scope.
+    if (!S->hasErrorOccurred())
+      DiagnoseUnusedDecl(D);
+    
+    // If this was a forward reference to a label, verify it was defined.
+    if (LabelDecl *LD = dyn_cast<LabelDecl>(D))
+      CheckPoppedLabel(LD, *this);
+    
+    // Remove this name from our lexical scope.
+    IdResolver.RemoveDecl(D);
+  }
+}
+
+void Sema::ActOnStartFunctionDeclarator() {
+  ++InFunctionDeclarator;
+}
+
+void Sema::ActOnEndFunctionDeclarator() {
+  assert(InFunctionDeclarator);
+  --InFunctionDeclarator;
+}
+
+/// \brief Look for an Objective-C class in the translation unit.
+///
+/// \param Id The name of the Objective-C class we're looking for. If
+/// typo-correction fixes this name, the Id will be updated
+/// to the fixed name.
+///
+/// \param IdLoc The location of the name in the translation unit.
+///
+/// \param TypoCorrection If true, this routine will attempt typo correction
+/// if there is no class with the given name.
+///
+/// \returns The declaration of the named Objective-C class, or NULL if the
+/// class could not be found.
+ObjCInterfaceDecl *Sema::getObjCInterfaceDecl(IdentifierInfo *&Id,
+                                              SourceLocation IdLoc,
+                                              bool DoTypoCorrection) {
+  // The third "scope" argument is 0 since we aren't enabling lazy built-in
+  // creation from this context.
+  NamedDecl *IDecl = LookupSingleName(TUScope, Id, IdLoc, LookupOrdinaryName);
+
+  if (!IDecl && DoTypoCorrection) {
+    // Perform typo correction at the given location, but only if we
+    // find an Objective-C class name.
+    DeclFilterCCC<ObjCInterfaceDecl> Validator;
+    if (TypoCorrection C = CorrectTypo(DeclarationNameInfo(Id, IdLoc),
+                                       LookupOrdinaryName, TUScope, NULL,
+                                       Validator)) {
+      IDecl = C.getCorrectionDeclAs<ObjCInterfaceDecl>();
+      Diag(IdLoc, diag::err_undef_interface_suggest)
+        << Id << IDecl->getDeclName() 
+        << FixItHint::CreateReplacement(IdLoc, IDecl->getNameAsString());
+      Diag(IDecl->getLocation(), diag::note_previous_decl)
+        << IDecl->getDeclName();
+      
+      Id = IDecl->getIdentifier();
+    }
+  }
+  ObjCInterfaceDecl *Def = dyn_cast_or_null<ObjCInterfaceDecl>(IDecl);
+  // This routine must always return a class definition, if any.
+  if (Def && Def->getDefinition())
+      Def = Def->getDefinition();
+  return Def;
+}
+
+/// getNonFieldDeclScope - Retrieves the innermost scope, starting
+/// from S, where a non-field would be declared. This routine copes
+/// with the difference between C and C++ scoping rules in structs and
+/// unions. For example, the following code is well-formed in C but
+/// ill-formed in C++:
+/// @code
+/// struct S6 {
+///   enum { BAR } e;
+/// };
+///
+/// void test_S6() {
+///   struct S6 a;
+///   a.e = BAR;
+/// }
+/// @endcode
+/// For the declaration of BAR, this routine will return a different
+/// scope. The scope S will be the scope of the unnamed enumeration
+/// within S6. In C++, this routine will return the scope associated
+/// with S6, because the enumeration's scope is a transparent
+/// context but structures can contain non-field names. In C, this
+/// routine will return the translation unit scope, since the
+/// enumeration's scope is a transparent context and structures cannot
+/// contain non-field names.
+Scope *Sema::getNonFieldDeclScope(Scope *S) {
+  while (((S->getFlags() & Scope::DeclScope) == 0) ||
+         (S->getEntity() &&
+          ((DeclContext *)S->getEntity())->isTransparentContext()) ||
+         (S->isClassScope() && !getLangOpts().CPlusPlus))
+    S = S->getParent();
+  return S;
+}
+
+/// LazilyCreateBuiltin - The specified Builtin-ID was first used at
+/// file scope.  lazily create a decl for it. ForRedeclaration is true
+/// if we're creating this built-in in anticipation of redeclaring the
+/// built-in.
+NamedDecl *Sema::LazilyCreateBuiltin(IdentifierInfo *II, unsigned bid,
+                                     Scope *S, bool ForRedeclaration,
+                                     SourceLocation Loc) {
+  Builtin::ID BID = (Builtin::ID)bid;
+
+  ASTContext::GetBuiltinTypeError Error;
+  QualType R = Context.GetBuiltinType(BID, Error);
+  switch (Error) {
+  case ASTContext::GE_None:
+    // Okay
+    break;
+
+  case ASTContext::GE_Missing_stdio:
+    if (ForRedeclaration)
+      Diag(Loc, diag::warn_implicit_decl_requires_stdio)
+        << Context.BuiltinInfo.GetName(BID);
+    return 0;
+
+  case ASTContext::GE_Missing_setjmp:
+    if (ForRedeclaration)
+      Diag(Loc, diag::warn_implicit_decl_requires_setjmp)
+        << Context.BuiltinInfo.GetName(BID);
+    return 0;
+
+  case ASTContext::GE_Missing_ucontext:
+    if (ForRedeclaration)
+      Diag(Loc, diag::warn_implicit_decl_requires_ucontext)
+        << Context.BuiltinInfo.GetName(BID);
+    return 0;
+  }
+
+  if (!ForRedeclaration && Context.BuiltinInfo.isPredefinedLibFunction(BID)) {
+    Diag(Loc, diag::ext_implicit_lib_function_decl)
+      << Context.BuiltinInfo.GetName(BID)
+      << R;
+    if (Context.BuiltinInfo.getHeaderName(BID) &&
+        Diags.getDiagnosticLevel(diag::ext_implicit_lib_function_decl, Loc)
+          != DiagnosticsEngine::Ignored)
+      Diag(Loc, diag::note_please_include_header)
+        << Context.BuiltinInfo.getHeaderName(BID)
+        << Context.BuiltinInfo.GetName(BID);
+  }
+
+  FunctionDecl *New = FunctionDecl::Create(Context,
+                                           Context.getTranslationUnitDecl(),
+                                           Loc, Loc, II, R, /*TInfo=*/0,
+                                           SC_Extern,
+                                           SC_None, false,
+                                           /*hasPrototype=*/true);
+  New->setImplicit();
+
+  // Create Decl objects for each parameter, adding them to the
+  // FunctionDecl.
+  if (const FunctionProtoType *FT = dyn_cast<FunctionProtoType>(R)) {
+    SmallVector<ParmVarDecl*, 16> Params;
+    for (unsigned i = 0, e = FT->getNumArgs(); i != e; ++i) {
+      ParmVarDecl *parm =
+        ParmVarDecl::Create(Context, New, SourceLocation(),
+                            SourceLocation(), 0,
+                            FT->getArgType(i), /*TInfo=*/0,
+                            SC_None, SC_None, 0);
+      parm->setScopeInfo(0, i);
+      Params.push_back(parm);
+    }
+    New->setParams(Params);
+  }
+
+  AddKnownFunctionAttributes(New);
+
+  // TUScope is the translation-unit scope to insert this function into.
+  // FIXME: This is hideous. We need to teach PushOnScopeChains to
+  // relate Scopes to DeclContexts, and probably eliminate CurContext
+  // entirely, but we're not there yet.
+  DeclContext *SavedContext = CurContext;
+  CurContext = Context.getTranslationUnitDecl();
+  PushOnScopeChains(New, TUScope);
+  CurContext = SavedContext;
+  return New;
+}
+
+bool Sema::isIncompatibleTypedef(TypeDecl *Old, TypedefNameDecl *New) {
+  QualType OldType;
+  if (TypedefNameDecl *OldTypedef = dyn_cast<TypedefNameDecl>(Old))
+    OldType = OldTypedef->getUnderlyingType();
+  else
+    OldType = Context.getTypeDeclType(Old);
+  QualType NewType = New->getUnderlyingType();
+
+  if (NewType->isVariablyModifiedType()) {
+    // Must not redefine a typedef with a variably-modified type.
+    int Kind = isa<TypeAliasDecl>(Old) ? 1 : 0;
+    Diag(New->getLocation(), diag::err_redefinition_variably_modified_typedef)
+      << Kind << NewType;
+    if (Old->getLocation().isValid())
+      Diag(Old->getLocation(), diag::note_previous_definition);
+    New->setInvalidDecl();
+    return true;    
+  }
+  
+  if (OldType != NewType &&
+      !OldType->isDependentType() &&
+      !NewType->isDependentType() &&
+      !Context.hasSameType(OldType, NewType)) { 
+    int Kind = isa<TypeAliasDecl>(Old) ? 1 : 0;
+    Diag(New->getLocation(), diag::err_redefinition_different_typedef)
+      << Kind << NewType << OldType;
+    if (Old->getLocation().isValid())
+      Diag(Old->getLocation(), diag::note_previous_definition);
+    New->setInvalidDecl();
+    return true;
+  }
+  return false;
+}
+
+/// MergeTypedefNameDecl - We just parsed a typedef 'New' which has the
+/// same name and scope as a previous declaration 'Old'.  Figure out
+/// how to resolve this situation, merging decls or emitting
+/// diagnostics as appropriate. If there was an error, set New to be invalid.
+///
+void Sema::MergeTypedefNameDecl(TypedefNameDecl *New, LookupResult &OldDecls) {
+  // If the new decl is known invalid already, don't bother doing any
+  // merging checks.
+  if (New->isInvalidDecl()) return;
+
+  // Allow multiple definitions for ObjC built-in typedefs.
+  // FIXME: Verify the underlying types are equivalent!
+  if (getLangOpts().ObjC1) {
+    const IdentifierInfo *TypeID = New->getIdentifier();
+    switch (TypeID->getLength()) {
+    default: break;
+    case 2:
+      if (!TypeID->isStr("id"))
+        break;
+      Context.setObjCIdRedefinitionType(New->getUnderlyingType());
+      // Install the built-in type for 'id', ignoring the current definition.
+      New->setTypeForDecl(Context.getObjCIdType().getTypePtr());
+      return;
+    case 5:
+      if (!TypeID->isStr("Class"))
+        break;
+      Context.setObjCClassRedefinitionType(New->getUnderlyingType());
+      // Install the built-in type for 'Class', ignoring the current definition.
+      New->setTypeForDecl(Context.getObjCClassType().getTypePtr());
+      return;
+    case 3:
+      if (!TypeID->isStr("SEL"))
+        break;
+      Context.setObjCSelRedefinitionType(New->getUnderlyingType());
+      // Install the built-in type for 'SEL', ignoring the current definition.
+      New->setTypeForDecl(Context.getObjCSelType().getTypePtr());
+      return;
+    }
+    // Fall through - the typedef name was not a builtin type.
+  }
+
+  // Verify the old decl was also a type.
+  TypeDecl *Old = OldDecls.getAsSingle<TypeDecl>();
+  if (!Old) {
+    Diag(New->getLocation(), diag::err_redefinition_different_kind)
+      << New->getDeclName();
+
+    NamedDecl *OldD = OldDecls.getRepresentativeDecl();
+    if (OldD->getLocation().isValid())
+      Diag(OldD->getLocation(), diag::note_previous_definition);
+
+    return New->setInvalidDecl();
+  }
+
+  // If the old declaration is invalid, just give up here.
+  if (Old->isInvalidDecl())
+    return New->setInvalidDecl();
+
+  // If the typedef types are not identical, reject them in all languages and
+  // with any extensions enabled.
+  if (isIncompatibleTypedef(Old, New))
+    return;
+
+  // The types match.  Link up the redeclaration chain if the old
+  // declaration was a typedef.
+  if (TypedefNameDecl *Typedef = dyn_cast<TypedefNameDecl>(Old))
+    New->setPreviousDeclaration(Typedef);
+
+  if (getLangOpts().MicrosoftExt)
+    return;
+
+  if (getLangOpts().CPlusPlus) {
+    // C++ [dcl.typedef]p2:
+    //   In a given non-class scope, a typedef specifier can be used to
+    //   redefine the name of any type declared in that scope to refer
+    //   to the type to which it already refers.
+    if (!isa<CXXRecordDecl>(CurContext))
+      return;
+
+    // C++0x [dcl.typedef]p4:
+    //   In a given class scope, a typedef specifier can be used to redefine 
+    //   any class-name declared in that scope that is not also a typedef-name
+    //   to refer to the type to which it already refers.
+    //
+    // This wording came in via DR424, which was a correction to the
+    // wording in DR56, which accidentally banned code like:
+    //
+    //   struct S {
+    //     typedef struct A { } A;
+    //   };
+    //
+    // in the C++03 standard. We implement the C++0x semantics, which
+    // allow the above but disallow
+    //
+    //   struct S {
+    //     typedef int I;
+    //     typedef int I;
+    //   };
+    //
+    // since that was the intent of DR56.
+    if (!isa<TypedefNameDecl>(Old))
+      return;
+
+    Diag(New->getLocation(), diag::err_redefinition)
+      << New->getDeclName();
+    Diag(Old->getLocation(), diag::note_previous_definition);
+    return New->setInvalidDecl();
+  }
+
+  // Modules always permit redefinition of typedefs, as does C11.
+  if (getLangOpts().Modules || getLangOpts().C11)
+    return;
+  
+  // If we have a redefinition of a typedef in C, emit a warning.  This warning
+  // is normally mapped to an error, but can be controlled with
+  // -Wtypedef-redefinition.  If either the original or the redefinition is
+  // in a system header, don't emit this for compatibility with GCC.
+  if (getDiagnostics().getSuppressSystemWarnings() &&
+      (Context.getSourceManager().isInSystemHeader(Old->getLocation()) ||
+       Context.getSourceManager().isInSystemHeader(New->getLocation())))
+    return;
+
+  Diag(New->getLocation(), diag::warn_redefinition_of_typedef)
+    << New->getDeclName();
+  Diag(Old->getLocation(), diag::note_previous_definition);
+  return;
+}
+
+/// DeclhasAttr - returns true if decl Declaration already has the target
+/// attribute.
+static bool
+DeclHasAttr(const Decl *D, const Attr *A) {
+  const OwnershipAttr *OA = dyn_cast<OwnershipAttr>(A);
+  const AnnotateAttr *Ann = dyn_cast<AnnotateAttr>(A);
+  for (Decl::attr_iterator i = D->attr_begin(), e = D->attr_end(); i != e; ++i)
+    if ((*i)->getKind() == A->getKind()) {
+      if (Ann) {
+        if (Ann->getAnnotation() == cast<AnnotateAttr>(*i)->getAnnotation())
+          return true;
+        continue;
+      }
+      // FIXME: Don't hardcode this check
+      if (OA && isa<OwnershipAttr>(*i))
+        return OA->getOwnKind() == cast<OwnershipAttr>(*i)->getOwnKind();
+      return true;
+    }
+
+  return false;
+}
+
+/// mergeDeclAttributes - Copy attributes from the Old decl to the New one.
+void Sema::mergeDeclAttributes(Decl *New, Decl *Old,
+                               bool MergeDeprecation) {
+  if (!Old->hasAttrs())
+    return;
+
+  bool foundAny = New->hasAttrs();
+
+  // Ensure that any moving of objects within the allocated map is done before
+  // we process them.
+  if (!foundAny) New->setAttrs(AttrVec());
+
+  for (specific_attr_iterator<InheritableAttr>
+         i = Old->specific_attr_begin<InheritableAttr>(),
+         e = Old->specific_attr_end<InheritableAttr>(); 
+       i != e; ++i) {
+    // Ignore deprecated/unavailable/availability attributes if requested.
+    if (!MergeDeprecation &&
+        (isa<DeprecatedAttr>(*i) || 
+         isa<UnavailableAttr>(*i) ||
+         isa<AvailabilityAttr>(*i)))
+      continue;
+
+    if (!DeclHasAttr(New, *i)) {
+      InheritableAttr *newAttr = cast<InheritableAttr>((*i)->clone(Context));
+      newAttr->setInherited(true);
+      New->addAttr(newAttr);
+      foundAny = true;
+    }
+  }
+
+  if (!foundAny) New->dropAttrs();
+}
+
+/// mergeParamDeclAttributes - Copy attributes from the old parameter
+/// to the new one.
+static void mergeParamDeclAttributes(ParmVarDecl *newDecl,
+                                     const ParmVarDecl *oldDecl,
+                                     ASTContext &C) {
+  if (!oldDecl->hasAttrs())
+    return;
+
+  bool foundAny = newDecl->hasAttrs();
+
+  // Ensure that any moving of objects within the allocated map is
+  // done before we process them.
+  if (!foundAny) newDecl->setAttrs(AttrVec());
+
+  for (specific_attr_iterator<InheritableParamAttr>
+       i = oldDecl->specific_attr_begin<InheritableParamAttr>(),
+       e = oldDecl->specific_attr_end<InheritableParamAttr>(); i != e; ++i) {
+    if (!DeclHasAttr(newDecl, *i)) {
+      InheritableAttr *newAttr = cast<InheritableParamAttr>((*i)->clone(C));
+      newAttr->setInherited(true);
+      newDecl->addAttr(newAttr);
+      foundAny = true;
+    }
+  }
+
+  if (!foundAny) newDecl->dropAttrs();
+}
+
+namespace {
+
+/// Used in MergeFunctionDecl to keep track of function parameters in
+/// C.
+struct GNUCompatibleParamWarning {
+  ParmVarDecl *OldParm;
+  ParmVarDecl *NewParm;
+  QualType PromotedType;
+};
+
+}
+
+/// getSpecialMember - get the special member enum for a method.
+Sema::CXXSpecialMember Sema::getSpecialMember(const CXXMethodDecl *MD) {
+  if (const CXXConstructorDecl *Ctor = dyn_cast<CXXConstructorDecl>(MD)) {
+    if (Ctor->isDefaultConstructor())
+      return Sema::CXXDefaultConstructor;
+
+    if (Ctor->isCopyConstructor())
+      return Sema::CXXCopyConstructor;
+
+    if (Ctor->isMoveConstructor())
+      return Sema::CXXMoveConstructor;
+  } else if (isa<CXXDestructorDecl>(MD)) {
+    return Sema::CXXDestructor;
+  } else if (MD->isCopyAssignmentOperator()) {
+    return Sema::CXXCopyAssignment;
+  } else if (MD->isMoveAssignmentOperator()) {
+    return Sema::CXXMoveAssignment;
+  }
+
+  return Sema::CXXInvalid;
+}
+
+/// canRedefineFunction - checks if a function can be redefined. Currently,
+/// only extern inline functions can be redefined, and even then only in
+/// GNU89 mode.
+static bool canRedefineFunction(const FunctionDecl *FD,
+                                const LangOptions& LangOpts) {
+  return ((FD->hasAttr<GNUInlineAttr>() || LangOpts.GNUInline) &&
+          !LangOpts.CPlusPlus &&
+          FD->isInlineSpecified() &&
+          FD->getStorageClass() == SC_Extern);
+}
+
+/// MergeFunctionDecl - We just parsed a function 'New' from
+/// declarator D which has the same name and scope as a previous
+/// declaration 'Old'.  Figure out how to resolve this situation,
+/// merging decls or emitting diagnostics as appropriate.
+///
+/// In C++, New and Old must be declarations that are not
+/// overloaded. Use IsOverload to determine whether New and Old are
+/// overloaded, and to select the Old declaration that New should be
+/// merged with.
+///
+/// Returns true if there was an error, false otherwise.
+bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD, Scope *S) {
+  // Verify the old decl was also a function.
+  FunctionDecl *Old = 0;
+  if (FunctionTemplateDecl *OldFunctionTemplate
+        = dyn_cast<FunctionTemplateDecl>(OldD))
+    Old = OldFunctionTemplate->getTemplatedDecl();
+  else
+    Old = dyn_cast<FunctionDecl>(OldD);
+  if (!Old) {
+    if (UsingShadowDecl *Shadow = dyn_cast<UsingShadowDecl>(OldD)) {
+      Diag(New->getLocation(), diag::err_using_decl_conflict_reverse);
+      Diag(Shadow->getTargetDecl()->getLocation(),
+           diag::note_using_decl_target);
+      Diag(Shadow->getUsingDecl()->getLocation(),
+           diag::note_using_decl) << 0;
+      return true;
+    }
+
+    Diag(New->getLocation(), diag::err_redefinition_different_kind)
+      << New->getDeclName();
+    Diag(OldD->getLocation(), diag::note_previous_definition);
+    return true;
+  }
+
+  // Determine whether the previous declaration was a definition,
+  // implicit declaration, or a declaration.
+  diag::kind PrevDiag;
+  if (Old->isThisDeclarationADefinition())
+    PrevDiag = diag::note_previous_definition;
+  else if (Old->isImplicit())
+    PrevDiag = diag::note_previous_implicit_declaration;
+  else
+    PrevDiag = diag::note_previous_declaration;
+
+  QualType OldQType = Context.getCanonicalType(Old->getType());
+  QualType NewQType = Context.getCanonicalType(New->getType());
+
+  // Don't complain about this if we're in GNU89 mode and the old function
+  // is an extern inline function.
+  if (!isa<CXXMethodDecl>(New) && !isa<CXXMethodDecl>(Old) &&
+      New->getStorageClass() == SC_Static &&
+      Old->getStorageClass() != SC_Static &&
+      !canRedefineFunction(Old, getLangOpts())) {
+    if (getLangOpts().MicrosoftExt) {
+      Diag(New->getLocation(), diag::warn_static_non_static) << New;
+      Diag(Old->getLocation(), PrevDiag);
+    } else {
+      Diag(New->getLocation(), diag::err_static_non_static) << New;
+      Diag(Old->getLocation(), PrevDiag);
+      return true;
+    }
+  }
+
+  // If a function is first declared with a calling convention, but is
+  // later declared or defined without one, the second decl assumes the
+  // calling convention of the first.
+  //
+  // For the new decl, we have to look at the NON-canonical type to tell the
+  // difference between a function that really doesn't have a calling
+  // convention and one that is declared cdecl. That's because in
+  // canonicalization (see ASTContext.cpp), cdecl is canonicalized away
+  // because it is the default calling convention.
+  //
+  // Note also that we DO NOT return at this point, because we still have
+  // other tests to run.
+  const FunctionType *OldType = cast<FunctionType>(OldQType);
+  const FunctionType *NewType = New->getType()->getAs<FunctionType>();
+  FunctionType::ExtInfo OldTypeInfo = OldType->getExtInfo();
+  FunctionType::ExtInfo NewTypeInfo = NewType->getExtInfo();
+  bool RequiresAdjustment = false;
+  if (OldTypeInfo.getCC() != CC_Default &&
+      NewTypeInfo.getCC() == CC_Default) {
+    NewTypeInfo = NewTypeInfo.withCallingConv(OldTypeInfo.getCC());
+    RequiresAdjustment = true;
+  } else if (!Context.isSameCallConv(OldTypeInfo.getCC(),
+                                     NewTypeInfo.getCC())) {
+    // Calling conventions really aren't compatible, so complain.
+    Diag(New->getLocation(), diag::err_cconv_change)
+      << FunctionType::getNameForCallConv(NewTypeInfo.getCC())
+      << (OldTypeInfo.getCC() == CC_Default)
+      << (OldTypeInfo.getCC() == CC_Default ? "" :
+          FunctionType::getNameForCallConv(OldTypeInfo.getCC()));
+    Diag(Old->getLocation(), diag::note_previous_declaration);
+    return true;
+  }
+
+  // FIXME: diagnose the other way around?
+  if (OldTypeInfo.getNoReturn() && !NewTypeInfo.getNoReturn()) {
+    NewTypeInfo = NewTypeInfo.withNoReturn(true);
+    RequiresAdjustment = true;
+  }
+
+  // Merge regparm attribute.
+  if (OldTypeInfo.getHasRegParm() != NewTypeInfo.getHasRegParm() ||
+      OldTypeInfo.getRegParm() != NewTypeInfo.getRegParm()) {
+    if (NewTypeInfo.getHasRegParm()) {
+      Diag(New->getLocation(), diag::err_regparm_mismatch)
+        << NewType->getRegParmType()
+        << OldType->getRegParmType();
+      Diag(Old->getLocation(), diag::note_previous_declaration);      
+      return true;
+    }
+
+    NewTypeInfo = NewTypeInfo.withRegParm(OldTypeInfo.getRegParm());
+    RequiresAdjustment = true;
+  }
+
+  // Merge ns_returns_retained attribute.
+  if (OldTypeInfo.getProducesResult() != NewTypeInfo.getProducesResult()) {
+    if (NewTypeInfo.getProducesResult()) {
+      Diag(New->getLocation(), diag::err_returns_retained_mismatch);
+      Diag(Old->getLocation(), diag::note_previous_declaration);      
+      return true;
+    }
+    
+    NewTypeInfo = NewTypeInfo.withProducesResult(true);
+    RequiresAdjustment = true;
+  }
+  
+  if (RequiresAdjustment) {
+    NewType = Context.adjustFunctionType(NewType, NewTypeInfo);
+    New->setType(QualType(NewType, 0));
+    NewQType = Context.getCanonicalType(New->getType());
+  }
+  
+  if (getLangOpts().CPlusPlus) {
+    // (C++98 13.1p2):
+    //   Certain function declarations cannot be overloaded:
+    //     -- Function declarations that differ only in the return type
+    //        cannot be overloaded.
+    QualType OldReturnType = OldType->getResultType();
+    QualType NewReturnType = cast<FunctionType>(NewQType)->getResultType();
+    QualType ResQT;
+    if (OldReturnType != NewReturnType) {
+      if (NewReturnType->isObjCObjectPointerType()
+          && OldReturnType->isObjCObjectPointerType())
+        ResQT = Context.mergeObjCGCQualifiers(NewQType, OldQType);
+      if (ResQT.isNull()) {
+        if (New->isCXXClassMember() && New->isOutOfLine())
+          Diag(New->getLocation(),
+               diag::err_member_def_does_not_match_ret_type) << New;
+        else
+          Diag(New->getLocation(), diag::err_ovl_diff_return_type);
+        Diag(Old->getLocation(), PrevDiag) << Old << Old->getType();
+        return true;
+      }
+      else
+        NewQType = ResQT;
+    }
+
+    const CXXMethodDecl* OldMethod = dyn_cast<CXXMethodDecl>(Old);
+    CXXMethodDecl* NewMethod = dyn_cast<CXXMethodDecl>(New);
+    if (OldMethod && NewMethod) {
+      // Preserve triviality.
+      NewMethod->setTrivial(OldMethod->isTrivial());
+
+      // MSVC allows explicit template specialization at class scope:
+      // 2 CXMethodDecls referring to the same function will be injected.
+      // We don't want a redeclartion error.
+      bool IsClassScopeExplicitSpecialization =
+                              OldMethod->isFunctionTemplateSpecialization() &&
+                              NewMethod->isFunctionTemplateSpecialization();
+      bool isFriend = NewMethod->getFriendObjectKind();
+
+      if (!isFriend && NewMethod->getLexicalDeclContext()->isRecord() &&
+          !IsClassScopeExplicitSpecialization) {
+        //    -- Member function declarations with the same name and the
+        //       same parameter types cannot be overloaded if any of them
+        //       is a static member function declaration.
+        if (OldMethod->isStatic() || NewMethod->isStatic()) {
+          Diag(New->getLocation(), diag::err_ovl_static_nonstatic_member);
+          Diag(Old->getLocation(), PrevDiag) << Old << Old->getType();
+          return true;
+        }
+      
+        // C++ [class.mem]p1:
+        //   [...] A member shall not be declared twice in the
+        //   member-specification, except that a nested class or member
+        //   class template can be declared and then later defined.
+        unsigned NewDiag;
+        if (isa<CXXConstructorDecl>(OldMethod))
+          NewDiag = diag::err_constructor_redeclared;
+        else if (isa<CXXDestructorDecl>(NewMethod))
+          NewDiag = diag::err_destructor_redeclared;
+        else if (isa<CXXConversionDecl>(NewMethod))
+          NewDiag = diag::err_conv_function_redeclared;
+        else
+          NewDiag = diag::err_member_redeclared;
+
+        Diag(New->getLocation(), NewDiag);
+        Diag(Old->getLocation(), PrevDiag) << Old << Old->getType();
+
+      // Complain if this is an explicit declaration of a special
+      // member that was initially declared implicitly.
+      //
+      // As an exception, it's okay to befriend such methods in order
+      // to permit the implicit constructor/destructor/operator calls.
+      } else if (OldMethod->isImplicit()) {
+        if (isFriend) {
+          NewMethod->setImplicit();
+        } else {
+          Diag(NewMethod->getLocation(),
+               diag::err_definition_of_implicitly_declared_member) 
+            << New << getSpecialMember(OldMethod);
+          return true;
+        }
+      } else if (OldMethod->isExplicitlyDefaulted()) {
+        Diag(NewMethod->getLocation(),
+             diag::err_definition_of_explicitly_defaulted_member)
+          << getSpecialMember(OldMethod);
+        return true;
+      }
+    }
+
+    // (C++98 8.3.5p3):
+    //   All declarations for a function shall agree exactly in both the
+    //   return type and the parameter-type-list.
+    // We also want to respect all the extended bits except noreturn.
+
+    // noreturn should now match unless the old type info didn't have it.
+    QualType OldQTypeForComparison = OldQType;
+    if (!OldTypeInfo.getNoReturn() && NewTypeInfo.getNoReturn()) {
+      assert(OldQType == QualType(OldType, 0));
+      const FunctionType *OldTypeForComparison
+        = Context.adjustFunctionType(OldType, OldTypeInfo.withNoReturn(true));
+      OldQTypeForComparison = QualType(OldTypeForComparison, 0);
+      assert(OldQTypeForComparison.isCanonical());
+    }
+
+    if (OldQTypeForComparison == NewQType)
+      return MergeCompatibleFunctionDecls(New, Old, S);
+
+    // Fall through for conflicting redeclarations and redefinitions.
+  }
+
+  // C: Function types need to be compatible, not identical. This handles
+  // duplicate function decls like "void f(int); void f(enum X);" properly.
+  if (!getLangOpts().CPlusPlus &&
+      Context.typesAreCompatible(OldQType, NewQType)) {
+    const FunctionType *OldFuncType = OldQType->getAs<FunctionType>();
+    const FunctionType *NewFuncType = NewQType->getAs<FunctionType>();
+    const FunctionProtoType *OldProto = 0;
+    if (isa<FunctionNoProtoType>(NewFuncType) &&
+        (OldProto = dyn_cast<FunctionProtoType>(OldFuncType))) {
+      // The old declaration provided a function prototype, but the
+      // new declaration does not. Merge in the prototype.
+      assert(!OldProto->hasExceptionSpec() && "Exception spec in C");
+      SmallVector<QualType, 16> ParamTypes(OldProto->arg_type_begin(),
+                                                 OldProto->arg_type_end());
+      NewQType = Context.getFunctionType(NewFuncType->getResultType(),
+                                         ParamTypes.data(), ParamTypes.size(),
+                                         OldProto->getExtProtoInfo());
+      New->setType(NewQType);
+      New->setHasInheritedPrototype();
+
+      // Synthesize a parameter for each argument type.
+      SmallVector<ParmVarDecl*, 16> Params;
+      for (FunctionProtoType::arg_type_iterator
+             ParamType = OldProto->arg_type_begin(),
+             ParamEnd = OldProto->arg_type_end();
+           ParamType != ParamEnd; ++ParamType) {
+        ParmVarDecl *Param = ParmVarDecl::Create(Context, New,
+                                                 SourceLocation(),
+                                                 SourceLocation(), 0,
+                                                 *ParamType, /*TInfo=*/0,
+                                                 SC_None, SC_None,
+                                                 0);
+        Param->setScopeInfo(0, Params.size());
+        Param->setImplicit();
+        Params.push_back(Param);
+      }
+
+      New->setParams(Params);
+    }
+
+    return MergeCompatibleFunctionDecls(New, Old, S);
+  }
+
+  // GNU C permits a K&R definition to follow a prototype declaration
+  // if the declared types of the parameters in the K&R definition
+  // match the types in the prototype declaration, even when the
+  // promoted types of the parameters from the K&R definition differ
+  // from the types in the prototype. GCC then keeps the types from
+  // the prototype.
+  //
+  // If a variadic prototype is followed by a non-variadic K&R definition,
+  // the K&R definition becomes variadic.  This is sort of an edge case, but
+  // it's legal per the standard depending on how you read C99 6.7.5.3p15 and
+  // C99 6.9.1p8.
+  if (!getLangOpts().CPlusPlus &&
+      Old->hasPrototype() && !New->hasPrototype() &&
+      New->getType()->getAs<FunctionProtoType>() &&
+      Old->getNumParams() == New->getNumParams()) {
+    SmallVector<QualType, 16> ArgTypes;
+    SmallVector<GNUCompatibleParamWarning, 16> Warnings;
+    const FunctionProtoType *OldProto
+      = Old->getType()->getAs<FunctionProtoType>();
+    const FunctionProtoType *NewProto
+      = New->getType()->getAs<FunctionProtoType>();
+
+    // Determine whether this is the GNU C extension.
+    QualType MergedReturn = Context.mergeTypes(OldProto->getResultType(),
+                                               NewProto->getResultType());
+    bool LooseCompatible = !MergedReturn.isNull();
+    for (unsigned Idx = 0, End = Old->getNumParams();
+         LooseCompatible && Idx != End; ++Idx) {
+      ParmVarDecl *OldParm = Old->getParamDecl(Idx);
+      ParmVarDecl *NewParm = New->getParamDecl(Idx);
+      if (Context.typesAreCompatible(OldParm->getType(),
+                                     NewProto->getArgType(Idx))) {
+        ArgTypes.push_back(NewParm->getType());
+      } else if (Context.typesAreCompatible(OldParm->getType(),
+                                            NewParm->getType(),
+                                            /*CompareUnqualified=*/true)) {
+        GNUCompatibleParamWarning Warn
+          = { OldParm, NewParm, NewProto->getArgType(Idx) };
+        Warnings.push_back(Warn);
+        ArgTypes.push_back(NewParm->getType());
+      } else
+        LooseCompatible = false;
+    }
+
+    if (LooseCompatible) {
+      for (unsigned Warn = 0; Warn < Warnings.size(); ++Warn) {
+        Diag(Warnings[Warn].NewParm->getLocation(),
+             diag::ext_param_promoted_not_compatible_with_prototype)
+          << Warnings[Warn].PromotedType
+          << Warnings[Warn].OldParm->getType();
+        if (Warnings[Warn].OldParm->getLocation().isValid())
+          Diag(Warnings[Warn].OldParm->getLocation(),
+               diag::note_previous_declaration);
+      }
+
+      New->setType(Context.getFunctionType(MergedReturn, &ArgTypes[0],
+                                           ArgTypes.size(),
+                                           OldProto->getExtProtoInfo()));
+      return MergeCompatibleFunctionDecls(New, Old, S);
+    }
+
+    // Fall through to diagnose conflicting types.
+  }
+
+  // A function that has already been declared has been redeclared or defined
+  // with a different type- show appropriate diagnostic
+  if (unsigned BuiltinID = Old->getBuiltinID()) {
+    // The user has declared a builtin function with an incompatible
+    // signature.
+    if (Context.BuiltinInfo.isPredefinedLibFunction(BuiltinID)) {
+      // The function the user is redeclaring is a library-defined
+      // function like 'malloc' or 'printf'. Warn about the
+      // redeclaration, then pretend that we don't know about this
+      // library built-in.
+      Diag(New->getLocation(), diag::warn_redecl_library_builtin) << New;
+      Diag(Old->getLocation(), diag::note_previous_builtin_declaration)
+        << Old << Old->getType();
+      New->getIdentifier()->setBuiltinID(Builtin::NotBuiltin);
+      Old->setInvalidDecl();
+      return false;
+    }
+
+    PrevDiag = diag::note_previous_builtin_declaration;
+  }
+
+  Diag(New->getLocation(), diag::err_conflicting_types) << New->getDeclName();
+  Diag(Old->getLocation(), PrevDiag) << Old << Old->getType();
+  return true;
+}
+
+/// \brief Completes the merge of two function declarations that are
+/// known to be compatible.
+///
+/// This routine handles the merging of attributes and other
+/// properties of function declarations form the old declaration to
+/// the new declaration, once we know that New is in fact a
+/// redeclaration of Old.
+///
+/// \returns false
+bool Sema::MergeCompatibleFunctionDecls(FunctionDecl *New, FunctionDecl *Old,
+                                        Scope *S) {
+  // Merge the attributes
+  mergeDeclAttributes(New, Old);
+
+  // Merge the storage class.
+  if (Old->getStorageClass() != SC_Extern &&
+      Old->getStorageClass() != SC_None)
+    New->setStorageClass(Old->getStorageClass());
+
+  // Merge "pure" flag.
+  if (Old->isPure())
+    New->setPure();
+
+  // Merge attributes from the parameters.  These can mismatch with K&R
+  // declarations.
+  if (New->getNumParams() == Old->getNumParams())
+    for (unsigned i = 0, e = New->getNumParams(); i != e; ++i)
+      mergeParamDeclAttributes(New->getParamDecl(i), Old->getParamDecl(i),
+                               Context);
+
+  if (getLangOpts().CPlusPlus)
+    return MergeCXXFunctionDecl(New, Old, S);
+
+  return false;
+}
+
+
+void Sema::mergeObjCMethodDecls(ObjCMethodDecl *newMethod,
+                                ObjCMethodDecl *oldMethod) {
+  // We don't want to merge unavailable and deprecated attributes
+  // except from interface to implementation.
+  bool mergeDeprecation = isa<ObjCImplDecl>(newMethod->getDeclContext());
+
+  // Merge the attributes.
+  mergeDeclAttributes(newMethod, oldMethod, mergeDeprecation);
+
+  // Merge attributes from the parameters.
+  ObjCMethodDecl::param_const_iterator oi = oldMethod->param_begin();
+  for (ObjCMethodDecl::param_iterator
+         ni = newMethod->param_begin(), ne = newMethod->param_end();
+       ni != ne; ++ni, ++oi)
+    mergeParamDeclAttributes(*ni, *oi, Context);
+
+  CheckObjCMethodOverride(newMethod, oldMethod, true);
+}
+
+/// MergeVarDeclTypes - We parsed a variable 'New' which has the same name and
+/// scope as a previous declaration 'Old'.  Figure out how to merge their types,
+/// emitting diagnostics as appropriate.
+///
+/// Declarations using the auto type specifier (C++ [decl.spec.auto]) call back
+/// to here in AddInitializerToDecl. We can't check them before the initializer
+/// is attached.
+void Sema::MergeVarDeclTypes(VarDecl *New, VarDecl *Old) {
+  if (New->isInvalidDecl() || Old->isInvalidDecl())
+    return;
+
+  QualType MergedT;
+  if (getLangOpts().CPlusPlus) {
+    AutoType *AT = New->getType()->getContainedAutoType();
+    if (AT && !AT->isDeduced()) {
+      // We don't know what the new type is until the initializer is attached.
+      return;
+    } else if (Context.hasSameType(New->getType(), Old->getType())) {
+      // These could still be something that needs exception specs checked.
+      return MergeVarDeclExceptionSpecs(New, Old);
+    }
+    // C++ [basic.link]p10:
+    //   [...] the types specified by all declarations referring to a given
+    //   object or function shall be identical, except that declarations for an
+    //   array object can specify array types that differ by the presence or
+    //   absence of a major array bound (8.3.4).
+    else if (Old->getType()->isIncompleteArrayType() &&
+             New->getType()->isArrayType()) {
+      CanQual<ArrayType> OldArray
+        = Context.getCanonicalType(Old->getType())->getAs<ArrayType>();
+      CanQual<ArrayType> NewArray
+        = Context.getCanonicalType(New->getType())->getAs<ArrayType>();
+      if (OldArray->getElementType() == NewArray->getElementType())
+        MergedT = New->getType();
+    } else if (Old->getType()->isArrayType() &&
+             New->getType()->isIncompleteArrayType()) {
+      CanQual<ArrayType> OldArray
+        = Context.getCanonicalType(Old->getType())->getAs<ArrayType>();
+      CanQual<ArrayType> NewArray
+        = Context.getCanonicalType(New->getType())->getAs<ArrayType>();
+      if (OldArray->getElementType() == NewArray->getElementType())
+        MergedT = Old->getType();
+    } else if (New->getType()->isObjCObjectPointerType()
+               && Old->getType()->isObjCObjectPointerType()) {
+        MergedT = Context.mergeObjCGCQualifiers(New->getType(),
+                                                        Old->getType());
+    }
+  } else {
+    MergedT = Context.mergeTypes(New->getType(), Old->getType());
+  }
+  if (MergedT.isNull()) {
+    Diag(New->getLocation(), diag::err_redefinition_different_type)
+      << New->getDeclName();
+    Diag(Old->getLocation(), diag::note_previous_definition);
+    return New->setInvalidDecl();
+  }
+  New->setType(MergedT);
+}
+
+/// MergeVarDecl - We just parsed a variable 'New' which has the same name
+/// and scope as a previous declaration 'Old'.  Figure out how to resolve this
+/// situation, merging decls or emitting diagnostics as appropriate.
+///
+/// Tentative definition rules (C99 6.9.2p2) are checked by
+/// FinalizeDeclaratorGroup. Unfortunately, we can't analyze tentative
+/// definitions here, since the initializer hasn't been attached.
+///
+void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous) {
+  // If the new decl is already invalid, don't do any other checking.
+  if (New->isInvalidDecl())
+    return;
+
+  // Verify the old decl was also a variable.
+  VarDecl *Old = 0;
+  if (!Previous.isSingleResult() ||
+      !(Old = dyn_cast<VarDecl>(Previous.getFoundDecl()))) {
+    Diag(New->getLocation(), diag::err_redefinition_different_kind)
+      << New->getDeclName();
+    Diag(Previous.getRepresentativeDecl()->getLocation(),
+         diag::note_previous_definition);
+    return New->setInvalidDecl();
+  }
+
+  // C++ [class.mem]p1:
+  //   A member shall not be declared twice in the member-specification [...]
+  // 
+  // Here, we need only consider static data members.
+  if (Old->isStaticDataMember() && !New->isOutOfLine()) {
+    Diag(New->getLocation(), diag::err_duplicate_member) 
+      << New->getIdentifier();
+    Diag(Old->getLocation(), diag::note_previous_declaration);
+    New->setInvalidDecl();
+  }
+  
+  mergeDeclAttributes(New, Old);
+  // Warn if an already-declared variable is made a weak_import in a subsequent 
+  // declaration
+  if (New->getAttr<WeakImportAttr>() &&
+      Old->getStorageClass() == SC_None &&
+      !Old->getAttr<WeakImportAttr>()) {
+    Diag(New->getLocation(), diag::warn_weak_import) << New->getDeclName();
+    Diag(Old->getLocation(), diag::note_previous_definition);
+    // Remove weak_import attribute on new declaration.
+    New->dropAttr<WeakImportAttr>();
+  }
+
+  // Merge the types.
+  MergeVarDeclTypes(New, Old);
+  if (New->isInvalidDecl())
+    return;
+
+  // C99 6.2.2p4: Check if we have a static decl followed by a non-static.
+  if (New->getStorageClass() == SC_Static &&
+      (Old->getStorageClass() == SC_None || Old->hasExternalStorage())) {
+    Diag(New->getLocation(), diag::err_static_non_static) << New->getDeclName();
+    Diag(Old->getLocation(), diag::note_previous_definition);
+    return New->setInvalidDecl();
+  }
+  // C99 6.2.2p4:
+  //   For an identifier declared with the storage-class specifier
+  //   extern in a scope in which a prior declaration of that
+  //   identifier is visible,23) if the prior declaration specifies
+  //   internal or external linkage, the linkage of the identifier at
+  //   the later declaration is the same as the linkage specified at
+  //   the prior declaration. If no prior declaration is visible, or
+  //   if the prior declaration specifies no linkage, then the
+  //   identifier has external linkage.
+  if (New->hasExternalStorage() && Old->hasLinkage())
+    /* Okay */;
+  else if (New->getStorageClass() != SC_Static &&
+           Old->getStorageClass() == SC_Static) {
+    Diag(New->getLocation(), diag::err_non_static_static) << New->getDeclName();
+    Diag(Old->getLocation(), diag::note_previous_definition);
+    return New->setInvalidDecl();
+  }
+
+  // Check if extern is followed by non-extern and vice-versa.
+  if (New->hasExternalStorage() &&
+      !Old->hasLinkage() && Old->isLocalVarDecl()) {
+    Diag(New->getLocation(), diag::err_extern_non_extern) << New->getDeclName();
+    Diag(Old->getLocation(), diag::note_previous_definition);
+    return New->setInvalidDecl();
+  }
+  if (Old->hasExternalStorage() &&
+      !New->hasLinkage() && New->isLocalVarDecl()) {
+    Diag(New->getLocation(), diag::err_non_extern_extern) << New->getDeclName();
+    Diag(Old->getLocation(), diag::note_previous_definition);
+    return New->setInvalidDecl();
+  }
+
+  // Variables with external linkage are analyzed in FinalizeDeclaratorGroup.
+
+  // FIXME: The test for external storage here seems wrong? We still
+  // need to check for mismatches.
+  if (!New->hasExternalStorage() && !New->isFileVarDecl() &&
+      // Don't complain about out-of-line definitions of static members.
+      !(Old->getLexicalDeclContext()->isRecord() &&
+        !New->getLexicalDeclContext()->isRecord())) {
+    Diag(New->getLocation(), diag::err_redefinition) << New->getDeclName();
+    Diag(Old->getLocation(), diag::note_previous_definition);
+    return New->setInvalidDecl();
+  }
+
+  if (New->isThreadSpecified() && !Old->isThreadSpecified()) {
+    Diag(New->getLocation(), diag::err_thread_non_thread) << New->getDeclName();
+    Diag(Old->getLocation(), diag::note_previous_definition);
+  } else if (!New->isThreadSpecified() && Old->isThreadSpecified()) {
+    Diag(New->getLocation(), diag::err_non_thread_thread) << New->getDeclName();
+    Diag(Old->getLocation(), diag::note_previous_definition);
+  }
+
+  // C++ doesn't have tentative definitions, so go right ahead and check here.
+  const VarDecl *Def;
+  if (getLangOpts().CPlusPlus &&
+      New->isThisDeclarationADefinition() == VarDecl::Definition &&
+      (Def = Old->getDefinition())) {
+    Diag(New->getLocation(), diag::err_redefinition)
+      << New->getDeclName();
+    Diag(Def->getLocation(), diag::note_previous_definition);
+    New->setInvalidDecl();
+    return;
+  }
+  // c99 6.2.2 P4.
+  // For an identifier declared with the storage-class specifier extern in a
+  // scope in which a prior declaration of that identifier is visible, if 
+  // the prior declaration specifies internal or external linkage, the linkage 
+  // of the identifier at the later declaration is the same as the linkage 
+  // specified at the prior declaration.
+  // FIXME. revisit this code.
+  if (New->hasExternalStorage() &&
+      Old->getLinkage() == InternalLinkage &&
+      New->getDeclContext() == Old->getDeclContext())
+    New->setStorageClass(Old->getStorageClass());
+
+  // Keep a chain of previous declarations.
+  New->setPreviousDeclaration(Old);
+
+  // Inherit access appropriately.
+  New->setAccess(Old->getAccess());
+}
+
+/// ParsedFreeStandingDeclSpec - This method is invoked when a declspec with
+/// no declarator (e.g. "struct foo;") is parsed.
+Decl *Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS,
+                                       DeclSpec &DS) {
+  return ParsedFreeStandingDeclSpec(S, AS, DS,
+                                    MultiTemplateParamsArg(*this, 0, 0));
+}
+
+/// ParsedFreeStandingDeclSpec - This method is invoked when a declspec with
+/// no declarator (e.g. "struct foo;") is parsed. It also accopts template
+/// parameters to cope with template friend declarations.
+Decl *Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS,
+                                       DeclSpec &DS,
+                                       MultiTemplateParamsArg TemplateParams) {
+  Decl *TagD = 0;
+  TagDecl *Tag = 0;
+  if (DS.getTypeSpecType() == DeclSpec::TST_class ||
+      DS.getTypeSpecType() == DeclSpec::TST_struct ||
+      DS.getTypeSpecType() == DeclSpec::TST_union ||
+      DS.getTypeSpecType() == DeclSpec::TST_enum) {
+    TagD = DS.getRepAsDecl();
+
+    if (!TagD) // We probably had an error
+      return 0;
+
+    // Note that the above type specs guarantee that the
+    // type rep is a Decl, whereas in many of the others
+    // it's a Type.
+    if (isa<TagDecl>(TagD))
+      Tag = cast<TagDecl>(TagD);
+    else if (ClassTemplateDecl *CTD = dyn_cast<ClassTemplateDecl>(TagD))
+      Tag = CTD->getTemplatedDecl();
+  }
+
+  if (Tag) {
+    Tag->setFreeStanding();
+    if (Tag->isInvalidDecl())
+      return Tag;
+  }
+
+  if (unsigned TypeQuals = DS.getTypeQualifiers()) {
+    // Enforce C99 6.7.3p2: "Types other than pointer types derived from object
+    // or incomplete types shall not be restrict-qualified."
+    if (TypeQuals & DeclSpec::TQ_restrict)
+      Diag(DS.getRestrictSpecLoc(),
+           diag::err_typecheck_invalid_restrict_not_pointer_noarg)
+           << DS.getSourceRange();
+  }
+
+  if (DS.isConstexprSpecified()) {
+    // C++0x [dcl.constexpr]p1: constexpr can only be applied to declarations
+    // and definitions of functions and variables.
+    if (Tag)
+      Diag(DS.getConstexprSpecLoc(), diag::err_constexpr_tag)
+        << (DS.getTypeSpecType() == DeclSpec::TST_class ? 0 :
+            DS.getTypeSpecType() == DeclSpec::TST_struct ? 1 :
+            DS.getTypeSpecType() == DeclSpec::TST_union ? 2 : 3);
+    else
+      Diag(DS.getConstexprSpecLoc(), diag::err_constexpr_no_declarators);
+    // Don't emit warnings after this error.
+    return TagD;
+  }
+
+  if (DS.isFriendSpecified()) {
+    // If we're dealing with a decl but not a TagDecl, assume that
+    // whatever routines created it handled the friendship aspect.
+    if (TagD && !Tag)
+      return 0;
+    return ActOnFriendTypeDecl(S, DS, TemplateParams);
+  }
+
+  // Track whether we warned about the fact that there aren't any
+  // declarators.
+  bool emittedWarning = false;
+         
+  if (RecordDecl *Record = dyn_cast_or_null<RecordDecl>(Tag)) {
+    if (!Record->getDeclName() && Record->isCompleteDefinition() &&
+        DS.getStorageClassSpec() != DeclSpec::SCS_typedef) {
+      if (getLangOpts().CPlusPlus ||
+          Record->getDeclContext()->isRecord())
+        return BuildAnonymousStructOrUnion(S, DS, AS, Record);
+
+      Diag(DS.getLocStart(), diag::ext_no_declarators)
+        << DS.getSourceRange();
+      emittedWarning = true;
+    }
+  }
+
+  // Check for Microsoft C extension: anonymous struct.
+  if (getLangOpts().MicrosoftExt && !getLangOpts().CPlusPlus &&
+      CurContext->isRecord() &&
+      DS.getStorageClassSpec() == DeclSpec::SCS_unspecified) {
+    // Handle 2 kinds of anonymous struct:
+    //   struct STRUCT;
+    // and
+    //   STRUCT_TYPE;  <- where STRUCT_TYPE is a typedef struct.
+    RecordDecl *Record = dyn_cast_or_null<RecordDecl>(Tag);
+    if ((Record && Record->getDeclName() && !Record->isCompleteDefinition()) ||
+        (DS.getTypeSpecType() == DeclSpec::TST_typename &&
+         DS.getRepAsType().get()->isStructureType())) {
+      Diag(DS.getLocStart(), diag::ext_ms_anonymous_struct)
+        << DS.getSourceRange();
+      return BuildMicrosoftCAnonymousStruct(S, DS, Record);
+    }
+  }
+  
+  if (getLangOpts().CPlusPlus && 
+      DS.getStorageClassSpec() != DeclSpec::SCS_typedef)
+    if (EnumDecl *Enum = dyn_cast_or_null<EnumDecl>(Tag))
+      if (Enum->enumerator_begin() == Enum->enumerator_end() &&
+          !Enum->getIdentifier() && !Enum->isInvalidDecl()) {
+        Diag(Enum->getLocation(), diag::ext_no_declarators)
+          << DS.getSourceRange();
+        emittedWarning = true;
+      }
+
+  // Skip all the checks below if we have a type error.
+  if (DS.getTypeSpecType() == DeclSpec::TST_error) return TagD;
+      
+  if (!DS.isMissingDeclaratorOk()) {
+    // Warn about typedefs of enums without names, since this is an
+    // extension in both Microsoft and GNU.
+    if (DS.getStorageClassSpec() == DeclSpec::SCS_typedef &&
+        Tag && isa<EnumDecl>(Tag)) {
+      Diag(DS.getLocStart(), diag::ext_typedef_without_a_name)
+        << DS.getSourceRange();
+      return Tag;
+    }
+
+    Diag(DS.getLocStart(), diag::ext_no_declarators)
+      << DS.getSourceRange();
+    emittedWarning = true;
+  }
+
+  // We're going to complain about a bunch of spurious specifiers;
+  // only do this if we're declaring a tag, because otherwise we
+  // should be getting diag::ext_no_declarators.
+  if (emittedWarning || (TagD && TagD->isInvalidDecl()))
+    return TagD;
+
+  // Note that a linkage-specification sets a storage class, but
+  // 'extern "C" struct foo;' is actually valid and not theoretically
+  // useless.
+  if (DeclSpec::SCS scs = DS.getStorageClassSpec())
+    if (!DS.isExternInLinkageSpec())
+      Diag(DS.getStorageClassSpecLoc(), diag::warn_standalone_specifier)
+        << DeclSpec::getSpecifierName(scs);
+
+  if (DS.isThreadSpecified())
+    Diag(DS.getThreadSpecLoc(), diag::warn_standalone_specifier) << "__thread";
+  if (DS.getTypeQualifiers()) {
+    if (DS.getTypeQualifiers() & DeclSpec::TQ_const)
+      Diag(DS.getConstSpecLoc(), diag::warn_standalone_specifier) << "const";
+    if (DS.getTypeQualifiers() & DeclSpec::TQ_volatile)
+      Diag(DS.getConstSpecLoc(), diag::warn_standalone_specifier) << "volatile";
+    // Restrict is covered above.
+  }
+  if (DS.isInlineSpecified())
+    Diag(DS.getInlineSpecLoc(), diag::warn_standalone_specifier) << "inline";
+  if (DS.isVirtualSpecified())
+    Diag(DS.getVirtualSpecLoc(), diag::warn_standalone_specifier) << "virtual";
+  if (DS.isExplicitSpecified())
+    Diag(DS.getExplicitSpecLoc(), diag::warn_standalone_specifier) <<"explicit";
+
+  if (DS.isModulePrivateSpecified() && 
+      Tag && Tag->getDeclContext()->isFunctionOrMethod())
+    Diag(DS.getModulePrivateSpecLoc(), diag::err_module_private_local_class)
+      << Tag->getTagKind()
+      << FixItHint::CreateRemoval(DS.getModulePrivateSpecLoc());
+
+  // Warn about ignored type attributes, for example:
+  // __attribute__((aligned)) struct A;
+  // Attributes should be placed after tag to apply to type declaration.
+  if (!DS.getAttributes().empty()) {
+    DeclSpec::TST TypeSpecType = DS.getTypeSpecType();
+    if (TypeSpecType == DeclSpec::TST_class ||
+        TypeSpecType == DeclSpec::TST_struct ||
+        TypeSpecType == DeclSpec::TST_union ||
+        TypeSpecType == DeclSpec::TST_enum) {
+      AttributeList* attrs = DS.getAttributes().getList();
+      while (attrs) {
+        Diag(attrs->getScopeLoc(),
+             diag::warn_declspec_attribute_ignored)
+        << attrs->getName()
+        << (TypeSpecType == DeclSpec::TST_class ? 0 :
+            TypeSpecType == DeclSpec::TST_struct ? 1 :
+            TypeSpecType == DeclSpec::TST_union ? 2 : 3);
+        attrs = attrs->getNext();
+      }
+    }
+  }
+
+  return TagD;
+}
+
+/// We are trying to inject an anonymous member into the given scope;
+/// check if there's an existing declaration that can't be overloaded.
+///
+/// \return true if this is a forbidden redeclaration
+static bool CheckAnonMemberRedeclaration(Sema &SemaRef,
+                                         Scope *S,
+                                         DeclContext *Owner,
+                                         DeclarationName Name,
+                                         SourceLocation NameLoc,
+                                         unsigned diagnostic) {
+  LookupResult R(SemaRef, Name, NameLoc, Sema::LookupMemberName,
+                 Sema::ForRedeclaration);
+  if (!SemaRef.LookupName(R, S)) return false;
+
+  if (R.getAsSingle<TagDecl>())
+    return false;
+
+  // Pick a representative declaration.
+  NamedDecl *PrevDecl = R.getRepresentativeDecl()->getUnderlyingDecl();
+  assert(PrevDecl && "Expected a non-null Decl");
+
+  if (!SemaRef.isDeclInScope(PrevDecl, Owner, S))
+    return false;
+
+  SemaRef.Diag(NameLoc, diagnostic) << Name;
+  SemaRef.Diag(PrevDecl->getLocation(), diag::note_previous_declaration);
+
+  return true;
+}
+
+/// InjectAnonymousStructOrUnionMembers - Inject the members of the
+/// anonymous struct or union AnonRecord into the owning context Owner
+/// and scope S. This routine will be invoked just after we realize
+/// that an unnamed union or struct is actually an anonymous union or
+/// struct, e.g.,
+///
+/// @code
+/// union {
+///   int i;
+///   float f;
+/// }; // InjectAnonymousStructOrUnionMembers called here to inject i and
+///    // f into the surrounding scope.x
+/// @endcode
+///
+/// This routine is recursive, injecting the names of nested anonymous
+/// structs/unions into the owning context and scope as well.
+static bool InjectAnonymousStructOrUnionMembers(Sema &SemaRef, Scope *S,
+                                                DeclContext *Owner,
+                                                RecordDecl *AnonRecord,
+                                                AccessSpecifier AS,
+                              SmallVector<NamedDecl*, 2> &Chaining,
+                                                      bool MSAnonStruct) {
+  unsigned diagKind
+    = AnonRecord->isUnion() ? diag::err_anonymous_union_member_redecl
+                            : diag::err_anonymous_struct_member_redecl;
+
+  bool Invalid = false;
+
+  // Look every FieldDecl and IndirectFieldDecl with a name.
+  for (RecordDecl::decl_iterator D = AnonRecord->decls_begin(),
+                               DEnd = AnonRecord->decls_end();
+       D != DEnd; ++D) {
+    if ((isa<FieldDecl>(*D) || isa<IndirectFieldDecl>(*D)) &&
+        cast<NamedDecl>(*D)->getDeclName()) {
+      ValueDecl *VD = cast<ValueDecl>(*D);
+      if (CheckAnonMemberRedeclaration(SemaRef, S, Owner, VD->getDeclName(),
+                                       VD->getLocation(), diagKind)) {
+        // C++ [class.union]p2:
+        //   The names of the members of an anonymous union shall be
+        //   distinct from the names of any other entity in the
+        //   scope in which the anonymous union is declared.
+        Invalid = true;
+      } else {
+        // C++ [class.union]p2:
+        //   For the purpose of name lookup, after the anonymous union
+        //   definition, the members of the anonymous union are
+        //   considered to have been defined in the scope in which the
+        //   anonymous union is declared.
+        unsigned OldChainingSize = Chaining.size();
+        if (IndirectFieldDecl *IF = dyn_cast<IndirectFieldDecl>(VD))
+          for (IndirectFieldDecl::chain_iterator PI = IF->chain_begin(),
+               PE = IF->chain_end(); PI != PE; ++PI)
+            Chaining.push_back(*PI);
+        else
+          Chaining.push_back(VD);
+
+        assert(Chaining.size() >= 2);
+        NamedDecl **NamedChain =
+          new (SemaRef.Context)NamedDecl*[Chaining.size()];
+        for (unsigned i = 0; i < Chaining.size(); i++)
+          NamedChain[i] = Chaining[i];
+
+        IndirectFieldDecl* IndirectField =
+          IndirectFieldDecl::Create(SemaRef.Context, Owner, VD->getLocation(),
+                                    VD->getIdentifier(), VD->getType(),
+                                    NamedChain, Chaining.size());
+
+        IndirectField->setAccess(AS);
+        IndirectField->setImplicit();
+        SemaRef.PushOnScopeChains(IndirectField, S);
+
+        // That includes picking up the appropriate access specifier.
+        if (AS != AS_none) IndirectField->setAccess(AS);
+
+        Chaining.resize(OldChainingSize);
+      }
+    }
+  }
+
+  return Invalid;
+}
+
+/// StorageClassSpecToVarDeclStorageClass - Maps a DeclSpec::SCS to
+/// a VarDecl::StorageClass. Any error reporting is up to the caller:
+/// illegal input values are mapped to SC_None.
+static StorageClass
+StorageClassSpecToVarDeclStorageClass(DeclSpec::SCS StorageClassSpec) {
+  switch (StorageClassSpec) {
+  case DeclSpec::SCS_unspecified:    return SC_None;
+  case DeclSpec::SCS_extern:         return SC_Extern;
+  case DeclSpec::SCS_static:         return SC_Static;
+  case DeclSpec::SCS_auto:           return SC_Auto;
+  case DeclSpec::SCS_register:       return SC_Register;
+  case DeclSpec::SCS_private_extern: return SC_PrivateExtern;
+    // Illegal SCSs map to None: error reporting is up to the caller.
+  case DeclSpec::SCS_mutable:        // Fall through.
+  case DeclSpec::SCS_typedef:        return SC_None;
+  }
+  llvm_unreachable("unknown storage class specifier");
+}
+
+/// StorageClassSpecToFunctionDeclStorageClass - Maps a DeclSpec::SCS to
+/// a StorageClass. Any error reporting is up to the caller:
+/// illegal input values are mapped to SC_None.
+static StorageClass
+StorageClassSpecToFunctionDeclStorageClass(DeclSpec::SCS StorageClassSpec) {
+  switch (StorageClassSpec) {
+  case DeclSpec::SCS_unspecified:    return SC_None;
+  case DeclSpec::SCS_extern:         return SC_Extern;
+  case DeclSpec::SCS_static:         return SC_Static;
+  case DeclSpec::SCS_private_extern: return SC_PrivateExtern;
+    // Illegal SCSs map to None: error reporting is up to the caller.
+  case DeclSpec::SCS_auto:           // Fall through.
+  case DeclSpec::SCS_mutable:        // Fall through.
+  case DeclSpec::SCS_register:       // Fall through.
+  case DeclSpec::SCS_typedef:        return SC_None;
+  }
+  llvm_unreachable("unknown storage class specifier");
+}
+
+/// BuildAnonymousStructOrUnion - Handle the declaration of an
+/// anonymous structure or union. Anonymous unions are a C++ feature
+/// (C++ [class.union]) and a C11 feature; anonymous structures
+/// are a C11 feature and GNU C++ extension.
+Decl *Sema::BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS,
+                                             AccessSpecifier AS,
+                                             RecordDecl *Record) {
+  DeclContext *Owner = Record->getDeclContext();
+
+  // Diagnose whether this anonymous struct/union is an extension.
+  if (Record->isUnion() && !getLangOpts().CPlusPlus && !getLangOpts().C11)
+    Diag(Record->getLocation(), diag::ext_anonymous_union);
+  else if (!Record->isUnion() && getLangOpts().CPlusPlus)
+    Diag(Record->getLocation(), diag::ext_gnu_anonymous_struct);
+  else if (!Record->isUnion() && !getLangOpts().C11)
+    Diag(Record->getLocation(), diag::ext_c11_anonymous_struct);
+
+  // C and C++ require different kinds of checks for anonymous
+  // structs/unions.
+  bool Invalid = false;
+  if (getLangOpts().CPlusPlus) {
+    const char* PrevSpec = 0;
+    unsigned DiagID;
+    if (Record->isUnion()) {
+      // C++ [class.union]p6:
+      //   Anonymous unions declared in a named namespace or in the
+      //   global namespace shall be declared static.
+      if (DS.getStorageClassSpec() != DeclSpec::SCS_static &&
+          (isa<TranslationUnitDecl>(Owner) ||
+           (isa<NamespaceDecl>(Owner) &&
+            cast<NamespaceDecl>(Owner)->getDeclName()))) {
+        Diag(Record->getLocation(), diag::err_anonymous_union_not_static)
+          << FixItHint::CreateInsertion(Record->getLocation(), "static ");
+  
+        // Recover by adding 'static'.
+        DS.SetStorageClassSpec(*this, DeclSpec::SCS_static, SourceLocation(),
+                               PrevSpec, DiagID);
+      }
+      // C++ [class.union]p6:
+      //   A storage class is not allowed in a declaration of an
+      //   anonymous union in a class scope.
+      else if (DS.getStorageClassSpec() != DeclSpec::SCS_unspecified &&
+               isa<RecordDecl>(Owner)) {
+        Diag(DS.getStorageClassSpecLoc(),
+             diag::err_anonymous_union_with_storage_spec)
+          << FixItHint::CreateRemoval(DS.getStorageClassSpecLoc());
+  
+        // Recover by removing the storage specifier.
+        DS.SetStorageClassSpec(*this, DeclSpec::SCS_unspecified, 
+                               SourceLocation(),
+                               PrevSpec, DiagID);
+      }
+    }
+
+    // Ignore const/volatile/restrict qualifiers.
+    if (DS.getTypeQualifiers()) {
+      if (DS.getTypeQualifiers() & DeclSpec::TQ_const)
+        Diag(DS.getConstSpecLoc(), diag::ext_anonymous_struct_union_qualified)
+          << Record->isUnion() << 0 
+          << FixItHint::CreateRemoval(DS.getConstSpecLoc());
+      if (DS.getTypeQualifiers() & DeclSpec::TQ_volatile)
+        Diag(DS.getVolatileSpecLoc(), 
+             diag::ext_anonymous_struct_union_qualified)
+          << Record->isUnion() << 1
+          << FixItHint::CreateRemoval(DS.getVolatileSpecLoc());
+      if (DS.getTypeQualifiers() & DeclSpec::TQ_restrict)
+        Diag(DS.getRestrictSpecLoc(), 
+             diag::ext_anonymous_struct_union_qualified)
+          << Record->isUnion() << 2 
+          << FixItHint::CreateRemoval(DS.getRestrictSpecLoc());
+
+      DS.ClearTypeQualifiers();
+    }
+
+    // C++ [class.union]p2:
+    //   The member-specification of an anonymous union shall only
+    //   define non-static data members. [Note: nested types and
+    //   functions cannot be declared within an anonymous union. ]
+    for (DeclContext::decl_iterator Mem = Record->decls_begin(),
+                                 MemEnd = Record->decls_end();
+         Mem != MemEnd; ++Mem) {
+      if (FieldDecl *FD = dyn_cast<FieldDecl>(*Mem)) {
+        // C++ [class.union]p3:
+        //   An anonymous union shall not have private or protected
+        //   members (clause 11).
+        assert(FD->getAccess() != AS_none);
+        if (FD->getAccess() != AS_public) {
+          Diag(FD->getLocation(), diag::err_anonymous_record_nonpublic_member)
+            << (int)Record->isUnion() << (int)(FD->getAccess() == AS_protected);
+          Invalid = true;
+        }
+
+        // C++ [class.union]p1
+        //   An object of a class with a non-trivial constructor, a non-trivial
+        //   copy constructor, a non-trivial destructor, or a non-trivial copy
+        //   assignment operator cannot be a member of a union, nor can an
+        //   array of such objects.
+        if (CheckNontrivialField(FD))
+          Invalid = true;
+      } else if ((*Mem)->isImplicit()) {
+        // Any implicit members are fine.
+      } else if (isa<TagDecl>(*Mem) && (*Mem)->getDeclContext() != Record) {
+        // This is a type that showed up in an
+        // elaborated-type-specifier inside the anonymous struct or
+        // union, but which actually declares a type outside of the
+        // anonymous struct or union. It's okay.
+      } else if (RecordDecl *MemRecord = dyn_cast<RecordDecl>(*Mem)) {
+        if (!MemRecord->isAnonymousStructOrUnion() &&
+            MemRecord->getDeclName()) {
+          // Visual C++ allows type definition in anonymous struct or union.
+          if (getLangOpts().MicrosoftExt)
+            Diag(MemRecord->getLocation(), diag::ext_anonymous_record_with_type)
+              << (int)Record->isUnion();
+          else {
+            // This is a nested type declaration.
+            Diag(MemRecord->getLocation(), diag::err_anonymous_record_with_type)
+              << (int)Record->isUnion();
+            Invalid = true;
+          }
+        }
+      } else if (isa<AccessSpecDecl>(*Mem)) {
+        // Any access specifier is fine.
+      } else {
+        // We have something that isn't a non-static data
+        // member. Complain about it.
+        unsigned DK = diag::err_anonymous_record_bad_member;
+        if (isa<TypeDecl>(*Mem))
+          DK = diag::err_anonymous_record_with_type;
+        else if (isa<FunctionDecl>(*Mem))
+          DK = diag::err_anonymous_record_with_function;
+        else if (isa<VarDecl>(*Mem))
+          DK = diag::err_anonymous_record_with_static;
+        
+        // Visual C++ allows type definition in anonymous struct or union.
+        if (getLangOpts().MicrosoftExt &&
+            DK == diag::err_anonymous_record_with_type)
+          Diag((*Mem)->getLocation(), diag::ext_anonymous_record_with_type)
+            << (int)Record->isUnion();
+        else {
+          Diag((*Mem)->getLocation(), DK)
+              << (int)Record->isUnion();
+          Invalid = true;
+        }
+      }
+    }
+  }
+
+  if (!Record->isUnion() && !Owner->isRecord()) {
+    Diag(Record->getLocation(), diag::err_anonymous_struct_not_member)
+      << (int)getLangOpts().CPlusPlus;
+    Invalid = true;
+  }
+
+  // Mock up a declarator.
+  Declarator Dc(DS, Declarator::MemberContext);
+  TypeSourceInfo *TInfo = GetTypeForDeclarator(Dc, S);
+  assert(TInfo && "couldn't build declarator info for anonymous struct/union");
+
+  // Create a declaration for this anonymous struct/union.
+  NamedDecl *Anon = 0;
+  if (RecordDecl *OwningClass = dyn_cast<RecordDecl>(Owner)) {
+    Anon = FieldDecl::Create(Context, OwningClass,
+                             DS.getLocStart(),
+                             Record->getLocation(),
+                             /*IdentifierInfo=*/0,
+                             Context.getTypeDeclType(Record),
+                             TInfo,
+                             /*BitWidth=*/0, /*Mutable=*/false,
+                             /*HasInit=*/false);
+    Anon->setAccess(AS);
+    if (getLangOpts().CPlusPlus)
+      FieldCollector->Add(cast<FieldDecl>(Anon));
+  } else {
+    DeclSpec::SCS SCSpec = DS.getStorageClassSpec();
+    assert(SCSpec != DeclSpec::SCS_typedef &&
+           "Parser allowed 'typedef' as storage class VarDecl.");
+    VarDecl::StorageClass SC = StorageClassSpecToVarDeclStorageClass(SCSpec);
+    if (SCSpec == DeclSpec::SCS_mutable) {
+      // mutable can only appear on non-static class members, so it's always
+      // an error here
+      Diag(Record->getLocation(), diag::err_mutable_nonmember);
+      Invalid = true;
+      SC = SC_None;
+    }
+    SCSpec = DS.getStorageClassSpecAsWritten();
+    VarDecl::StorageClass SCAsWritten
+      = StorageClassSpecToVarDeclStorageClass(SCSpec);
+
+    Anon = VarDecl::Create(Context, Owner,
+                           DS.getLocStart(),
+                           Record->getLocation(), /*IdentifierInfo=*/0,
+                           Context.getTypeDeclType(Record),
+                           TInfo, SC, SCAsWritten);
+
+    // Default-initialize the implicit variable. This initialization will be
+    // trivial in almost all cases, except if a union member has an in-class
+    // initializer:
+    //   union { int n = 0; };
+    ActOnUninitializedDecl(Anon, /*TypeMayContainAuto=*/false);
+  }
+  Anon->setImplicit();
+
+  // Add the anonymous struct/union object to the current
+  // context. We'll be referencing this object when we refer to one of
+  // its members.
+  Owner->addDecl(Anon);
+  
+  // Inject the members of the anonymous struct/union into the owning
+  // context and into the identifier resolver chain for name lookup
+  // purposes.
+  SmallVector<NamedDecl*, 2> Chain;
+  Chain.push_back(Anon);
+
+  if (InjectAnonymousStructOrUnionMembers(*this, S, Owner, Record, AS,
+                                          Chain, false))
+    Invalid = true;
+
+  // Mark this as an anonymous struct/union type. Note that we do not
+  // do this until after we have already checked and injected the
+  // members of this anonymous struct/union type, because otherwise
+  // the members could be injected twice: once by DeclContext when it
+  // builds its lookup table, and once by
+  // InjectAnonymousStructOrUnionMembers.
+  Record->setAnonymousStructOrUnion(true);
+
+  if (Invalid)
+    Anon->setInvalidDecl();
+
+  return Anon;
+}
+
+/// BuildMicrosoftCAnonymousStruct - Handle the declaration of an
+/// Microsoft C anonymous structure.
+/// Ref: http://msdn.microsoft.com/en-us/library/z2cx9y4f.aspx
+/// Example:
+///
+/// struct A { int a; };
+/// struct B { struct A; int b; };
+///
+/// void foo() {
+///   B var;
+///   var.a = 3; 
+/// }
+///
+Decl *Sema::BuildMicrosoftCAnonymousStruct(Scope *S, DeclSpec &DS,
+                                           RecordDecl *Record) {
+  
+  // If there is no Record, get the record via the typedef.
+  if (!Record)
+    Record = DS.getRepAsType().get()->getAsStructureType()->getDecl();
+
+  // Mock up a declarator.
+  Declarator Dc(DS, Declarator::TypeNameContext);
+  TypeSourceInfo *TInfo = GetTypeForDeclarator(Dc, S);
+  assert(TInfo && "couldn't build declarator info for anonymous struct");
+
+  // Create a declaration for this anonymous struct.
+  NamedDecl* Anon = FieldDecl::Create(Context,
+                             cast<RecordDecl>(CurContext),
+                             DS.getLocStart(),
+                             DS.getLocStart(),
+                             /*IdentifierInfo=*/0,
+                             Context.getTypeDeclType(Record),
+                             TInfo,
+                             /*BitWidth=*/0, /*Mutable=*/false,
+                             /*HasInit=*/false);
+  Anon->setImplicit();
+
+  // Add the anonymous struct object to the current context.
+  CurContext->addDecl(Anon);
+
+  // Inject the members of the anonymous struct into the current
+  // context and into the identifier resolver chain for name lookup
+  // purposes.
+  SmallVector<NamedDecl*, 2> Chain;
+  Chain.push_back(Anon);
+
+  RecordDecl *RecordDef = Record->getDefinition();
+  if (!RecordDef || InjectAnonymousStructOrUnionMembers(*this, S, CurContext,
+                                                        RecordDef, AS_none,
+                                                        Chain, true))
+    Anon->setInvalidDecl();
+
+  return Anon;
+}
+
+/// GetNameForDeclarator - Determine the full declaration name for the
+/// given Declarator.
+DeclarationNameInfo Sema::GetNameForDeclarator(Declarator &D) {
+  return GetNameFromUnqualifiedId(D.getName());
+}
+
+/// \brief Retrieves the declaration name from a parsed unqualified-id.
+DeclarationNameInfo
+Sema::GetNameFromUnqualifiedId(const UnqualifiedId &Name) {
+  DeclarationNameInfo NameInfo;
+  NameInfo.setLoc(Name.StartLocation);
+
+  switch (Name.getKind()) {
+
+  case UnqualifiedId::IK_ImplicitSelfParam:
+  case UnqualifiedId::IK_Identifier:
+    NameInfo.setName(Name.Identifier);
+    NameInfo.setLoc(Name.StartLocation);
+    return NameInfo;
+
+  case UnqualifiedId::IK_OperatorFunctionId:
+    NameInfo.setName(Context.DeclarationNames.getCXXOperatorName(
+                                           Name.OperatorFunctionId.Operator));
+    NameInfo.setLoc(Name.StartLocation);
+    NameInfo.getInfo().CXXOperatorName.BeginOpNameLoc
+      = Name.OperatorFunctionId.SymbolLocations[0];
+    NameInfo.getInfo().CXXOperatorName.EndOpNameLoc
+      = Name.EndLocation.getRawEncoding();
+    return NameInfo;
+
+  case UnqualifiedId::IK_LiteralOperatorId:
+    NameInfo.setName(Context.DeclarationNames.getCXXLiteralOperatorName(
+                                                           Name.Identifier));
+    NameInfo.setLoc(Name.StartLocation);
+    NameInfo.setCXXLiteralOperatorNameLoc(Name.EndLocation);
+    return NameInfo;
+
+  case UnqualifiedId::IK_ConversionFunctionId: {
+    TypeSourceInfo *TInfo;
+    QualType Ty = GetTypeFromParser(Name.ConversionFunctionId, &TInfo);
+    if (Ty.isNull())
+      return DeclarationNameInfo();
+    NameInfo.setName(Context.DeclarationNames.getCXXConversionFunctionName(
+                                               Context.getCanonicalType(Ty)));
+    NameInfo.setLoc(Name.StartLocation);
+    NameInfo.setNamedTypeInfo(TInfo);
+    return NameInfo;
+  }
+
+  case UnqualifiedId::IK_ConstructorName: {
+    TypeSourceInfo *TInfo;
+    QualType Ty = GetTypeFromParser(Name.ConstructorName, &TInfo);
+    if (Ty.isNull())
+      return DeclarationNameInfo();
+    NameInfo.setName(Context.DeclarationNames.getCXXConstructorName(
+                                              Context.getCanonicalType(Ty)));
+    NameInfo.setLoc(Name.StartLocation);
+    NameInfo.setNamedTypeInfo(TInfo);
+    return NameInfo;
+  }
+
+  case UnqualifiedId::IK_ConstructorTemplateId: {
+    // In well-formed code, we can only have a constructor
+    // template-id that refers to the current context, so go there
+    // to find the actual type being constructed.
+    CXXRecordDecl *CurClass = dyn_cast<CXXRecordDecl>(CurContext);
+    if (!CurClass || CurClass->getIdentifier() != Name.TemplateId->Name)
+      return DeclarationNameInfo();
+
+    // Determine the type of the class being constructed.
+    QualType CurClassType = Context.getTypeDeclType(CurClass);
+
+    // FIXME: Check two things: that the template-id names the same type as
+    // CurClassType, and that the template-id does not occur when the name
+    // was qualified.
+
+    NameInfo.setName(Context.DeclarationNames.getCXXConstructorName(
+                                    Context.getCanonicalType(CurClassType)));
+    NameInfo.setLoc(Name.StartLocation);
+    // FIXME: should we retrieve TypeSourceInfo?
+    NameInfo.setNamedTypeInfo(0);
+    return NameInfo;
+  }
+
+  case UnqualifiedId::IK_DestructorName: {
+    TypeSourceInfo *TInfo;
+    QualType Ty = GetTypeFromParser(Name.DestructorName, &TInfo);
+    if (Ty.isNull())
+      return DeclarationNameInfo();
+    NameInfo.setName(Context.DeclarationNames.getCXXDestructorName(
+                                              Context.getCanonicalType(Ty)));
+    NameInfo.setLoc(Name.StartLocation);
+    NameInfo.setNamedTypeInfo(TInfo);
+    return NameInfo;
+  }
+
+  case UnqualifiedId::IK_TemplateId: {
+    TemplateName TName = Name.TemplateId->Template.get();
+    SourceLocation TNameLoc = Name.TemplateId->TemplateNameLoc;
+    return Context.getNameForTemplate(TName, TNameLoc);
+  }
+
+  } // switch (Name.getKind())
+
+  llvm_unreachable("Unknown name kind");
+}
+
+static QualType getCoreType(QualType Ty) {
+  do {
+    if (Ty->isPointerType() || Ty->isReferenceType())
+      Ty = Ty->getPointeeType();
+    else if (Ty->isArrayType())
+      Ty = Ty->castAsArrayTypeUnsafe()->getElementType();
+    else
+      return Ty.withoutLocalFastQualifiers();
+  } while (true);
+}
+
+/// hasSimilarParameters - Determine whether the C++ functions Declaration
+/// and Definition have "nearly" matching parameters. This heuristic is
+/// used to improve diagnostics in the case where an out-of-line function
+/// definition doesn't match any declaration within the class or namespace.
+/// Also sets Params to the list of indices to the parameters that differ
+/// between the declaration and the definition. If hasSimilarParameters
+/// returns true and Params is empty, then all of the parameters match.
+static bool hasSimilarParameters(ASTContext &Context,
+                                     FunctionDecl *Declaration,
+                                     FunctionDecl *Definition,
+                                     llvm::SmallVectorImpl<unsigned> &Params) {
+  Params.clear();
+  if (Declaration->param_size() != Definition->param_size())
+    return false;
+  for (unsigned Idx = 0; Idx < Declaration->param_size(); ++Idx) {
+    QualType DeclParamTy = Declaration->getParamDecl(Idx)->getType();
+    QualType DefParamTy = Definition->getParamDecl(Idx)->getType();
+
+    // The parameter types are identical
+    if (Context.hasSameType(DefParamTy, DeclParamTy))
+      continue;
+
+    QualType DeclParamBaseTy = getCoreType(DeclParamTy);
+    QualType DefParamBaseTy = getCoreType(DefParamTy);
+    const IdentifierInfo *DeclTyName = DeclParamBaseTy.getBaseTypeIdentifier();
+    const IdentifierInfo *DefTyName = DefParamBaseTy.getBaseTypeIdentifier();
+
+    if (Context.hasSameUnqualifiedType(DeclParamBaseTy, DefParamBaseTy) ||
+        (DeclTyName && DeclTyName == DefTyName))
+      Params.push_back(Idx);
+    else  // The two parameters aren't even close
+      return false;
+  }
+
+  return true;
+}
+
+/// NeedsRebuildingInCurrentInstantiation - Checks whether the given
+/// declarator needs to be rebuilt in the current instantiation.
+/// Any bits of declarator which appear before the name are valid for
+/// consideration here.  That's specifically the type in the decl spec
+/// and the base type in any member-pointer chunks.
+static bool RebuildDeclaratorInCurrentInstantiation(Sema &S, Declarator &D,
+                                                    DeclarationName Name) {
+  // The types we specifically need to rebuild are:
+  //   - typenames, typeofs, and decltypes
+  //   - types which will become injected class names
+  // Of course, we also need to rebuild any type referencing such a
+  // type.  It's safest to just say "dependent", but we call out a
+  // few cases here.
+
+  DeclSpec &DS = D.getMutableDeclSpec();
+  switch (DS.getTypeSpecType()) {
+  case DeclSpec::TST_typename:
+  case DeclSpec::TST_typeofType:
+  case DeclSpec::TST_decltype:
+  case DeclSpec::TST_underlyingType:
+  case DeclSpec::TST_atomic: {
+    // Grab the type from the parser.
+    TypeSourceInfo *TSI = 0;
+    QualType T = S.GetTypeFromParser(DS.getRepAsType(), &TSI);
+    if (T.isNull() || !T->isDependentType()) break;
+
+    // Make sure there's a type source info.  This isn't really much
+    // of a waste; most dependent types should have type source info
+    // attached already.
+    if (!TSI)
+      TSI = S.Context.getTrivialTypeSourceInfo(T, DS.getTypeSpecTypeLoc());
+
+    // Rebuild the type in the current instantiation.
+    TSI = S.RebuildTypeInCurrentInstantiation(TSI, D.getIdentifierLoc(), Name);
+    if (!TSI) return true;
+
+    // Store the new type back in the decl spec.
+    ParsedType LocType = S.CreateParsedType(TSI->getType(), TSI);
+    DS.UpdateTypeRep(LocType);
+    break;
+  }
+
+  case DeclSpec::TST_typeofExpr: {
+    Expr *E = DS.getRepAsExpr();
+    ExprResult Result = S.RebuildExprInCurrentInstantiation(E);
+    if (Result.isInvalid()) return true;
+    DS.UpdateExprRep(Result.get());
+    break;
+  }
+
+  default:
+    // Nothing to do for these decl specs.
+    break;
+  }
+
+  // It doesn't matter what order we do this in.
+  for (unsigned I = 0, E = D.getNumTypeObjects(); I != E; ++I) {
+    DeclaratorChunk &Chunk = D.getTypeObject(I);
+
+    // The only type information in the declarator which can come
+    // before the declaration name is the base type of a member
+    // pointer.
+    if (Chunk.Kind != DeclaratorChunk::MemberPointer)
+      continue;
+
+    // Rebuild the scope specifier in-place.
+    CXXScopeSpec &SS = Chunk.Mem.Scope();
+    if (S.RebuildNestedNameSpecifierInCurrentInstantiation(SS))
+      return true;
+  }
+
+  return false;
+}
+
+Decl *Sema::ActOnDeclarator(Scope *S, Declarator &D) {
+  D.setFunctionDefinitionKind(FDK_Declaration);
+  Decl *Dcl = HandleDeclarator(S, D, MultiTemplateParamsArg(*this));
+
+  if (OriginalLexicalContext && OriginalLexicalContext->isObjCContainer() &&
+      Dcl->getDeclContext()->isFileContext())
+    Dcl->setTopLevelDeclInObjCContainer();
+
+  return Dcl;
+}
+
+/// DiagnoseClassNameShadow - Implement C++ [class.mem]p13:
+///   If T is the name of a class, then each of the following shall have a 
+///   name different from T:
+///     - every static data member of class T;
+///     - every member function of class T
+///     - every member of class T that is itself a type;
+/// \returns true if the declaration name violates these rules.
+bool Sema::DiagnoseClassNameShadow(DeclContext *DC,
+                                   DeclarationNameInfo NameInfo) {
+  DeclarationName Name = NameInfo.getName();
+
+  if (CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(DC)) 
+    if (Record->getIdentifier() && Record->getDeclName() == Name) {
+      Diag(NameInfo.getLoc(), diag::err_member_name_of_class) << Name;
+      return true;
+    }
+
+  return false;
+}
+
+/// \brief Diagnose a declaration whose declarator-id has the given 
+/// nested-name-specifier.
+///
+/// \param SS The nested-name-specifier of the declarator-id.
+///
+/// \param DC The declaration context to which the nested-name-specifier 
+/// resolves.
+///
+/// \param Name The name of the entity being declared.
+///
+/// \param Loc The location of the name of the entity being declared.
+///
+/// \returns true if we cannot safely recover from this error, false otherwise.
+bool Sema::diagnoseQualifiedDeclaration(CXXScopeSpec &SS, DeclContext *DC,
+                                        DeclarationName Name,
+                                      SourceLocation Loc) {
+  DeclContext *Cur = CurContext;
+  while (isa<LinkageSpecDecl>(Cur))
+    Cur = Cur->getParent();
+  
+  // C++ [dcl.meaning]p1:
+  //   A declarator-id shall not be qualified except for the definition
+  //   of a member function (9.3) or static data member (9.4) outside of
+  //   its class, the definition or explicit instantiation of a function 
+  //   or variable member of a namespace outside of its namespace, or the
+  //   definition of an explicit specialization outside of its namespace,
+  //   or the declaration of a friend function that is a member of 
+  //   another class or namespace (11.3). [...]
+    
+  // The user provided a superfluous scope specifier that refers back to the
+  // class or namespaces in which the entity is already declared.
+  //
+  // class X {
+  //   void X::f();
+  // };
+  if (Cur->Equals(DC)) {
+    Diag(Loc, diag::warn_member_extra_qualification)
+      << Name << FixItHint::CreateRemoval(SS.getRange());
+    SS.clear();
+    return false;
+  } 
+
+  // Check whether the qualifying scope encloses the scope of the original
+  // declaration.
+  if (!Cur->Encloses(DC)) {
+    if (Cur->isRecord())
+      Diag(Loc, diag::err_member_qualification)
+        << Name << SS.getRange();
+    else if (isa<TranslationUnitDecl>(DC))
+      Diag(Loc, diag::err_invalid_declarator_global_scope)
+        << Name << SS.getRange();
+    else if (isa<FunctionDecl>(Cur))
+      Diag(Loc, diag::err_invalid_declarator_in_function) 
+        << Name << SS.getRange();
+    else
+      Diag(Loc, diag::err_invalid_declarator_scope)
+      << Name << cast<NamedDecl>(Cur) << cast<NamedDecl>(DC) << SS.getRange();
+    
+    return true;
+  }
+
+  if (Cur->isRecord()) {
+    // Cannot qualify members within a class.
+    Diag(Loc, diag::err_member_qualification)
+      << Name << SS.getRange();
+    SS.clear();
+    
+    // C++ constructors and destructors with incorrect scopes can break
+    // our AST invariants by having the wrong underlying types. If
+    // that's the case, then drop this declaration entirely.
+    if ((Name.getNameKind() == DeclarationName::CXXConstructorName ||
+         Name.getNameKind() == DeclarationName::CXXDestructorName) &&
+        !Context.hasSameType(Name.getCXXNameType(),
+                             Context.getTypeDeclType(cast<CXXRecordDecl>(Cur))))
+      return true;
+    
+    return false;
+  }
+  
+  // C++11 [dcl.meaning]p1:
+  //   [...] "The nested-name-specifier of the qualified declarator-id shall
+  //   not begin with a decltype-specifer"
+  NestedNameSpecifierLoc SpecLoc(SS.getScopeRep(), SS.location_data());
+  while (SpecLoc.getPrefix())
+    SpecLoc = SpecLoc.getPrefix();
+  if (dyn_cast_or_null<DecltypeType>(
+        SpecLoc.getNestedNameSpecifier()->getAsType()))
+    Diag(Loc, diag::err_decltype_in_declarator)
+      << SpecLoc.getTypeLoc().getSourceRange();
+
+  return false;
+}
+
+Decl *Sema::HandleDeclarator(Scope *S, Declarator &D,
+                             MultiTemplateParamsArg TemplateParamLists) {
+  // TODO: consider using NameInfo for diagnostic.
+  DeclarationNameInfo NameInfo = GetNameForDeclarator(D);
+  DeclarationName Name = NameInfo.getName();
+
+  // All of these full declarators require an identifier.  If it doesn't have
+  // one, the ParsedFreeStandingDeclSpec action should be used.
+  if (!Name) {
+    if (!D.isInvalidType())  // Reject this if we think it is valid.
+      Diag(D.getDeclSpec().getLocStart(),
+           diag::err_declarator_need_ident)
+        << D.getDeclSpec().getSourceRange() << D.getSourceRange();
+    return 0;
+  } else if (DiagnoseUnexpandedParameterPack(NameInfo, UPPC_DeclarationType))
+    return 0;
+
+  // The scope passed in may not be a decl scope.  Zip up the scope tree until
+  // we find one that is.
+  while ((S->getFlags() & Scope::DeclScope) == 0 ||
+         (S->getFlags() & Scope::TemplateParamScope) != 0)
+    S = S->getParent();
+
+  DeclContext *DC = CurContext;
+  if (D.getCXXScopeSpec().isInvalid())
+    D.setInvalidType();
+  else if (D.getCXXScopeSpec().isSet()) {
+    if (DiagnoseUnexpandedParameterPack(D.getCXXScopeSpec(), 
+                                        UPPC_DeclarationQualifier))
+      return 0;
+
+    bool EnteringContext = !D.getDeclSpec().isFriendSpecified();
+    DC = computeDeclContext(D.getCXXScopeSpec(), EnteringContext);
+    if (!DC) {
+      // If we could not compute the declaration context, it's because the
+      // declaration context is dependent but does not refer to a class,
+      // class template, or class template partial specialization. Complain
+      // and return early, to avoid the coming semantic disaster.
+      Diag(D.getIdentifierLoc(),
+           diag::err_template_qualified_declarator_no_match)
+        << (NestedNameSpecifier*)D.getCXXScopeSpec().getScopeRep()
+        << D.getCXXScopeSpec().getRange();
+      return 0;
+    }
+    bool IsDependentContext = DC->isDependentContext();
+
+    if (!IsDependentContext && 
+        RequireCompleteDeclContext(D.getCXXScopeSpec(), DC))
+      return 0;
+
+    if (isa<CXXRecordDecl>(DC) && !cast<CXXRecordDecl>(DC)->hasDefinition()) {
+      Diag(D.getIdentifierLoc(),
+           diag::err_member_def_undefined_record)
+        << Name << DC << D.getCXXScopeSpec().getRange();
+      D.setInvalidType();
+    } else if (!D.getDeclSpec().isFriendSpecified()) {
+      if (diagnoseQualifiedDeclaration(D.getCXXScopeSpec(), DC,
+                                      Name, D.getIdentifierLoc())) {
+        if (DC->isRecord())
+          return 0;
+        
+        D.setInvalidType();
+      }
+    }
+
+    // Check whether we need to rebuild the type of the given
+    // declaration in the current instantiation.
+    if (EnteringContext && IsDependentContext &&
+        TemplateParamLists.size() != 0) {
+      ContextRAII SavedContext(*this, DC);
+      if (RebuildDeclaratorInCurrentInstantiation(*this, D, Name))
+        D.setInvalidType();
+    }
+  }
+
+  if (DiagnoseClassNameShadow(DC, NameInfo))
+    // If this is a typedef, we'll end up spewing multiple diagnostics.
+    // Just return early; it's safer.
+    if (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_typedef)
+      return 0;
+  
+  NamedDecl *New;
+
+  TypeSourceInfo *TInfo = GetTypeForDeclarator(D, S);
+  QualType R = TInfo->getType();
+
+  if (DiagnoseUnexpandedParameterPack(D.getIdentifierLoc(), TInfo,
+                                      UPPC_DeclarationType))
+    D.setInvalidType();
+
+  LookupResult Previous(*this, NameInfo, LookupOrdinaryName,
+                        ForRedeclaration);
+
+  // See if this is a redefinition of a variable in the same scope.
+  if (!D.getCXXScopeSpec().isSet()) {
+    bool IsLinkageLookup = false;
+
+    // If the declaration we're planning to build will be a function
+    // or object with linkage, then look for another declaration with
+    // linkage (C99 6.2.2p4-5 and C++ [basic.link]p6).
+    if (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_typedef)
+      /* Do nothing*/;
+    else if (R->isFunctionType()) {
+      if (CurContext->isFunctionOrMethod() ||
+          D.getDeclSpec().getStorageClassSpec() != DeclSpec::SCS_static)
+        IsLinkageLookup = true;
+    } else if (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_extern)
+      IsLinkageLookup = true;
+    else if (CurContext->getRedeclContext()->isTranslationUnit() &&
+             D.getDeclSpec().getStorageClassSpec() != DeclSpec::SCS_static)
+      IsLinkageLookup = true;
+
+    if (IsLinkageLookup)
+      Previous.clear(LookupRedeclarationWithLinkage);
+
+    LookupName(Previous, S, /* CreateBuiltins = */ IsLinkageLookup);
+  } else { // Something like "int foo::x;"
+    LookupQualifiedName(Previous, DC);
+
+    // C++ [dcl.meaning]p1:
+    //   When the declarator-id is qualified, the declaration shall refer to a 
+    //  previously declared member of the class or namespace to which the 
+    //  qualifier refers (or, in the case of a namespace, of an element of the
+    //  inline namespace set of that namespace (7.3.1)) or to a specialization
+    //  thereof; [...] 
+    //
+    // Note that we already checked the context above, and that we do not have
+    // enough information to make sure that Previous contains the declaration
+    // we want to match. For example, given:
+    //
+    //   class X {
+    //     void f();
+    //     void f(float);
+    //   };
+    //
+    //   void X::f(int) { } // ill-formed
+    //
+    // In this case, Previous will point to the overload set
+    // containing the two f's declared in X, but neither of them
+    // matches.
+    
+    // C++ [dcl.meaning]p1:
+    //   [...] the member shall not merely have been introduced by a 
+    //   using-declaration in the scope of the class or namespace nominated by 
+    //   the nested-name-specifier of the declarator-id.
+    RemoveUsingDecls(Previous);
+  }
+
+  if (Previous.isSingleResult() &&
+      Previous.getFoundDecl()->isTemplateParameter()) {
+    // Maybe we will complain about the shadowed template parameter.
+    if (!D.isInvalidType())
+      DiagnoseTemplateParameterShadow(D.getIdentifierLoc(),
+                                      Previous.getFoundDecl());
+
+    // Just pretend that we didn't see the previous declaration.
+    Previous.clear();
+  }
+
+  // In C++, the previous declaration we find might be a tag type
+  // (class or enum). In this case, the new declaration will hide the
+  // tag type. Note that this does does not apply if we're declaring a
+  // typedef (C++ [dcl.typedef]p4).
+  if (Previous.isSingleTagDecl() &&
+      D.getDeclSpec().getStorageClassSpec() != DeclSpec::SCS_typedef)
+    Previous.clear();
+
+  bool AddToScope = true;
+  if (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_typedef) {
+    if (TemplateParamLists.size()) {
+      Diag(D.getIdentifierLoc(), diag::err_template_typedef);
+      return 0;
+    }
+
+    New = ActOnTypedefDeclarator(S, D, DC, TInfo, Previous);
+  } else if (R->isFunctionType()) {
+    New = ActOnFunctionDeclarator(S, D, DC, TInfo, Previous,
+                                  move(TemplateParamLists),
+                                  AddToScope);
+  } else {
+    New = ActOnVariableDeclarator(S, D, DC, TInfo, Previous,
+                                  move(TemplateParamLists));
+  }
+
+  if (New == 0)
+    return 0;
+
+  // If this has an identifier and is not an invalid redeclaration or 
+  // function template specialization, add it to the scope stack.
+  if (New->getDeclName() && AddToScope &&
+       !(D.isRedeclaration() && New->isInvalidDecl()))
+    PushOnScopeChains(New, S);
+
+  return New;
+}
+
+/// TryToFixInvalidVariablyModifiedType - Helper method to turn variable array
+/// types into constant array types in certain situations which would otherwise
+/// be errors (for GCC compatibility).
+static QualType TryToFixInvalidVariablyModifiedType(QualType T,
+                                                    ASTContext &Context,
+                                                    bool &SizeIsNegative,
+                                                    llvm::APSInt &Oversized) {
+  // This method tries to turn a variable array into a constant
+  // array even when the size isn't an ICE.  This is necessary
+  // for compatibility with code that depends on gcc's buggy
+  // constant expression folding, like struct {char x[(int)(char*)2];}
+  SizeIsNegative = false;
+  Oversized = 0;
+  
+  if (T->isDependentType())
+    return QualType();
+  
+  QualifierCollector Qs;
+  const Type *Ty = Qs.strip(T);
+
+  if (const PointerType* PTy = dyn_cast<PointerType>(Ty)) {
+    QualType Pointee = PTy->getPointeeType();
+    QualType FixedType =
+        TryToFixInvalidVariablyModifiedType(Pointee, Context, SizeIsNegative,
+                                            Oversized);
+    if (FixedType.isNull()) return FixedType;
+    FixedType = Context.getPointerType(FixedType);
+    return Qs.apply(Context, FixedType);
+  }
+  if (const ParenType* PTy = dyn_cast<ParenType>(Ty)) {
+    QualType Inner = PTy->getInnerType();
+    QualType FixedType =
+        TryToFixInvalidVariablyModifiedType(Inner, Context, SizeIsNegative,
+                                            Oversized);
+    if (FixedType.isNull()) return FixedType;
+    FixedType = Context.getParenType(FixedType);
+    return Qs.apply(Context, FixedType);
+  }
+
+  const VariableArrayType* VLATy = dyn_cast<VariableArrayType>(T);
+  if (!VLATy)
+    return QualType();
+  // FIXME: We should probably handle this case
+  if (VLATy->getElementType()->isVariablyModifiedType())
+    return QualType();
+
+  llvm::APSInt Res;
+  if (!VLATy->getSizeExpr() ||
+      !VLATy->getSizeExpr()->EvaluateAsInt(Res, Context))
+    return QualType();
+
+  // Check whether the array size is negative.
+  if (Res.isSigned() && Res.isNegative()) {
+    SizeIsNegative = true;
+    return QualType();
+  }
+
+  // Check whether the array is too large to be addressed.
+  unsigned ActiveSizeBits
+    = ConstantArrayType::getNumAddressingBits(Context, VLATy->getElementType(),
+                                              Res);
+  if (ActiveSizeBits > ConstantArrayType::getMaxSizeBits(Context)) {
+    Oversized = Res;
+    return QualType();
+  }
+  
+  return Context.getConstantArrayType(VLATy->getElementType(),
+                                      Res, ArrayType::Normal, 0);
+}
+
+/// \brief Register the given locally-scoped external C declaration so
+/// that it can be found later for redeclarations
+void
+Sema::RegisterLocallyScopedExternCDecl(NamedDecl *ND,
+                                       const LookupResult &Previous,
+                                       Scope *S) {
+  assert(ND->getLexicalDeclContext()->isFunctionOrMethod() &&
+         "Decl is not a locally-scoped decl!");
+  // Note that we have a locally-scoped external with this name.
+  LocallyScopedExternalDecls[ND->getDeclName()] = ND;
+
+  if (!Previous.isSingleResult())
+    return;
+
+  NamedDecl *PrevDecl = Previous.getFoundDecl();
+
+  // If there was a previous declaration of this variable, it may be
+  // in our identifier chain. Update the identifier chain with the new
+  // declaration.
+  if (S && IdResolver.ReplaceDecl(PrevDecl, ND)) {
+    // The previous declaration was found on the identifer resolver
+    // chain, so remove it from its scope.
+
+    if (S->isDeclScope(PrevDecl)) {
+      // Special case for redeclarations in the SAME scope.
+      // Because this declaration is going to be added to the identifier chain
+      // later, we should temporarily take it OFF the chain.
+      IdResolver.RemoveDecl(ND);
+
+    } else {
+      // Find the scope for the original declaration.
+      while (S && !S->isDeclScope(PrevDecl))
+        S = S->getParent();
+    }
+
+    if (S)
+      S->RemoveDecl(PrevDecl);
+  }
+}
+
+llvm::DenseMap<DeclarationName, NamedDecl *>::iterator
+Sema::findLocallyScopedExternalDecl(DeclarationName Name) {
+  if (ExternalSource) {
+    // Load locally-scoped external decls from the external source.
+    SmallVector<NamedDecl *, 4> Decls;
+    ExternalSource->ReadLocallyScopedExternalDecls(Decls);
+    for (unsigned I = 0, N = Decls.size(); I != N; ++I) {
+      llvm::DenseMap<DeclarationName, NamedDecl *>::iterator Pos
+        = LocallyScopedExternalDecls.find(Decls[I]->getDeclName());
+      if (Pos == LocallyScopedExternalDecls.end())
+        LocallyScopedExternalDecls[Decls[I]->getDeclName()] = Decls[I];
+    }
+  }
+  
+  return LocallyScopedExternalDecls.find(Name);
+}
+
+/// \brief Diagnose function specifiers on a declaration of an identifier that
+/// does not identify a function.
+void Sema::DiagnoseFunctionSpecifiers(Declarator& D) {
+  // FIXME: We should probably indicate the identifier in question to avoid
+  // confusion for constructs like "inline int a(), b;"
+  if (D.getDeclSpec().isInlineSpecified())
+    Diag(D.getDeclSpec().getInlineSpecLoc(),
+         diag::err_inline_non_function);
+
+  if (D.getDeclSpec().isVirtualSpecified())
+    Diag(D.getDeclSpec().getVirtualSpecLoc(),
+         diag::err_virtual_non_function);
+
+  if (D.getDeclSpec().isExplicitSpecified())
+    Diag(D.getDeclSpec().getExplicitSpecLoc(),
+         diag::err_explicit_non_function);
+}
+
+NamedDecl*
+Sema::ActOnTypedefDeclarator(Scope* S, Declarator& D, DeclContext* DC,
+                             TypeSourceInfo *TInfo, LookupResult &Previous) {
+  // Typedef declarators cannot be qualified (C++ [dcl.meaning]p1).
+  if (D.getCXXScopeSpec().isSet()) {
+    Diag(D.getIdentifierLoc(), diag::err_qualified_typedef_declarator)
+      << D.getCXXScopeSpec().getRange();
+    D.setInvalidType();
+    // Pretend we didn't see the scope specifier.
+    DC = CurContext;
+    Previous.clear();
+  }
+
+  if (getLangOpts().CPlusPlus) {
+    // Check that there are no default arguments (C++ only).
+    CheckExtraCXXDefaultArguments(D);
+  }
+
+  DiagnoseFunctionSpecifiers(D);
+
+  if (D.getDeclSpec().isThreadSpecified())
+    Diag(D.getDeclSpec().getThreadSpecLoc(), diag::err_invalid_thread);
+  if (D.getDeclSpec().isConstexprSpecified())
+    Diag(D.getDeclSpec().getConstexprSpecLoc(), diag::err_invalid_constexpr)
+      << 1;
+
+  if (D.getName().Kind != UnqualifiedId::IK_Identifier) {
+    Diag(D.getName().StartLocation, diag::err_typedef_not_identifier)
+      << D.getName().getSourceRange();
+    return 0;
+  }
+
+  TypedefDecl *NewTD = ParseTypedefDecl(S, D, TInfo->getType(), TInfo);
+  if (!NewTD) return 0;
+
+  // Handle attributes prior to checking for duplicates in MergeVarDecl
+  ProcessDeclAttributes(S, NewTD, D);
+
+  CheckTypedefForVariablyModifiedType(S, NewTD);
+
+  bool Redeclaration = D.isRedeclaration();
+  NamedDecl *ND = ActOnTypedefNameDecl(S, DC, NewTD, Previous, Redeclaration);
+  D.setRedeclaration(Redeclaration);
+  return ND;
+}
+
+void
+Sema::CheckTypedefForVariablyModifiedType(Scope *S, TypedefNameDecl *NewTD) {
+  // C99 6.7.7p2: If a typedef name specifies a variably modified type
+  // then it shall have block scope.
+  // Note that variably modified types must be fixed before merging the decl so
+  // that redeclarations will match.
+  QualType T = NewTD->getUnderlyingType();
+  if (T->isVariablyModifiedType()) {
+    getCurFunction()->setHasBranchProtectedScope();
+
+    if (S->getFnParent() == 0) {
+      bool SizeIsNegative;
+      llvm::APSInt Oversized;
+      QualType FixedTy =
+          TryToFixInvalidVariablyModifiedType(T, Context, SizeIsNegative,
+                                              Oversized);
+      if (!FixedTy.isNull()) {
+        Diag(NewTD->getLocation(), diag::warn_illegal_constant_array_size);
+        NewTD->setTypeSourceInfo(Context.getTrivialTypeSourceInfo(FixedTy));
+      } else {
+        if (SizeIsNegative)
+          Diag(NewTD->getLocation(), diag::err_typecheck_negative_array_size);
+        else if (T->isVariableArrayType())
+          Diag(NewTD->getLocation(), diag::err_vla_decl_in_file_scope);
+        else if (Oversized.getBoolValue())
+          Diag(NewTD->getLocation(), diag::err_array_too_large) 
+            << Oversized.toString(10);
+        else
+          Diag(NewTD->getLocation(), diag::err_vm_decl_in_file_scope);
+        NewTD->setInvalidDecl();
+      }
+    }
+  }
+}
+
+
+/// ActOnTypedefNameDecl - Perform semantic checking for a declaration which
+/// declares a typedef-name, either using the 'typedef' type specifier or via
+/// a C++0x [dcl.typedef]p2 alias-declaration: 'using T = A;'.
+NamedDecl*
+Sema::ActOnTypedefNameDecl(Scope *S, DeclContext *DC, TypedefNameDecl *NewTD,
+                           LookupResult &Previous, bool &Redeclaration) {
+  // Merge the decl with the existing one if appropriate. If the decl is
+  // in an outer scope, it isn't the same thing.
+  FilterLookupForScope(Previous, DC, S, /*ConsiderLinkage*/ false,
+                       /*ExplicitInstantiationOrSpecialization=*/false);
+  if (!Previous.empty()) {
+    Redeclaration = true;
+    MergeTypedefNameDecl(NewTD, Previous);
+  }
+
+  // If this is the C FILE type, notify the AST context.
+  if (IdentifierInfo *II = NewTD->getIdentifier())
+    if (!NewTD->isInvalidDecl() &&
+        NewTD->getDeclContext()->getRedeclContext()->isTranslationUnit()) {
+      if (II->isStr("FILE"))
+        Context.setFILEDecl(NewTD);
+      else if (II->isStr("jmp_buf"))
+        Context.setjmp_bufDecl(NewTD);
+      else if (II->isStr("sigjmp_buf"))
+        Context.setsigjmp_bufDecl(NewTD);
+      else if (II->isStr("ucontext_t"))
+        Context.setucontext_tDecl(NewTD);
+      else if (II->isStr("__builtin_va_list"))
+        Context.setBuiltinVaListType(Context.getTypedefType(NewTD));
+    }
+
+  return NewTD;
+}
+
+/// \brief Determines whether the given declaration is an out-of-scope
+/// previous declaration.
+///
+/// This routine should be invoked when name lookup has found a
+/// previous declaration (PrevDecl) that is not in the scope where a
+/// new declaration by the same name is being introduced. If the new
+/// declaration occurs in a local scope, previous declarations with
+/// linkage may still be considered previous declarations (C99
+/// 6.2.2p4-5, C++ [basic.link]p6).
+///
+/// \param PrevDecl the previous declaration found by name
+/// lookup
+///
+/// \param DC the context in which the new declaration is being
+/// declared.
+///
+/// \returns true if PrevDecl is an out-of-scope previous declaration
+/// for a new delcaration with the same name.
+static bool
+isOutOfScopePreviousDeclaration(NamedDecl *PrevDecl, DeclContext *DC,
+                                ASTContext &Context) {
+  if (!PrevDecl)
+    return false;
+
+  if (!PrevDecl->hasLinkage())
+    return false;
+
+  if (Context.getLangOpts().CPlusPlus) {
+    // C++ [basic.link]p6:
+    //   If there is a visible declaration of an entity with linkage
+    //   having the same name and type, ignoring entities declared
+    //   outside the innermost enclosing namespace scope, the block
+    //   scope declaration declares that same entity and receives the
+    //   linkage of the previous declaration.
+    DeclContext *OuterContext = DC->getRedeclContext();
+    if (!OuterContext->isFunctionOrMethod())
+      // This rule only applies to block-scope declarations.
+      return false;
+    
+    DeclContext *PrevOuterContext = PrevDecl->getDeclContext();
+    if (PrevOuterContext->isRecord())
+      // We found a member function: ignore it.
+      return false;
+    
+    // Find the innermost enclosing namespace for the new and
+    // previous declarations.
+    OuterContext = OuterContext->getEnclosingNamespaceContext();
+    PrevOuterContext = PrevOuterContext->getEnclosingNamespaceContext();
+
+    // The previous declaration is in a different namespace, so it
+    // isn't the same function.
+    if (!OuterContext->Equals(PrevOuterContext))
+      return false;
+  }
+
+  return true;
+}
+
+static void SetNestedNameSpecifier(DeclaratorDecl *DD, Declarator &D) {
+  CXXScopeSpec &SS = D.getCXXScopeSpec();
+  if (!SS.isSet()) return;
+  DD->setQualifierInfo(SS.getWithLocInContext(DD->getASTContext()));
+}
+
+bool Sema::inferObjCARCLifetime(ValueDecl *decl) {
+  QualType type = decl->getType();
+  Qualifiers::ObjCLifetime lifetime = type.getObjCLifetime();
+  if (lifetime == Qualifiers::OCL_Autoreleasing) {
+    // Various kinds of declaration aren't allowed to be __autoreleasing.
+    unsigned kind = -1U;
+    if (VarDecl *var = dyn_cast<VarDecl>(decl)) {
+      if (var->hasAttr<BlocksAttr>())
+        kind = 0; // __block
+      else if (!var->hasLocalStorage())
+        kind = 1; // global
+    } else if (isa<ObjCIvarDecl>(decl)) {
+      kind = 3; // ivar
+    } else if (isa<FieldDecl>(decl)) {
+      kind = 2; // field
+    }
+
+    if (kind != -1U) {
+      Diag(decl->getLocation(), diag::err_arc_autoreleasing_var)
+        << kind;
+    }
+  } else if (lifetime == Qualifiers::OCL_None) {
+    // Try to infer lifetime.
+    if (!type->isObjCLifetimeType())
+      return false;
+
+    lifetime = type->getObjCARCImplicitLifetime();
+    type = Context.getLifetimeQualifiedType(type, lifetime);
+    decl->setType(type);
+  }
+  
+  if (VarDecl *var = dyn_cast<VarDecl>(decl)) {
+    // Thread-local variables cannot have lifetime.
+    if (lifetime && lifetime != Qualifiers::OCL_ExplicitNone &&
+        var->isThreadSpecified()) {
+      Diag(var->getLocation(), diag::err_arc_thread_ownership)
+        << var->getType();
+      return true;
+    }
+  }
+  
+  return false;
+}
+
+NamedDecl*
+Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC,
+                              TypeSourceInfo *TInfo, LookupResult &Previous,
+                              MultiTemplateParamsArg TemplateParamLists) {
+  QualType R = TInfo->getType();
+  DeclarationName Name = GetNameForDeclarator(D).getName();
+
+  // Check that there are no default arguments (C++ only).
+  if (getLangOpts().CPlusPlus)
+    CheckExtraCXXDefaultArguments(D);
+
+  DeclSpec::SCS SCSpec = D.getDeclSpec().getStorageClassSpec();
+  assert(SCSpec != DeclSpec::SCS_typedef &&
+         "Parser allowed 'typedef' as storage class VarDecl.");
+  VarDecl::StorageClass SC = StorageClassSpecToVarDeclStorageClass(SCSpec);
+  if (SCSpec == DeclSpec::SCS_mutable) {
+    // mutable can only appear on non-static class members, so it's always
+    // an error here
+    Diag(D.getIdentifierLoc(), diag::err_mutable_nonmember);
+    D.setInvalidType();
+    SC = SC_None;
+  }
+  SCSpec = D.getDeclSpec().getStorageClassSpecAsWritten();
+  VarDecl::StorageClass SCAsWritten
+    = StorageClassSpecToVarDeclStorageClass(SCSpec);
+
+  IdentifierInfo *II = Name.getAsIdentifierInfo();
+  if (!II) {
+    Diag(D.getIdentifierLoc(), diag::err_bad_variable_name)
+      << Name;
+    return 0;
+  }
+
+  DiagnoseFunctionSpecifiers(D);
+
+  if (!DC->isRecord() && S->getFnParent() == 0) {
+    // C99 6.9p2: The storage-class specifiers auto and register shall not
+    // appear in the declaration specifiers in an external declaration.
+    if (SC == SC_Auto || SC == SC_Register) {
+
+      // If this is a register variable with an asm label specified, then this
+      // is a GNU extension.
+      if (SC == SC_Register && D.getAsmLabel())
+        Diag(D.getIdentifierLoc(), diag::err_unsupported_global_register);
+      else
+        Diag(D.getIdentifierLoc(), diag::err_typecheck_sclass_fscope);
+      D.setInvalidType();
+    }
+  }
+  
+  if (getLangOpts().OpenCL) {
+    // Set up the special work-group-local storage class for variables in the
+    // OpenCL __local address space.
+    if (R.getAddressSpace() == LangAS::opencl_local)
+      SC = SC_OpenCLWorkGroupLocal;
+  }
+
+  bool isExplicitSpecialization = false;
+  VarDecl *NewVD;
+  if (!getLangOpts().CPlusPlus) {
+    NewVD = VarDecl::Create(Context, DC, D.getLocStart(),
+                            D.getIdentifierLoc(), II,
+                            R, TInfo, SC, SCAsWritten);
+  
+    if (D.isInvalidType())
+      NewVD->setInvalidDecl();
+  } else {
+    if (DC->isRecord() && !CurContext->isRecord()) {
+      // This is an out-of-line definition of a static data member.
+      if (SC == SC_Static) {
+        Diag(D.getDeclSpec().getStorageClassSpecLoc(),
+             diag::err_static_out_of_line)
+          << FixItHint::CreateRemoval(D.getDeclSpec().getStorageClassSpecLoc());
+      } else if (SC == SC_None)
+        SC = SC_Static;
+    }
+    if (SC == SC_Static && CurContext->isRecord()) {
+      if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(DC)) {
+        if (RD->isLocalClass())
+          Diag(D.getIdentifierLoc(),
+               diag::err_static_data_member_not_allowed_in_local_class)
+            << Name << RD->getDeclName();
+
+        // C++98 [class.union]p1: If a union contains a static data member,
+        // the program is ill-formed. C++11 drops this restriction.
+        if (RD->isUnion())
+          Diag(D.getIdentifierLoc(),
+               getLangOpts().CPlusPlus0x
+                 ? diag::warn_cxx98_compat_static_data_member_in_union
+                 : diag::ext_static_data_member_in_union) << Name;
+        // We conservatively disallow static data members in anonymous structs.
+        else if (!RD->getDeclName())
+          Diag(D.getIdentifierLoc(),
+               diag::err_static_data_member_not_allowed_in_anon_struct)
+            << Name << RD->isUnion();
+      }
+    }
+
+    // Match up the template parameter lists with the scope specifier, then
+    // determine whether we have a template or a template specialization.
+    isExplicitSpecialization = false;
+    bool Invalid = false;
+    if (TemplateParameterList *TemplateParams
+        = MatchTemplateParametersToScopeSpecifier(
+                                  D.getDeclSpec().getLocStart(),
+                                                  D.getIdentifierLoc(),
+                                                  D.getCXXScopeSpec(),
+                                                  TemplateParamLists.get(),
+                                                  TemplateParamLists.size(),
+                                                  /*never a friend*/ false,
+                                                  isExplicitSpecialization,
+                                                  Invalid)) {
+      if (TemplateParams->size() > 0) {
+        // There is no such thing as a variable template.
+        Diag(D.getIdentifierLoc(), diag::err_template_variable)
+          << II
+          << SourceRange(TemplateParams->getTemplateLoc(),
+                         TemplateParams->getRAngleLoc());
+        return 0;
+      } else {
+        // There is an extraneous 'template<>' for this variable. Complain
+        // about it, but allow the declaration of the variable.
+        Diag(TemplateParams->getTemplateLoc(),
+             diag::err_template_variable_noparams)
+          << II
+          << SourceRange(TemplateParams->getTemplateLoc(),
+                         TemplateParams->getRAngleLoc());
+      }
+    }
+
+    NewVD = VarDecl::Create(Context, DC, D.getLocStart(),
+                            D.getIdentifierLoc(), II,
+                            R, TInfo, SC, SCAsWritten);
+
+    // If this decl has an auto type in need of deduction, make a note of the
+    // Decl so we can diagnose uses of it in its own initializer.
+    if (D.getDeclSpec().getTypeSpecType() == DeclSpec::TST_auto &&
+        R->getContainedAutoType())
+      ParsingInitForAutoVars.insert(NewVD);
+
+    if (D.isInvalidType() || Invalid)
+      NewVD->setInvalidDecl();
+
+    SetNestedNameSpecifier(NewVD, D);
+
+    if (TemplateParamLists.size() > 0 && D.getCXXScopeSpec().isSet()) {
+      NewVD->setTemplateParameterListsInfo(Context,
+                                           TemplateParamLists.size(),
+                                           TemplateParamLists.release());
+    }
+
+    if (D.getDeclSpec().isConstexprSpecified())
+      NewVD->setConstexpr(true);
+  }
+
+  // Set the lexical context. If the declarator has a C++ scope specifier, the
+  // lexical context will be different from the semantic context.
+  NewVD->setLexicalDeclContext(CurContext);
+
+  if (D.getDeclSpec().isThreadSpecified()) {
+    if (NewVD->hasLocalStorage())
+      Diag(D.getDeclSpec().getThreadSpecLoc(), diag::err_thread_non_global);
+    else if (!Context.getTargetInfo().isTLSSupported())
+      Diag(D.getDeclSpec().getThreadSpecLoc(), diag::err_thread_unsupported);
+    else
+      NewVD->setThreadSpecified(true);
+  }
+
+  if (D.getDeclSpec().isModulePrivateSpecified()) {
+    if (isExplicitSpecialization)
+      Diag(NewVD->getLocation(), diag::err_module_private_specialization)
+        << 2
+        << FixItHint::CreateRemoval(D.getDeclSpec().getModulePrivateSpecLoc());
+    else if (NewVD->hasLocalStorage())
+      Diag(NewVD->getLocation(), diag::err_module_private_local)
+        << 0 << NewVD->getDeclName()
+        << SourceRange(D.getDeclSpec().getModulePrivateSpecLoc())
+        << FixItHint::CreateRemoval(D.getDeclSpec().getModulePrivateSpecLoc());
+    else
+      NewVD->setModulePrivate();
+  }
+
+  // Handle attributes prior to checking for duplicates in MergeVarDecl
+  ProcessDeclAttributes(S, NewVD, D);
+
+  // In auto-retain/release, infer strong retension for variables of
+  // retainable type.
+  if (getLangOpts().ObjCAutoRefCount && inferObjCARCLifetime(NewVD))
+    NewVD->setInvalidDecl();
+
+  // Handle GNU asm-label extension (encoded as an attribute).
+  if (Expr *E = (Expr*)D.getAsmLabel()) {
+    // The parser guarantees this is a string.
+    StringLiteral *SE = cast<StringLiteral>(E);
+    StringRef Label = SE->getString();
+    if (S->getFnParent() != 0) {
+      switch (SC) {
+      case SC_None:
+      case SC_Auto:
+        Diag(E->getExprLoc(), diag::warn_asm_label_on_auto_decl) << Label;
+        break;
+      case SC_Register:
+        if (!Context.getTargetInfo().isValidGCCRegisterName(Label))
+          Diag(E->getExprLoc(), diag::err_asm_unknown_register_name) << Label;
+        break;
+      case SC_Static:
+      case SC_Extern:
+      case SC_PrivateExtern:
+      case SC_OpenCLWorkGroupLocal:
+        break;
+      }
+    }
+
+    NewVD->addAttr(::new (Context) AsmLabelAttr(SE->getStrTokenLoc(0),
+                                                Context, Label));
+  } else if (!ExtnameUndeclaredIdentifiers.empty()) {
+    llvm::DenseMap<IdentifierInfo*,AsmLabelAttr*>::iterator I =
+      ExtnameUndeclaredIdentifiers.find(NewVD->getIdentifier());
+    if (I != ExtnameUndeclaredIdentifiers.end()) {
+      NewVD->addAttr(I->second);
+      ExtnameUndeclaredIdentifiers.erase(I);
+    }
+  }
+
+  // Diagnose shadowed variables before filtering for scope.
+  if (!D.getCXXScopeSpec().isSet())
+    CheckShadow(S, NewVD, Previous);
+
+  // Don't consider existing declarations that are in a different
+  // scope and are out-of-semantic-context declarations (if the new
+  // declaration has linkage).
+  FilterLookupForScope(Previous, DC, S, NewVD->hasLinkage(),
+                       isExplicitSpecialization);
+  
+  if (!getLangOpts().CPlusPlus) {
+    D.setRedeclaration(CheckVariableDeclaration(NewVD, Previous));
+  } else {
+    // Merge the decl with the existing one if appropriate.
+    if (!Previous.empty()) {
+      if (Previous.isSingleResult() &&
+          isa<FieldDecl>(Previous.getFoundDecl()) &&
+          D.getCXXScopeSpec().isSet()) {
+        // The user tried to define a non-static data member
+        // out-of-line (C++ [dcl.meaning]p1).
+        Diag(NewVD->getLocation(), diag::err_nonstatic_member_out_of_line)
+          << D.getCXXScopeSpec().getRange();
+        Previous.clear();
+        NewVD->setInvalidDecl();
+      }
+    } else if (D.getCXXScopeSpec().isSet()) {
+      // No previous declaration in the qualifying scope.
+      Diag(D.getIdentifierLoc(), diag::err_no_member)
+        << Name << computeDeclContext(D.getCXXScopeSpec(), true)
+        << D.getCXXScopeSpec().getRange();
+      NewVD->setInvalidDecl();
+    }
+
+    D.setRedeclaration(CheckVariableDeclaration(NewVD, Previous));
+
+    // This is an explicit specialization of a static data member. Check it.
+    if (isExplicitSpecialization && !NewVD->isInvalidDecl() &&
+        CheckMemberSpecialization(NewVD, Previous))
+      NewVD->setInvalidDecl();
+  }
+  
+  // attributes declared post-definition are currently ignored
+  // FIXME: This should be handled in attribute merging, not
+  // here.
+  if (Previous.isSingleResult()) {
+    VarDecl *Def = dyn_cast<VarDecl>(Previous.getFoundDecl());
+    if (Def && (Def = Def->getDefinition()) &&
+        Def != NewVD && D.hasAttributes()) {
+      Diag(NewVD->getLocation(), diag::warn_attribute_precede_definition);
+      Diag(Def->getLocation(), diag::note_previous_definition);
+    }
+  }
+
+  // If this is a locally-scoped extern C variable, update the map of
+  // such variables.
+  if (CurContext->isFunctionOrMethod() && NewVD->isExternC() &&
+      !NewVD->isInvalidDecl())
+    RegisterLocallyScopedExternCDecl(NewVD, Previous, S);
+
+  // If there's a #pragma GCC visibility in scope, and this isn't a class
+  // member, set the visibility of this variable.
+  if (NewVD->getLinkage() == ExternalLinkage && !DC->isRecord())
+    AddPushedVisibilityAttribute(NewVD);
+  
+  MarkUnusedFileScopedDecl(NewVD);
+
+  return NewVD;
+}
+
+/// \brief Diagnose variable or built-in function shadowing.  Implements
+/// -Wshadow.
+///
+/// This method is called whenever a VarDecl is added to a "useful"
+/// scope.
+///
+/// \param S the scope in which the shadowing name is being declared
+/// \param R the lookup of the name
+///
+void Sema::CheckShadow(Scope *S, VarDecl *D, const LookupResult& R) {
+  // Return if warning is ignored.
+  if (Diags.getDiagnosticLevel(diag::warn_decl_shadow, R.getNameLoc()) ==
+        DiagnosticsEngine::Ignored)
+    return;
+
+  // Don't diagnose declarations at file scope.
+  if (D->hasGlobalStorage())
+    return;
+
+  DeclContext *NewDC = D->getDeclContext();
+
+  // Only diagnose if we're shadowing an unambiguous field or variable.
+  if (R.getResultKind() != LookupResult::Found)
+    return;
+
+  NamedDecl* ShadowedDecl = R.getFoundDecl();
+  if (!isa<VarDecl>(ShadowedDecl) && !isa<FieldDecl>(ShadowedDecl))
+    return;
+
+  // Fields are not shadowed by variables in C++ static methods.
+  if (isa<FieldDecl>(ShadowedDecl))
+    if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(NewDC))
+      if (MD->isStatic())
+        return;
+
+  if (VarDecl *shadowedVar = dyn_cast<VarDecl>(ShadowedDecl))
+    if (shadowedVar->isExternC()) {
+      // For shadowing external vars, make sure that we point to the global
+      // declaration, not a locally scoped extern declaration.
+      for (VarDecl::redecl_iterator
+             I = shadowedVar->redecls_begin(), E = shadowedVar->redecls_end();
+           I != E; ++I)
+        if (I->isFileVarDecl()) {
+          ShadowedDecl = *I;
+          break;
+        }
+    }
+
+  DeclContext *OldDC = ShadowedDecl->getDeclContext();
+
+  // Only warn about certain kinds of shadowing for class members.
+  if (NewDC && NewDC->isRecord()) {
+    // In particular, don't warn about shadowing non-class members.
+    if (!OldDC->isRecord())
+      return;
+
+    // TODO: should we warn about static data members shadowing
+    // static data members from base classes?
+    
+    // TODO: don't diagnose for inaccessible shadowed members.
+    // This is hard to do perfectly because we might friend the
+    // shadowing context, but that's just a false negative.
+  }
+
+  // Determine what kind of declaration we're shadowing.
+  unsigned Kind;
+  if (isa<RecordDecl>(OldDC)) {
+    if (isa<FieldDecl>(ShadowedDecl))
+      Kind = 3; // field
+    else
+      Kind = 2; // static data member
+  } else if (OldDC->isFileContext())
+    Kind = 1; // global
+  else
+    Kind = 0; // local
+
+  DeclarationName Name = R.getLookupName();
+
+  // Emit warning and note.
+  Diag(R.getNameLoc(), diag::warn_decl_shadow) << Name << Kind << OldDC;
+  Diag(ShadowedDecl->getLocation(), diag::note_previous_declaration);
+}
+
+/// \brief Check -Wshadow without the advantage of a previous lookup.
+void Sema::CheckShadow(Scope *S, VarDecl *D) {
+  if (Diags.getDiagnosticLevel(diag::warn_decl_shadow, D->getLocation()) ==
+        DiagnosticsEngine::Ignored)
+    return;
+
+  LookupResult R(*this, D->getDeclName(), D->getLocation(),
+                 Sema::LookupOrdinaryName, Sema::ForRedeclaration);
+  LookupName(R, S);
+  CheckShadow(S, D, R);
+}
+
+/// \brief Perform semantic checking on a newly-created variable
+/// declaration.
+///
+/// This routine performs all of the type-checking required for a
+/// variable declaration once it has been built. It is used both to
+/// check variables after they have been parsed and their declarators
+/// have been translated into a declaration, and to check variables
+/// that have been instantiated from a template.
+///
+/// Sets NewVD->isInvalidDecl() if an error was encountered.
+///
+/// Returns true if the variable declaration is a redeclaration.
+bool Sema::CheckVariableDeclaration(VarDecl *NewVD,
+                                    LookupResult &Previous) {
+  // If the decl is already known invalid, don't check it.
+  if (NewVD->isInvalidDecl())
+    return false;
+
+  QualType T = NewVD->getType();
+
+  if (T->isObjCObjectType()) {
+    Diag(NewVD->getLocation(), diag::err_statically_allocated_object)
+      << FixItHint::CreateInsertion(NewVD->getLocation(), "*");
+    T = Context.getObjCObjectPointerType(T);
+    NewVD->setType(T);
+  }
+
+  // Emit an error if an address space was applied to decl with local storage.
+  // This includes arrays of objects with address space qualifiers, but not
+  // automatic variables that point to other address spaces.
+  // ISO/IEC TR 18037 S5.1.2
+  if (NewVD->hasLocalStorage() && T.getAddressSpace() != 0) {
+    Diag(NewVD->getLocation(), diag::err_as_qualified_auto_decl);
+    NewVD->setInvalidDecl();
+    return false;
+  }
+
+  if (NewVD->hasLocalStorage() && T.isObjCGCWeak()
+      && !NewVD->hasAttr<BlocksAttr>()) {
+    if (getLangOpts().getGC() != LangOptions::NonGC)
+      Diag(NewVD->getLocation(), diag::warn_gc_attribute_weak_on_local);
+    else
+      Diag(NewVD->getLocation(), diag::warn_attribute_weak_on_local);
+  }
+  
+  bool isVM = T->isVariablyModifiedType();
+  if (isVM || NewVD->hasAttr<CleanupAttr>() ||
+      NewVD->hasAttr<BlocksAttr>())
+    getCurFunction()->setHasBranchProtectedScope();
+
+  if ((isVM && NewVD->hasLinkage()) ||
+      (T->isVariableArrayType() && NewVD->hasGlobalStorage())) {
+    bool SizeIsNegative;
+    llvm::APSInt Oversized;
+    QualType FixedTy =
+        TryToFixInvalidVariablyModifiedType(T, Context, SizeIsNegative,
+                                            Oversized);
+
+    if (FixedTy.isNull() && T->isVariableArrayType()) {
+      const VariableArrayType *VAT = Context.getAsVariableArrayType(T);
+      // FIXME: This won't give the correct result for
+      // int a[10][n];
+      SourceRange SizeRange = VAT->getSizeExpr()->getSourceRange();
+
+      if (NewVD->isFileVarDecl())
+        Diag(NewVD->getLocation(), diag::err_vla_decl_in_file_scope)
+        << SizeRange;
+      else if (NewVD->getStorageClass() == SC_Static)
+        Diag(NewVD->getLocation(), diag::err_vla_decl_has_static_storage)
+        << SizeRange;
+      else
+        Diag(NewVD->getLocation(), diag::err_vla_decl_has_extern_linkage)
+        << SizeRange;
+      NewVD->setInvalidDecl();
+      return false;
+    }
+
+    if (FixedTy.isNull()) {
+      if (NewVD->isFileVarDecl())
+        Diag(NewVD->getLocation(), diag::err_vm_decl_in_file_scope);
+      else
+        Diag(NewVD->getLocation(), diag::err_vm_decl_has_extern_linkage);
+      NewVD->setInvalidDecl();
+      return false;
+    }
+
+    Diag(NewVD->getLocation(), diag::warn_illegal_constant_array_size);
+    NewVD->setType(FixedTy);
+  }
+
+  if (Previous.empty() && NewVD->isExternC()) {
+    // Since we did not find anything by this name and we're declaring
+    // an extern "C" variable, look for a non-visible extern "C"
+    // declaration with the same name.
+    llvm::DenseMap<DeclarationName, NamedDecl *>::iterator Pos
+      = findLocallyScopedExternalDecl(NewVD->getDeclName());
+    if (Pos != LocallyScopedExternalDecls.end())
+      Previous.addDecl(Pos->second);
+  }
+
+  if (T->isVoidType() && !NewVD->hasExternalStorage()) {
+    Diag(NewVD->getLocation(), diag::err_typecheck_decl_incomplete_type)
+      << T;
+    NewVD->setInvalidDecl();
+    return false;
+  }
+
+  if (!NewVD->hasLocalStorage() && NewVD->hasAttr<BlocksAttr>()) {
+    Diag(NewVD->getLocation(), diag::err_block_on_nonlocal);
+    NewVD->setInvalidDecl();
+    return false;
+  }
+
+  if (isVM && NewVD->hasAttr<BlocksAttr>()) {
+    Diag(NewVD->getLocation(), diag::err_block_on_vm);
+    NewVD->setInvalidDecl();
+    return false;
+  }
+
+  if (NewVD->isConstexpr() && !T->isDependentType() &&
+      RequireLiteralType(NewVD->getLocation(), T,
+                         PDiag(diag::err_constexpr_var_non_literal))) {
+    NewVD->setInvalidDecl();
+    return false;
+  }
+
+  if (!Previous.empty()) {
+    MergeVarDecl(NewVD, Previous);
+    return true;
+  }
+  return false;
+}
+
+/// \brief Data used with FindOverriddenMethod
+struct FindOverriddenMethodData {
+  Sema *S;
+  CXXMethodDecl *Method;
+};
+
+/// \brief Member lookup function that determines whether a given C++
+/// method overrides a method in a base class, to be used with
+/// CXXRecordDecl::lookupInBases().
+static bool FindOverriddenMethod(const CXXBaseSpecifier *Specifier,
+                                 CXXBasePath &Path,
+                                 void *UserData) {
+  RecordDecl *BaseRecord = Specifier->getType()->getAs<RecordType>()->getDecl();
+
+  FindOverriddenMethodData *Data 
+    = reinterpret_cast<FindOverriddenMethodData*>(UserData);
+  
+  DeclarationName Name = Data->Method->getDeclName();
+  
+  // FIXME: Do we care about other names here too?
+  if (Name.getNameKind() == DeclarationName::CXXDestructorName) {
+    // We really want to find the base class destructor here.
+    QualType T = Data->S->Context.getTypeDeclType(BaseRecord);
+    CanQualType CT = Data->S->Context.getCanonicalType(T);
+    
+    Name = Data->S->Context.DeclarationNames.getCXXDestructorName(CT);
+  }    
+  
+  for (Path.Decls = BaseRecord->lookup(Name);
+       Path.Decls.first != Path.Decls.second;
+       ++Path.Decls.first) {
+    NamedDecl *D = *Path.Decls.first;
+    if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(D)) {
+      if (MD->isVirtual() && !Data->S->IsOverload(Data->Method, MD, false))
+        return true;
+    }
+  }
+  
+  return false;
+}
+
+static bool hasDelayedExceptionSpec(CXXMethodDecl *Method) {
+  const FunctionProtoType *Proto =Method->getType()->getAs<FunctionProtoType>();
+  return Proto && Proto->getExceptionSpecType() == EST_Delayed;
+}
+
+/// AddOverriddenMethods - See if a method overrides any in the base classes,
+/// and if so, check that it's a valid override and remember it.
+bool Sema::AddOverriddenMethods(CXXRecordDecl *DC, CXXMethodDecl *MD) {
+  // Look for virtual methods in base classes that this method might override.
+  CXXBasePaths Paths;
+  FindOverriddenMethodData Data;
+  Data.Method = MD;
+  Data.S = this;
+  bool AddedAny = false;
+  if (DC->lookupInBases(&FindOverriddenMethod, &Data, Paths)) {
+    for (CXXBasePaths::decl_iterator I = Paths.found_decls_begin(),
+         E = Paths.found_decls_end(); I != E; ++I) {
+      if (CXXMethodDecl *OldMD = dyn_cast<CXXMethodDecl>(*I)) {
+        MD->addOverriddenMethod(OldMD->getCanonicalDecl());
+        if (!CheckOverridingFunctionReturnType(MD, OldMD) &&
+            (hasDelayedExceptionSpec(MD) ||
+             !CheckOverridingFunctionExceptionSpec(MD, OldMD)) &&
+            !CheckIfOverriddenFunctionIsMarkedFinal(MD, OldMD)) {
+          AddedAny = true;
+        }
+      }
+    }
+  }
+  
+  return AddedAny;
+}
+
+namespace {
+  // Struct for holding all of the extra arguments needed by
+  // DiagnoseInvalidRedeclaration to call Sema::ActOnFunctionDeclarator.
+  struct ActOnFDArgs {
+    Scope *S;
+    Declarator &D;
+    MultiTemplateParamsArg TemplateParamLists;
+    bool AddToScope;
+  };
+}
+
+namespace {
+
+// Callback to only accept typo corrections that have a non-zero edit distance.
+// Also only accept corrections that have the same parent decl.
+class DifferentNameValidatorCCC : public CorrectionCandidateCallback {
+ public:
+  DifferentNameValidatorCCC(CXXRecordDecl *Parent)
+      : ExpectedParent(Parent ? Parent->getCanonicalDecl() : 0) {}
+
+  virtual bool ValidateCandidate(const TypoCorrection &candidate) {
+    if (candidate.getEditDistance() == 0)
+      return false;
+
+    if (CXXMethodDecl *MD = candidate.getCorrectionDeclAs<CXXMethodDecl>()) {
+      CXXRecordDecl *Parent = MD->getParent();
+      return Parent && Parent->getCanonicalDecl() == ExpectedParent;
+    }
+
+    return !ExpectedParent;
+  }
+
+ private:
+  CXXRecordDecl *ExpectedParent;
+};
+
+}
+
+/// \brief Generate diagnostics for an invalid function redeclaration.
+///
+/// This routine handles generating the diagnostic messages for an invalid
+/// function redeclaration, including finding possible similar declarations
+/// or performing typo correction if there are no previous declarations with
+/// the same name.
+///
+/// Returns a NamedDecl iff typo correction was performed and substituting in
+/// the new declaration name does not cause new errors.
+static NamedDecl* DiagnoseInvalidRedeclaration(
+    Sema &SemaRef, LookupResult &Previous, FunctionDecl *NewFD,
+    ActOnFDArgs &ExtraArgs) {
+  NamedDecl *Result = NULL;
+  DeclarationName Name = NewFD->getDeclName();
+  DeclContext *NewDC = NewFD->getDeclContext();
+  LookupResult Prev(SemaRef, Name, NewFD->getLocation(),
+                    Sema::LookupOrdinaryName, Sema::ForRedeclaration);
+  llvm::SmallVector<unsigned, 1> MismatchedParams;
+  llvm::SmallVector<std::pair<FunctionDecl*, unsigned>, 1> NearMatches;
+  TypoCorrection Correction;
+  bool isFriendDecl = (SemaRef.getLangOpts().CPlusPlus &&
+                       ExtraArgs.D.getDeclSpec().isFriendSpecified());
+  unsigned DiagMsg = isFriendDecl ? diag::err_no_matching_local_friend
+                                  : diag::err_member_def_does_not_match;
+
+  NewFD->setInvalidDecl();
+  SemaRef.LookupQualifiedName(Prev, NewDC);
+  assert(!Prev.isAmbiguous() &&
+         "Cannot have an ambiguity in previous-declaration lookup");
+  CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(NewFD);
+  DifferentNameValidatorCCC Validator(MD ? MD->getParent() : 0);
+  if (!Prev.empty()) {
+    for (LookupResult::iterator Func = Prev.begin(), FuncEnd = Prev.end();
+         Func != FuncEnd; ++Func) {
+      FunctionDecl *FD = dyn_cast<FunctionDecl>(*Func);
+      if (FD &&
+          hasSimilarParameters(SemaRef.Context, FD, NewFD, MismatchedParams)) {
+        // Add 1 to the index so that 0 can mean the mismatch didn't
+        // involve a parameter
+        unsigned ParamNum =
+            MismatchedParams.empty() ? 0 : MismatchedParams.front() + 1;
+        NearMatches.push_back(std::make_pair(FD, ParamNum));
+      }
+    }
+  // If the qualified name lookup yielded nothing, try typo correction
+  } else if ((Correction = SemaRef.CorrectTypo(Prev.getLookupNameInfo(),
+                                         Prev.getLookupKind(), 0, 0,
+                                         Validator, NewDC))) {
+    // Trap errors.
+    Sema::SFINAETrap Trap(SemaRef);
+
+    // Set up everything for the call to ActOnFunctionDeclarator
+    ExtraArgs.D.SetIdentifier(Correction.getCorrectionAsIdentifierInfo(),
+                              ExtraArgs.D.getIdentifierLoc());
+    Previous.clear();
+    Previous.setLookupName(Correction.getCorrection());
+    for (TypoCorrection::decl_iterator CDecl = Correction.begin(),
+                                    CDeclEnd = Correction.end();
+         CDecl != CDeclEnd; ++CDecl) {
+      FunctionDecl *FD = dyn_cast<FunctionDecl>(*CDecl);
+      if (FD && hasSimilarParameters(SemaRef.Context, FD, NewFD,
+                                     MismatchedParams)) {
+        Previous.addDecl(FD);
+      }
+    }
+    bool wasRedeclaration = ExtraArgs.D.isRedeclaration();
+    // TODO: Refactor ActOnFunctionDeclarator so that we can call only the
+    // pieces need to verify the typo-corrected C++ declaraction and hopefully
+    // eliminate the need for the parameter pack ExtraArgs.
+    Result = SemaRef.ActOnFunctionDeclarator(
+        ExtraArgs.S, ExtraArgs.D,
+        Correction.getCorrectionDecl()->getDeclContext(),
+        NewFD->getTypeSourceInfo(), Previous, ExtraArgs.TemplateParamLists,
+        ExtraArgs.AddToScope);
+    if (Trap.hasErrorOccurred()) {
+      // Pretend the typo correction never occurred
+      ExtraArgs.D.SetIdentifier(Name.getAsIdentifierInfo(),
+                                ExtraArgs.D.getIdentifierLoc());
+      ExtraArgs.D.setRedeclaration(wasRedeclaration);
+      Previous.clear();
+      Previous.setLookupName(Name);
+      Result = NULL;
+    } else {
+      for (LookupResult::iterator Func = Previous.begin(),
+                               FuncEnd = Previous.end();
+           Func != FuncEnd; ++Func) {
+        if (FunctionDecl *FD = dyn_cast<FunctionDecl>(*Func))
+          NearMatches.push_back(std::make_pair(FD, 0));
+      }
+    }
+    if (NearMatches.empty()) {
+      // Ignore the correction if it didn't yield any close FunctionDecl matches
+      Correction = TypoCorrection();
+    } else {
+      DiagMsg = isFriendDecl ? diag::err_no_matching_local_friend_suggest
+                             : diag::err_member_def_does_not_match_suggest;
+    }
+  }
+
+  if (Correction)
+    SemaRef.Diag(NewFD->getLocation(), DiagMsg)
+        << Name << NewDC << Correction.getQuoted(SemaRef.getLangOpts())
+        << FixItHint::CreateReplacement(
+            NewFD->getLocation(),
+            Correction.getAsString(SemaRef.getLangOpts()));
+  else
+    SemaRef.Diag(NewFD->getLocation(), DiagMsg)
+        << Name << NewDC << NewFD->getLocation();
+
+  bool NewFDisConst = false;
+  if (CXXMethodDecl *NewMD = dyn_cast<CXXMethodDecl>(NewFD))
+    NewFDisConst = NewMD->getTypeQualifiers() & Qualifiers::Const;
+
+  for (llvm::SmallVector<std::pair<FunctionDecl*, unsigned>, 1>::iterator
+       NearMatch = NearMatches.begin(), NearMatchEnd = NearMatches.end();
+       NearMatch != NearMatchEnd; ++NearMatch) {
+    FunctionDecl *FD = NearMatch->first;
+    bool FDisConst = false;
+    if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD))
+      FDisConst = MD->getTypeQualifiers() & Qualifiers::Const;
+
+    if (unsigned Idx = NearMatch->second) {
+      ParmVarDecl *FDParam = FD->getParamDecl(Idx-1);
+      SourceLocation Loc = FDParam->getTypeSpecStartLoc();
+      if (Loc.isInvalid()) Loc = FD->getLocation();
+      SemaRef.Diag(Loc, diag::note_member_def_close_param_match)
+          << Idx << FDParam->getType() << NewFD->getParamDecl(Idx-1)->getType();
+    } else if (Correction) {
+      SemaRef.Diag(FD->getLocation(), diag::note_previous_decl)
+          << Correction.getQuoted(SemaRef.getLangOpts());
+    } else if (FDisConst != NewFDisConst) {
+      SemaRef.Diag(FD->getLocation(), diag::note_member_def_close_const_match)
+          << NewFDisConst << FD->getSourceRange().getEnd();
+    } else
+      SemaRef.Diag(FD->getLocation(), diag::note_member_def_close_match);
+  }
+  return Result;
+}
+
+static FunctionDecl::StorageClass getFunctionStorageClass(Sema &SemaRef, 
+                                                          Declarator &D) {
+  switch (D.getDeclSpec().getStorageClassSpec()) {
+  default: llvm_unreachable("Unknown storage class!");
+  case DeclSpec::SCS_auto:
+  case DeclSpec::SCS_register:
+  case DeclSpec::SCS_mutable:
+    SemaRef.Diag(D.getDeclSpec().getStorageClassSpecLoc(),
+                 diag::err_typecheck_sclass_func);
+    D.setInvalidType();
+    break;
+  case DeclSpec::SCS_unspecified: break;
+  case DeclSpec::SCS_extern: return SC_Extern;
+  case DeclSpec::SCS_static: {
+    if (SemaRef.CurContext->getRedeclContext()->isFunctionOrMethod()) {
+      // C99 6.7.1p5:
+      //   The declaration of an identifier for a function that has
+      //   block scope shall have no explicit storage-class specifier
+      //   other than extern
+      // See also (C++ [dcl.stc]p4).
+      SemaRef.Diag(D.getDeclSpec().getStorageClassSpecLoc(),
+                   diag::err_static_block_func);
+      break;
+    } else
+      return SC_Static;
+  }
+  case DeclSpec::SCS_private_extern: return SC_PrivateExtern;
+  }
+
+  // No explicit storage class has already been returned
+  return SC_None;
+}
+
+static FunctionDecl* CreateNewFunctionDecl(Sema &SemaRef, Declarator &D,
+                                           DeclContext *DC, QualType &R,
+                                           TypeSourceInfo *TInfo,
+                                           FunctionDecl::StorageClass SC,
+                                           bool &IsVirtualOkay) {
+  DeclarationNameInfo NameInfo = SemaRef.GetNameForDeclarator(D);
+  DeclarationName Name = NameInfo.getName();
+
+  FunctionDecl *NewFD = 0;
+  bool isInline = D.getDeclSpec().isInlineSpecified();
+  DeclSpec::SCS SCSpec = D.getDeclSpec().getStorageClassSpecAsWritten();
+  FunctionDecl::StorageClass SCAsWritten
+    = StorageClassSpecToFunctionDeclStorageClass(SCSpec);
+
+  if (!SemaRef.getLangOpts().CPlusPlus) {
+    // Determine whether the function was written with a
+    // prototype. This true when:
+    //   - there is a prototype in the declarator, or
+    //   - the type R of the function is some kind of typedef or other reference
+    //     to a type name (which eventually refers to a function type).
+    bool HasPrototype =
+      (D.isFunctionDeclarator() && D.getFunctionTypeInfo().hasPrototype) ||
+      (!isa<FunctionType>(R.getTypePtr()) && R->isFunctionProtoType());
+
+    NewFD = FunctionDecl::Create(SemaRef.Context, DC, 
+                                 D.getLocStart(), NameInfo, R, 
+                                 TInfo, SC, SCAsWritten, isInline, 
+                                 HasPrototype);
+    if (D.isInvalidType())
+      NewFD->setInvalidDecl();
+
+    // Set the lexical context.
+    NewFD->setLexicalDeclContext(SemaRef.CurContext);
+
+    return NewFD;
+  }
+
+  bool isExplicit = D.getDeclSpec().isExplicitSpecified();
+  bool isConstexpr = D.getDeclSpec().isConstexprSpecified();
+
+  // Check that the return type is not an abstract class type.
+  // For record types, this is done by the AbstractClassUsageDiagnoser once
+  // the class has been completely parsed.
+  if (!DC->isRecord() &&
+      SemaRef.RequireNonAbstractType(D.getIdentifierLoc(),
+                                     R->getAs<FunctionType>()->getResultType(),
+                                     diag::err_abstract_type_in_decl,
+                                     SemaRef.AbstractReturnType))
+    D.setInvalidType();
+
+  if (Name.getNameKind() == DeclarationName::CXXConstructorName) {
+    // This is a C++ constructor declaration.
+    assert(DC->isRecord() &&
+           "Constructors can only be declared in a member context");
+
+    R = SemaRef.CheckConstructorDeclarator(D, R, SC);
+    return CXXConstructorDecl::Create(SemaRef.Context, cast<CXXRecordDecl>(DC),
+                                      D.getLocStart(), NameInfo,
+                                      R, TInfo, isExplicit, isInline,
+                                      /*isImplicitlyDeclared=*/false,
+                                      isConstexpr);
+
+  } else if (Name.getNameKind() == DeclarationName::CXXDestructorName) {
+    // This is a C++ destructor declaration.
+    if (DC->isRecord()) {
+      R = SemaRef.CheckDestructorDeclarator(D, R, SC);
+      CXXRecordDecl *Record = cast<CXXRecordDecl>(DC);
+      CXXDestructorDecl *NewDD = CXXDestructorDecl::Create(
+                                        SemaRef.Context, Record,
+                                        D.getLocStart(),
+                                        NameInfo, R, TInfo, isInline,
+                                        /*isImplicitlyDeclared=*/false);
+
+      // If the class is complete, then we now create the implicit exception
+      // specification. If the class is incomplete or dependent, we can't do
+      // it yet.
+      if (SemaRef.getLangOpts().CPlusPlus0x && !Record->isDependentType() &&
+          Record->getDefinition() && !Record->isBeingDefined() &&
+          R->getAs<FunctionProtoType>()->getExceptionSpecType() == EST_None) {
+        SemaRef.AdjustDestructorExceptionSpec(Record, NewDD);
+      }
+
+      IsVirtualOkay = true;
+      return NewDD;
+
+    } else {
+      SemaRef.Diag(D.getIdentifierLoc(), diag::err_destructor_not_member);
+      D.setInvalidType();
+
+      // Create a FunctionDecl to satisfy the function definition parsing
+      // code path.
+      return FunctionDecl::Create(SemaRef.Context, DC,
+                                  D.getLocStart(),
+                                  D.getIdentifierLoc(), Name, R, TInfo,
+                                  SC, SCAsWritten, isInline,
+                                  /*hasPrototype=*/true, isConstexpr);
+    }
+
+  } else if (Name.getNameKind() == DeclarationName::CXXConversionFunctionName) {
+    if (!DC->isRecord()) {
+      SemaRef.Diag(D.getIdentifierLoc(),
+           diag::err_conv_function_not_member);
+      return 0;
+    }
+
+    SemaRef.CheckConversionDeclarator(D, R, SC);
+    IsVirtualOkay = true;
+    return CXXConversionDecl::Create(SemaRef.Context, cast<CXXRecordDecl>(DC),
+                                     D.getLocStart(), NameInfo,
+                                     R, TInfo, isInline, isExplicit,
+                                     isConstexpr, SourceLocation());
+
+  } else if (DC->isRecord()) {
+    // If the name of the function is the same as the name of the record,
+    // then this must be an invalid constructor that has a return type.
+    // (The parser checks for a return type and makes the declarator a
+    // constructor if it has no return type).
+    if (Name.getAsIdentifierInfo() &&
+        Name.getAsIdentifierInfo() == cast<CXXRecordDecl>(DC)->getIdentifier()){
+      SemaRef.Diag(D.getIdentifierLoc(), diag::err_constructor_return_type)
+        << SourceRange(D.getDeclSpec().getTypeSpecTypeLoc())
+        << SourceRange(D.getIdentifierLoc());
+      return 0;
+    }
+
+    bool isStatic = SC == SC_Static;
+
+    // [class.free]p1:
+    // Any allocation function for a class T is a static member
+    // (even if not explicitly declared static).
+    if (Name.getCXXOverloadedOperator() == OO_New ||
+        Name.getCXXOverloadedOperator() == OO_Array_New)
+      isStatic = true;
+
+    // [class.free]p6 Any deallocation function for a class X is a static member
+    // (even if not explicitly declared static).
+    if (Name.getCXXOverloadedOperator() == OO_Delete ||
+        Name.getCXXOverloadedOperator() == OO_Array_Delete)
+      isStatic = true;
+
+    IsVirtualOkay = !isStatic;
+
+    // This is a C++ method declaration.
+    return CXXMethodDecl::Create(SemaRef.Context, cast<CXXRecordDecl>(DC),
+                                 D.getLocStart(), NameInfo, R,
+                                 TInfo, isStatic, SCAsWritten, isInline,
+                                 isConstexpr, SourceLocation());
+
+  } else {
+    // Determine whether the function was written with a
+    // prototype. This true when:
+    //   - we're in C++ (where every function has a prototype),
+    return FunctionDecl::Create(SemaRef.Context, DC,
+                                D.getLocStart(),
+                                NameInfo, R, TInfo, SC, SCAsWritten, isInline,
+                                true/*HasPrototype*/, isConstexpr);
+  }
+}
+
+NamedDecl*
+Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
+                              TypeSourceInfo *TInfo, LookupResult &Previous,
+                              MultiTemplateParamsArg TemplateParamLists,
+                              bool &AddToScope) {
+  QualType R = TInfo->getType();
+
+  assert(R.getTypePtr()->isFunctionType());
+
+  // TODO: consider using NameInfo for diagnostic.
+  DeclarationNameInfo NameInfo = GetNameForDeclarator(D);
+  DeclarationName Name = NameInfo.getName();
+  FunctionDecl::StorageClass SC = getFunctionStorageClass(*this, D);
+
+  if (D.getDeclSpec().isThreadSpecified())
+    Diag(D.getDeclSpec().getThreadSpecLoc(), diag::err_invalid_thread);
+
+  // Do not allow returning a objc interface by-value.
+  if (R->getAs<FunctionType>()->getResultType()->isObjCObjectType()) {
+    Diag(D.getIdentifierLoc(),
+         diag::err_object_cannot_be_passed_returned_by_value) << 0
+    << R->getAs<FunctionType>()->getResultType()
+    << FixItHint::CreateInsertion(D.getIdentifierLoc(), "*");
+
+    QualType T = R->getAs<FunctionType>()->getResultType();
+    T = Context.getObjCObjectPointerType(T);
+    if (const FunctionProtoType *FPT = dyn_cast<FunctionProtoType>(R)) {
+      FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo();
+      R = Context.getFunctionType(T, FPT->arg_type_begin(),
+                                  FPT->getNumArgs(), EPI);
+    }
+    else if (isa<FunctionNoProtoType>(R))
+      R = Context.getFunctionNoProtoType(T);
+  }
+
+  bool isFriend = false;
+  FunctionTemplateDecl *FunctionTemplate = 0;
+  bool isExplicitSpecialization = false;
+  bool isFunctionTemplateSpecialization = false;
+  bool isDependentClassScopeExplicitSpecialization = false;
+  bool isVirtualOkay = false;
+
+  FunctionDecl *NewFD = CreateNewFunctionDecl(*this, D, DC, R, TInfo, SC,
+                                              isVirtualOkay);
+  if (!NewFD) return 0;
+
+  if (OriginalLexicalContext && OriginalLexicalContext->isObjCContainer())
+    NewFD->setTopLevelDeclInObjCContainer();
+
+  if (getLangOpts().CPlusPlus) {
+    bool isInline = D.getDeclSpec().isInlineSpecified();
+    bool isVirtual = D.getDeclSpec().isVirtualSpecified();
+    bool isExplicit = D.getDeclSpec().isExplicitSpecified();
+    bool isConstexpr = D.getDeclSpec().isConstexprSpecified();
+    isFriend = D.getDeclSpec().isFriendSpecified();
+    if (isFriend && !isInline && D.isFunctionDefinition()) {
+      // C++ [class.friend]p5
+      //   A function can be defined in a friend declaration of a
+      //   class . . . . Such a function is implicitly inline.
+      NewFD->setImplicitlyInline();
+    }
+
+    SetNestedNameSpecifier(NewFD, D);
+    isExplicitSpecialization = false;
+    isFunctionTemplateSpecialization = false;
+    if (D.isInvalidType())
+      NewFD->setInvalidDecl();
+    
+    // Set the lexical context. If the declarator has a C++
+    // scope specifier, or is the object of a friend declaration, the
+    // lexical context will be different from the semantic context.
+    NewFD->setLexicalDeclContext(CurContext);
+        
+    // Match up the template parameter lists with the scope specifier, then
+    // determine whether we have a template or a template specialization.
+    bool Invalid = false;
+    if (TemplateParameterList *TemplateParams
+          = MatchTemplateParametersToScopeSpecifier(
+                                  D.getDeclSpec().getLocStart(),
+                                  D.getIdentifierLoc(),
+                                  D.getCXXScopeSpec(),
+                                  TemplateParamLists.get(),
+                                  TemplateParamLists.size(),
+                                  isFriend,
+                                  isExplicitSpecialization,
+                                  Invalid)) {
+      if (TemplateParams->size() > 0) {
+        // This is a function template
+
+        // Check that we can declare a template here.
+        if (CheckTemplateDeclScope(S, TemplateParams))
+          return 0;
+
+        // A destructor cannot be a template.
+        if (Name.getNameKind() == DeclarationName::CXXDestructorName) {
+          Diag(NewFD->getLocation(), diag::err_destructor_template);
+          return 0;
+        }
+        
+        // If we're adding a template to a dependent context, we may need to 
+        // rebuilding some of the types used within the template parameter list,
+        // now that we know what the current instantiation is.
+        if (DC->isDependentContext()) {
+          ContextRAII SavedContext(*this, DC);
+          if (RebuildTemplateParamsInCurrentInstantiation(TemplateParams))
+            Invalid = true;
+        }
+        
+
+        FunctionTemplate = FunctionTemplateDecl::Create(Context, DC,
+                                                        NewFD->getLocation(),
+                                                        Name, TemplateParams,
+                                                        NewFD);
+        FunctionTemplate->setLexicalDeclContext(CurContext);
+        NewFD->setDescribedFunctionTemplate(FunctionTemplate);
+
+        // For source fidelity, store the other template param lists.
+        if (TemplateParamLists.size() > 1) {
+          NewFD->setTemplateParameterListsInfo(Context,
+                                               TemplateParamLists.size() - 1,
+                                               TemplateParamLists.release());
+        }
+      } else {
+        // This is a function template specialization.
+        isFunctionTemplateSpecialization = true;
+        // For source fidelity, store all the template param lists.
+        NewFD->setTemplateParameterListsInfo(Context,
+                                             TemplateParamLists.size(),
+                                             TemplateParamLists.release());
+
+        // C++0x [temp.expl.spec]p20 forbids "template<> friend void foo(int);".
+        if (isFriend) {
+          // We want to remove the "template<>", found here.
+          SourceRange RemoveRange = TemplateParams->getSourceRange();
+
+          // If we remove the template<> and the name is not a
+          // template-id, we're actually silently creating a problem:
+          // the friend declaration will refer to an untemplated decl,
+          // and clearly the user wants a template specialization.  So
+          // we need to insert '<>' after the name.
+          SourceLocation InsertLoc;
+          if (D.getName().getKind() != UnqualifiedId::IK_TemplateId) {
+            InsertLoc = D.getName().getSourceRange().getEnd();
+            InsertLoc = PP.getLocForEndOfToken(InsertLoc);
+          }
+
+          Diag(D.getIdentifierLoc(), diag::err_template_spec_decl_friend)
+            << Name << RemoveRange
+            << FixItHint::CreateRemoval(RemoveRange)
+            << FixItHint::CreateInsertion(InsertLoc, "<>");
+        }
+      }
+    }
+    else {
+      // All template param lists were matched against the scope specifier:
+      // this is NOT (an explicit specialization of) a template.
+      if (TemplateParamLists.size() > 0)
+        // For source fidelity, store all the template param lists.
+        NewFD->setTemplateParameterListsInfo(Context,
+                                             TemplateParamLists.size(),
+                                             TemplateParamLists.release());
+    }
+
+    if (Invalid) {
+      NewFD->setInvalidDecl();
+      if (FunctionTemplate)
+        FunctionTemplate->setInvalidDecl();
+    }
+
+    // If we see "T var();" at block scope, where T is a class type, it is
+    // probably an attempt to initialize a variable, not a function declaration.
+    // We don't catch this case earlier, since there is no ambiguity here.
+    if (!FunctionTemplate && D.getFunctionDefinitionKind() == FDK_Declaration &&
+        CurContext->isFunctionOrMethod() &&
+        D.getNumTypeObjects() == 1 && D.isFunctionDeclarator() &&
+        D.getDeclSpec().getStorageClassSpecAsWritten()
+          == DeclSpec::SCS_unspecified) {
+      QualType T = R->getAs<FunctionType>()->getResultType();
+      DeclaratorChunk &C = D.getTypeObject(0);
+      if (!T->isVoidType() && C.Fun.NumArgs == 0 && !C.Fun.isVariadic &&
+          !C.Fun.TrailingReturnType &&
+          C.Fun.getExceptionSpecType() == EST_None) {
+        SourceRange ParenRange(C.Loc, C.EndLoc);
+        Diag(C.Loc, diag::warn_empty_parens_are_function_decl) << ParenRange;
+
+        // If the declaration looks like:
+        //   T var1,
+        //   f();
+        // and name lookup finds a function named 'f', then the ',' was
+        // probably intended to be a ';'.
+        if (!D.isFirstDeclarator() && D.getIdentifier()) {
+          FullSourceLoc Comma(D.getCommaLoc(), SourceMgr);
+          FullSourceLoc Name(D.getIdentifierLoc(), SourceMgr);
+          if (Comma.getFileID() != Name.getFileID() ||
+              Comma.getSpellingLineNumber() != Name.getSpellingLineNumber()) {
+            LookupResult Result(*this, D.getIdentifier(), SourceLocation(),
+                                LookupOrdinaryName);
+            if (LookupName(Result, S))
+              Diag(D.getCommaLoc(), diag::note_empty_parens_function_call)
+                << FixItHint::CreateReplacement(D.getCommaLoc(), ";") << NewFD;
+          }
+        }
+        const CXXRecordDecl *RD = T->getAsCXXRecordDecl();
+        // Empty parens mean value-initialization, and no parens mean default
+        // initialization. These are equivalent if the default constructor is
+        // user-provided, or if zero-initialization is a no-op.
+        if (RD && RD->hasDefinition() &&
+            (RD->isEmpty() || RD->hasUserProvidedDefaultConstructor()))
+          Diag(C.Loc, diag::note_empty_parens_default_ctor)
+            << FixItHint::CreateRemoval(ParenRange);
+        else if (const char *Init = getFixItZeroInitializerForType(T))
+          Diag(C.Loc, diag::note_empty_parens_zero_initialize)
+            << FixItHint::CreateReplacement(ParenRange, Init);
+        else if (LangOpts.CPlusPlus0x)
+          Diag(C.Loc, diag::note_empty_parens_zero_initialize)
+            << FixItHint::CreateReplacement(ParenRange, "{}");
+      }
+    }
+
+    // C++ [dcl.fct.spec]p5:
+    //   The virtual specifier shall only be used in declarations of
+    //   nonstatic class member functions that appear within a
+    //   member-specification of a class declaration; see 10.3.
+    //
+    if (isVirtual && !NewFD->isInvalidDecl()) {
+      if (!isVirtualOkay) {
+        Diag(D.getDeclSpec().getVirtualSpecLoc(),
+             diag::err_virtual_non_function);
+      } else if (!CurContext->isRecord()) {
+        // 'virtual' was specified outside of the class.
+        Diag(D.getDeclSpec().getVirtualSpecLoc(), 
+             diag::err_virtual_out_of_class)
+          << FixItHint::CreateRemoval(D.getDeclSpec().getVirtualSpecLoc());
+      } else if (NewFD->getDescribedFunctionTemplate()) {
+        // C++ [temp.mem]p3:
+        //  A member function template shall not be virtual.
+        Diag(D.getDeclSpec().getVirtualSpecLoc(),
+             diag::err_virtual_member_function_template)
+          << FixItHint::CreateRemoval(D.getDeclSpec().getVirtualSpecLoc());
+      } else {
+        // Okay: Add virtual to the method.
+        NewFD->setVirtualAsWritten(true);
+      }
+    }
+
+    // C++ [dcl.fct.spec]p3:
+    //  The inline specifier shall not appear on a block scope function 
+    //  declaration.
+    if (isInline && !NewFD->isInvalidDecl()) {
+      if (CurContext->isFunctionOrMethod()) {
+        // 'inline' is not allowed on block scope function declaration.
+        Diag(D.getDeclSpec().getInlineSpecLoc(), 
+             diag::err_inline_declaration_block_scope) << Name
+          << FixItHint::CreateRemoval(D.getDeclSpec().getInlineSpecLoc());
+      }
+    }
+
+    // C++ [dcl.fct.spec]p6:
+    //  The explicit specifier shall be used only in the declaration of a
+    //  constructor or conversion function within its class definition; 
+    //  see 12.3.1 and 12.3.2.
+    if (isExplicit && !NewFD->isInvalidDecl()) {
+      if (!CurContext->isRecord()) {
+        // 'explicit' was specified outside of the class.
+        Diag(D.getDeclSpec().getExplicitSpecLoc(), 
+             diag::err_explicit_out_of_class)
+          << FixItHint::CreateRemoval(D.getDeclSpec().getExplicitSpecLoc());
+      } else if (!isa<CXXConstructorDecl>(NewFD) && 
+                 !isa<CXXConversionDecl>(NewFD)) {
+        // 'explicit' was specified on a function that wasn't a constructor
+        // or conversion function.
+        Diag(D.getDeclSpec().getExplicitSpecLoc(),
+             diag::err_explicit_non_ctor_or_conv_function)
+          << FixItHint::CreateRemoval(D.getDeclSpec().getExplicitSpecLoc());
+      }      
+    }
+
+    if (isConstexpr) {
+      // C++0x [dcl.constexpr]p2: constexpr functions and constexpr constructors
+      // are implicitly inline.
+      NewFD->setImplicitlyInline();
+
+      // C++0x [dcl.constexpr]p3: functions declared constexpr are required to
+      // be either constructors or to return a literal type. Therefore,
+      // destructors cannot be declared constexpr.
+      if (isa<CXXDestructorDecl>(NewFD))
+        Diag(D.getDeclSpec().getConstexprSpecLoc(), diag::err_constexpr_dtor);
+    }
+
+    // If __module_private__ was specified, mark the function accordingly.
+    if (D.getDeclSpec().isModulePrivateSpecified()) {
+      if (isFunctionTemplateSpecialization) {
+        SourceLocation ModulePrivateLoc
+          = D.getDeclSpec().getModulePrivateSpecLoc();
+        Diag(ModulePrivateLoc, diag::err_module_private_specialization)
+          << 0
+          << FixItHint::CreateRemoval(ModulePrivateLoc);
+      } else {
+        NewFD->setModulePrivate();
+        if (FunctionTemplate)
+          FunctionTemplate->setModulePrivate();
+      }
+    }
+
+    if (isFriend) {
+      // For now, claim that the objects have no previous declaration.
+      if (FunctionTemplate) {
+        FunctionTemplate->setObjectOfFriendDecl(false);
+        FunctionTemplate->setAccess(AS_public);
+      }
+      NewFD->setObjectOfFriendDecl(false);
+      NewFD->setAccess(AS_public);
+    }
+
+    // If a function is defined as defaulted or deleted, mark it as such now.
+    switch (D.getFunctionDefinitionKind()) {
+      case FDK_Declaration:
+      case FDK_Definition:
+        break;
+        
+      case FDK_Defaulted:
+        NewFD->setDefaulted();
+        break;
+        
+      case FDK_Deleted:
+        NewFD->setDeletedAsWritten();
+        break;
+    }
+
+    if (isa<CXXMethodDecl>(NewFD) && DC == CurContext &&
+        D.isFunctionDefinition()) {
+      // C++ [class.mfct]p2:
+      //   A member function may be defined (8.4) in its class definition, in 
+      //   which case it is an inline member function (7.1.2)
+      NewFD->setImplicitlyInline();
+    }
+
+    if (SC == SC_Static && isa<CXXMethodDecl>(NewFD) &&
+        !CurContext->isRecord()) {
+      // C++ [class.static]p1:
+      //   A data or function member of a class may be declared static
+      //   in a class definition, in which case it is a static member of
+      //   the class.
+
+      // Complain about the 'static' specifier if it's on an out-of-line
+      // member function definition.
+      Diag(D.getDeclSpec().getStorageClassSpecLoc(),
+           diag::err_static_out_of_line)
+        << FixItHint::CreateRemoval(D.getDeclSpec().getStorageClassSpecLoc());
+    }
+  }
+
+  // Filter out previous declarations that don't match the scope.
+  FilterLookupForScope(Previous, DC, S, NewFD->hasLinkage(),
+                       isExplicitSpecialization ||
+                       isFunctionTemplateSpecialization);
+  
+  // Handle GNU asm-label extension (encoded as an attribute).
+  if (Expr *E = (Expr*) D.getAsmLabel()) {
+    // The parser guarantees this is a string.
+    StringLiteral *SE = cast<StringLiteral>(E);
+    NewFD->addAttr(::new (Context) AsmLabelAttr(SE->getStrTokenLoc(0), Context,
+                                                SE->getString()));
+  } else if (!ExtnameUndeclaredIdentifiers.empty()) {
+    llvm::DenseMap<IdentifierInfo*,AsmLabelAttr*>::iterator I =
+      ExtnameUndeclaredIdentifiers.find(NewFD->getIdentifier());
+    if (I != ExtnameUndeclaredIdentifiers.end()) {
+      NewFD->addAttr(I->second);
+      ExtnameUndeclaredIdentifiers.erase(I);
+    }
+  }
+
+  // Copy the parameter declarations from the declarator D to the function
+  // declaration NewFD, if they are available.  First scavenge them into Params.
+  SmallVector<ParmVarDecl*, 16> Params;
+  if (D.isFunctionDeclarator()) {
+    DeclaratorChunk::FunctionTypeInfo &FTI = D.getFunctionTypeInfo();
+
+    // Check for C99 6.7.5.3p10 - foo(void) is a non-varargs
+    // function that takes no arguments, not a function that takes a
+    // single void argument.
+    // We let through "const void" here because Sema::GetTypeForDeclarator
+    // already checks for that case.
+    if (FTI.NumArgs == 1 && !FTI.isVariadic && FTI.ArgInfo[0].Ident == 0 &&
+        FTI.ArgInfo[0].Param &&
+        cast<ParmVarDecl>(FTI.ArgInfo[0].Param)->getType()->isVoidType()) {
+      // Empty arg list, don't push any params.
+      ParmVarDecl *Param = cast<ParmVarDecl>(FTI.ArgInfo[0].Param);
+
+      // In C++, the empty parameter-type-list must be spelled "void"; a
+      // typedef of void is not permitted.
+      if (getLangOpts().CPlusPlus &&
+          Param->getType().getUnqualifiedType() != Context.VoidTy) {
+        bool IsTypeAlias = false;
+        if (const TypedefType *TT = Param->getType()->getAs<TypedefType>())
+          IsTypeAlias = isa<TypeAliasDecl>(TT->getDecl());
+        else if (const TemplateSpecializationType *TST =
+                   Param->getType()->getAs<TemplateSpecializationType>())
+          IsTypeAlias = TST->isTypeAlias();
+        Diag(Param->getLocation(), diag::err_param_typedef_of_void)
+          << IsTypeAlias;
+      }
+    } else if (FTI.NumArgs > 0 && FTI.ArgInfo[0].Param != 0) {
+      for (unsigned i = 0, e = FTI.NumArgs; i != e; ++i) {
+        ParmVarDecl *Param = cast<ParmVarDecl>(FTI.ArgInfo[i].Param);
+        assert(Param->getDeclContext() != NewFD && "Was set before ?");
+        Param->setDeclContext(NewFD);
+        Params.push_back(Param);
+
+        if (Param->isInvalidDecl())
+          NewFD->setInvalidDecl();
+      }
+    }
+
+  } else if (const FunctionProtoType *FT = R->getAs<FunctionProtoType>()) {
+    // When we're declaring a function with a typedef, typeof, etc as in the
+    // following example, we'll need to synthesize (unnamed)
+    // parameters for use in the declaration.
+    //
+    // @code
+    // typedef void fn(int);
+    // fn f;
+    // @endcode
+
+    // Synthesize a parameter for each argument type.
+    for (FunctionProtoType::arg_type_iterator AI = FT->arg_type_begin(),
+         AE = FT->arg_type_end(); AI != AE; ++AI) {
+      ParmVarDecl *Param =
+        BuildParmVarDeclForTypedef(NewFD, D.getIdentifierLoc(), *AI);
+      Param->setScopeInfo(0, Params.size());
+      Params.push_back(Param);
+    }
+  } else {
+    assert(R->isFunctionNoProtoType() && NewFD->getNumParams() == 0 &&
+           "Should not need args for typedef of non-prototype fn");
+  }
+
+  // Finally, we know we have the right number of parameters, install them.
+  NewFD->setParams(Params);
+
+  // Find all anonymous symbols defined during the declaration of this function
+  // and add to NewFD. This lets us track decls such 'enum Y' in:
+  //
+  //   void f(enum Y {AA} x) {}
+  //
+  // which would otherwise incorrectly end up in the translation unit scope.
+  NewFD->setDeclsInPrototypeScope(DeclsInPrototypeScope);
+  DeclsInPrototypeScope.clear();
+
+  // Process the non-inheritable attributes on this declaration.
+  ProcessDeclAttributes(S, NewFD, D,
+                        /*NonInheritable=*/true, /*Inheritable=*/false);
+
+  // Functions returning a variably modified type violate C99 6.7.5.2p2
+  // because all functions have linkage.
+  if (!NewFD->isInvalidDecl() &&
+      NewFD->getResultType()->isVariablyModifiedType()) {
+    Diag(NewFD->getLocation(), diag::err_vm_func_decl);
+    NewFD->setInvalidDecl();
+  }
+
+  if (!getLangOpts().CPlusPlus) {
+    // Perform semantic checking on the function declaration.
+    bool isExplicitSpecialization=false;
+    if (!NewFD->isInvalidDecl()) {
+      if (NewFD->isMain())
+        CheckMain(NewFD, D.getDeclSpec());
+      D.setRedeclaration(CheckFunctionDeclaration(S, NewFD, Previous,
+                                                  isExplicitSpecialization));
+    }
+    assert((NewFD->isInvalidDecl() || !D.isRedeclaration() ||
+            Previous.getResultKind() != LookupResult::FoundOverloaded) &&
+           "previous declaration set still overloaded");
+  } else {
+    // If the declarator is a template-id, translate the parser's template 
+    // argument list into our AST format.
+    bool HasExplicitTemplateArgs = false;
+    TemplateArgumentListInfo TemplateArgs;
+    if (D.getName().getKind() == UnqualifiedId::IK_TemplateId) {
+      TemplateIdAnnotation *TemplateId = D.getName().TemplateId;
+      TemplateArgs.setLAngleLoc(TemplateId->LAngleLoc);
+      TemplateArgs.setRAngleLoc(TemplateId->RAngleLoc);
+      ASTTemplateArgsPtr TemplateArgsPtr(*this,
+                                         TemplateId->getTemplateArgs(),
+                                         TemplateId->NumArgs);
+      translateTemplateArguments(TemplateArgsPtr,
+                                 TemplateArgs);
+      TemplateArgsPtr.release();
+    
+      HasExplicitTemplateArgs = true;
+    
+      if (NewFD->isInvalidDecl()) {
+        HasExplicitTemplateArgs = false;
+      } else if (FunctionTemplate) {
+        // Function template with explicit template arguments.
+        Diag(D.getIdentifierLoc(), diag::err_function_template_partial_spec)
+          << SourceRange(TemplateId->LAngleLoc, TemplateId->RAngleLoc);
+
+        HasExplicitTemplateArgs = false;
+      } else if (!isFunctionTemplateSpecialization && 
+                 !D.getDeclSpec().isFriendSpecified()) {
+        // We have encountered something that the user meant to be a 
+        // specialization (because it has explicitly-specified template
+        // arguments) but that was not introduced with a "template<>" (or had
+        // too few of them).
+        Diag(D.getIdentifierLoc(), diag::err_template_spec_needs_header)
+          << SourceRange(TemplateId->LAngleLoc, TemplateId->RAngleLoc)
+          << FixItHint::CreateInsertion(
+                                    D.getDeclSpec().getLocStart(),
+                                        "template<> ");
+        isFunctionTemplateSpecialization = true;
+      } else {
+        // "friend void foo<>(int);" is an implicit specialization decl.
+        isFunctionTemplateSpecialization = true;
+      }
+    } else if (isFriend && isFunctionTemplateSpecialization) {
+      // This combination is only possible in a recovery case;  the user
+      // wrote something like:
+      //   template <> friend void foo(int);
+      // which we're recovering from as if the user had written:
+      //   friend void foo<>(int);
+      // Go ahead and fake up a template id.
+      HasExplicitTemplateArgs = true;
+        TemplateArgs.setLAngleLoc(D.getIdentifierLoc());
+      TemplateArgs.setRAngleLoc(D.getIdentifierLoc());
+    }
+
+    // If it's a friend (and only if it's a friend), it's possible
+    // that either the specialized function type or the specialized
+    // template is dependent, and therefore matching will fail.  In
+    // this case, don't check the specialization yet.
+    bool InstantiationDependent = false;
+    if (isFunctionTemplateSpecialization && isFriend &&
+        (NewFD->getType()->isDependentType() || DC->isDependentContext() ||
+         TemplateSpecializationType::anyDependentTemplateArguments(
+            TemplateArgs.getArgumentArray(), TemplateArgs.size(),
+            InstantiationDependent))) {
+      assert(HasExplicitTemplateArgs &&
+             "friend function specialization without template args");
+      if (CheckDependentFunctionTemplateSpecialization(NewFD, TemplateArgs,
+                                                       Previous))
+        NewFD->setInvalidDecl();
+    } else if (isFunctionTemplateSpecialization) {
+      if (CurContext->isDependentContext() && CurContext->isRecord() 
+          && !isFriend) {
+        isDependentClassScopeExplicitSpecialization = true;
+        Diag(NewFD->getLocation(), getLangOpts().MicrosoftExt ? 
+          diag::ext_function_specialization_in_class :
+          diag::err_function_specialization_in_class)
+          << NewFD->getDeclName();
+      } else if (CheckFunctionTemplateSpecialization(NewFD,
+                                  (HasExplicitTemplateArgs ? &TemplateArgs : 0),
+                                                     Previous))
+        NewFD->setInvalidDecl();
+      
+      // C++ [dcl.stc]p1:
+      //   A storage-class-specifier shall not be specified in an explicit
+      //   specialization (14.7.3)
+      if (SC != SC_None) {
+        if (SC != NewFD->getStorageClass())
+          Diag(NewFD->getLocation(),
+               diag::err_explicit_specialization_inconsistent_storage_class)
+            << SC
+            << FixItHint::CreateRemoval(
+                                      D.getDeclSpec().getStorageClassSpecLoc());
+            
+        else
+          Diag(NewFD->getLocation(), 
+               diag::ext_explicit_specialization_storage_class)
+            << FixItHint::CreateRemoval(
+                                      D.getDeclSpec().getStorageClassSpecLoc());
+      }
+      
+    } else if (isExplicitSpecialization && isa<CXXMethodDecl>(NewFD)) {
+      if (CheckMemberSpecialization(NewFD, Previous))
+          NewFD->setInvalidDecl();
+    }
+
+    // Perform semantic checking on the function declaration.
+    if (!isDependentClassScopeExplicitSpecialization) {
+      if (NewFD->isInvalidDecl()) {
+        // If this is a class member, mark the class invalid immediately.
+        // This avoids some consistency errors later.
+        if (CXXMethodDecl* methodDecl = dyn_cast<CXXMethodDecl>(NewFD))
+          methodDecl->getParent()->setInvalidDecl();
+      } else {
+        if (NewFD->isMain()) 
+          CheckMain(NewFD, D.getDeclSpec());
+        D.setRedeclaration(CheckFunctionDeclaration(S, NewFD, Previous,
+                                                    isExplicitSpecialization));
+      }
+    }
+
+    assert((NewFD->isInvalidDecl() || !D.isRedeclaration() ||
+            Previous.getResultKind() != LookupResult::FoundOverloaded) &&
+           "previous declaration set still overloaded");
+
+    NamedDecl *PrincipalDecl = (FunctionTemplate
+                                ? cast<NamedDecl>(FunctionTemplate)
+                                : NewFD);
+
+    if (isFriend && D.isRedeclaration()) {
+      AccessSpecifier Access = AS_public;
+      if (!NewFD->isInvalidDecl())
+        Access = NewFD->getPreviousDecl()->getAccess();
+
+      NewFD->setAccess(Access);
+      if (FunctionTemplate) FunctionTemplate->setAccess(Access);
+
+      PrincipalDecl->setObjectOfFriendDecl(true);
+    }
+
+    if (NewFD->isOverloadedOperator() && !DC->isRecord() &&
+        PrincipalDecl->isInIdentifierNamespace(Decl::IDNS_Ordinary))
+      PrincipalDecl->setNonMemberOperator();
+
+    // If we have a function template, check the template parameter
+    // list. This will check and merge default template arguments.
+    if (FunctionTemplate) {
+      FunctionTemplateDecl *PrevTemplate = 
+                                     FunctionTemplate->getPreviousDecl();
+      CheckTemplateParameterList(FunctionTemplate->getTemplateParameters(),
+                       PrevTemplate ? PrevTemplate->getTemplateParameters() : 0,
+                            D.getDeclSpec().isFriendSpecified()
+                              ? (D.isFunctionDefinition()
+                                   ? TPC_FriendFunctionTemplateDefinition
+                                   : TPC_FriendFunctionTemplate)
+                              : (D.getCXXScopeSpec().isSet() && 
+                                 DC && DC->isRecord() && 
+                                 DC->isDependentContext())
+                                  ? TPC_ClassTemplateMember
+                                  : TPC_FunctionTemplate);
+    }
+
+    if (NewFD->isInvalidDecl()) {
+      // Ignore all the rest of this.
+    } else if (!D.isRedeclaration()) {
+      struct ActOnFDArgs ExtraArgs = { S, D, TemplateParamLists,
+                                       AddToScope };
+      // Fake up an access specifier if it's supposed to be a class member.
+      if (isa<CXXRecordDecl>(NewFD->getDeclContext()))
+        NewFD->setAccess(AS_public);
+
+      // Qualified decls generally require a previous declaration.
+      if (D.getCXXScopeSpec().isSet()) {
+        // ...with the major exception of templated-scope or
+        // dependent-scope friend declarations.
+
+        // TODO: we currently also suppress this check in dependent
+        // contexts because (1) the parameter depth will be off when
+        // matching friend templates and (2) we might actually be
+        // selecting a friend based on a dependent factor.  But there
+        // are situations where these conditions don't apply and we
+        // can actually do this check immediately.
+        if (isFriend &&
+            (TemplateParamLists.size() ||
+             D.getCXXScopeSpec().getScopeRep()->isDependent() ||
+             CurContext->isDependentContext())) {
+          // ignore these
+        } else {
+          // The user tried to provide an out-of-line definition for a
+          // function that is a member of a class or namespace, but there
+          // was no such member function declared (C++ [class.mfct]p2,
+          // C++ [namespace.memdef]p2). For example:
+          //
+          // class X {
+          //   void f() const;
+          // };
+          //
+          // void X::f() { } // ill-formed
+          //
+          // Complain about this problem, and attempt to suggest close
+          // matches (e.g., those that differ only in cv-qualifiers and
+          // whether the parameter types are references).
+
+          if (NamedDecl *Result = DiagnoseInvalidRedeclaration(*this, Previous,
+                                                               NewFD,
+                                                               ExtraArgs)) {
+            AddToScope = ExtraArgs.AddToScope;
+            return Result;
+          }
+        }
+
+        // Unqualified local friend declarations are required to resolve
+        // to something.
+      } else if (isFriend && cast<CXXRecordDecl>(CurContext)->isLocalClass()) {
+        if (NamedDecl *Result = DiagnoseInvalidRedeclaration(*this, Previous,
+                                                             NewFD,
+                                                             ExtraArgs)) {
+          AddToScope = ExtraArgs.AddToScope;
+          return Result;
+        }
+      }
+
+    } else if (!D.isFunctionDefinition() && D.getCXXScopeSpec().isSet() &&
+               !isFriend && !isFunctionTemplateSpecialization &&
+               !isExplicitSpecialization) {
+      // An out-of-line member function declaration must also be a
+      // definition (C++ [dcl.meaning]p1).
+      // Note that this is not the case for explicit specializations of
+      // function templates or member functions of class templates, per
+      // C++ [temp.expl.spec]p2. We also allow these declarations as an 
+      // extension for compatibility with old SWIG code which likes to 
+      // generate them.
+      Diag(NewFD->getLocation(), diag::ext_out_of_line_declaration)
+        << D.getCXXScopeSpec().getRange();
+    }
+  }
+ 
+ 
+  // Handle attributes. We need to have merged decls when handling attributes
+  // (for example to check for conflicts, etc).
+  // FIXME: This needs to happen before we merge declarations. Then,
+  // let attribute merging cope with attribute conflicts.
+  ProcessDeclAttributes(S, NewFD, D,
+                        /*NonInheritable=*/false, /*Inheritable=*/true);
+
+  // attributes declared post-definition are currently ignored
+  // FIXME: This should happen during attribute merging
+  if (D.isRedeclaration() && Previous.isSingleResult()) {
+    const FunctionDecl *Def;
+    FunctionDecl *PrevFD = dyn_cast<FunctionDecl>(Previous.getFoundDecl());
+    if (PrevFD && PrevFD->isDefined(Def) && D.hasAttributes()) {
+      Diag(NewFD->getLocation(), diag::warn_attribute_precede_definition);
+      Diag(Def->getLocation(), diag::note_previous_definition);
+    }
+  }
+
+  AddKnownFunctionAttributes(NewFD);
+
+  if (NewFD->hasAttr<OverloadableAttr>() && 
+      !NewFD->getType()->getAs<FunctionProtoType>()) {
+    Diag(NewFD->getLocation(),
+         diag::err_attribute_overloadable_no_prototype)
+      << NewFD;
+
+    // Turn this into a variadic function with no parameters.
+    const FunctionType *FT = NewFD->getType()->getAs<FunctionType>();
+    FunctionProtoType::ExtProtoInfo EPI;
+    EPI.Variadic = true;
+    EPI.ExtInfo = FT->getExtInfo();
+
+    QualType R = Context.getFunctionType(FT->getResultType(), 0, 0, EPI);
+    NewFD->setType(R);
+  }
+
+  // If there's a #pragma GCC visibility in scope, and this isn't a class
+  // member, set the visibility of this function.
+  if (NewFD->getLinkage() == ExternalLinkage && !DC->isRecord())
+    AddPushedVisibilityAttribute(NewFD);
+
+  // If there's a #pragma clang arc_cf_code_audited in scope, consider
+  // marking the function.
+  AddCFAuditedAttribute(NewFD);
+
+  // If this is a locally-scoped extern C function, update the
+  // map of such names.
+  if (CurContext->isFunctionOrMethod() && NewFD->isExternC()
+      && !NewFD->isInvalidDecl())
+    RegisterLocallyScopedExternCDecl(NewFD, Previous, S);
+
+  // Set this FunctionDecl's range up to the right paren.
+  NewFD->setRangeEnd(D.getSourceRange().getEnd());
+
+  if (getLangOpts().CPlusPlus) {
+    if (FunctionTemplate) {
+      if (NewFD->isInvalidDecl())
+        FunctionTemplate->setInvalidDecl();
+      return FunctionTemplate;
+    }
+  }
+
+  MarkUnusedFileScopedDecl(NewFD);
+
+  if (getLangOpts().CUDA)
+    if (IdentifierInfo *II = NewFD->getIdentifier())
+      if (!NewFD->isInvalidDecl() &&
+          NewFD->getDeclContext()->getRedeclContext()->isTranslationUnit()) {
+        if (II->isStr("cudaConfigureCall")) {
+          if (!R->getAs<FunctionType>()->getResultType()->isScalarType())
+            Diag(NewFD->getLocation(), diag::err_config_scalar_return);
+
+          Context.setcudaConfigureCallDecl(NewFD);
+        }
+      }
+  
+  // Here we have an function template explicit specialization at class scope.
+  // The actually specialization will be postponed to template instatiation
+  // time via the ClassScopeFunctionSpecializationDecl node.
+  if (isDependentClassScopeExplicitSpecialization) {
+    ClassScopeFunctionSpecializationDecl *NewSpec =
+                         ClassScopeFunctionSpecializationDecl::Create(
+                                Context, CurContext,  SourceLocation(), 
+                                cast<CXXMethodDecl>(NewFD));
+    CurContext->addDecl(NewSpec);
+    AddToScope = false;
+  }
+
+  return NewFD;
+}
+
+/// \brief Perform semantic checking of a new function declaration.
+///
+/// Performs semantic analysis of the new function declaration
+/// NewFD. This routine performs all semantic checking that does not
+/// require the actual declarator involved in the declaration, and is
+/// used both for the declaration of functions as they are parsed
+/// (called via ActOnDeclarator) and for the declaration of functions
+/// that have been instantiated via C++ template instantiation (called
+/// via InstantiateDecl).
+///
+/// \param IsExplicitSpecialiation whether this new function declaration is
+/// an explicit specialization of the previous declaration.
+///
+/// This sets NewFD->isInvalidDecl() to true if there was an error.
+///
+/// Returns true if the function declaration is a redeclaration.
+bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD,
+                                    LookupResult &Previous,
+                                    bool IsExplicitSpecialization) {
+  assert(!NewFD->getResultType()->isVariablyModifiedType() 
+         && "Variably modified return types are not handled here");
+
+  // Check for a previous declaration of this name.
+  if (Previous.empty() && NewFD->isExternC()) {
+    // Since we did not find anything by this name and we're declaring
+    // an extern "C" function, look for a non-visible extern "C"
+    // declaration with the same name.
+    llvm::DenseMap<DeclarationName, NamedDecl *>::iterator Pos
+      = findLocallyScopedExternalDecl(NewFD->getDeclName());
+    if (Pos != LocallyScopedExternalDecls.end())
+      Previous.addDecl(Pos->second);
+  }
+
+  bool Redeclaration = false;
+
+  // Merge or overload the declaration with an existing declaration of
+  // the same name, if appropriate.
+  if (!Previous.empty()) {
+    // Determine whether NewFD is an overload of PrevDecl or
+    // a declaration that requires merging. If it's an overload,
+    // there's no more work to do here; we'll just add the new
+    // function to the scope.
+
+    NamedDecl *OldDecl = 0;
+    if (!AllowOverloadingOfFunction(Previous, Context)) {
+      Redeclaration = true;
+      OldDecl = Previous.getFoundDecl();
+    } else {
+      switch (CheckOverload(S, NewFD, Previous, OldDecl,
+                            /*NewIsUsingDecl*/ false)) {
+      case Ovl_Match:
+        Redeclaration = true;
+        break;
+
+      case Ovl_NonFunction:
+        Redeclaration = true;
+        break;
+
+      case Ovl_Overload:
+        Redeclaration = false;
+        break;
+      }
+
+      if (!getLangOpts().CPlusPlus && !NewFD->hasAttr<OverloadableAttr>()) {
+        // If a function name is overloadable in C, then every function
+        // with that name must be marked "overloadable".
+        Diag(NewFD->getLocation(), diag::err_attribute_overloadable_missing)
+          << Redeclaration << NewFD;
+        NamedDecl *OverloadedDecl = 0;
+        if (Redeclaration)
+          OverloadedDecl = OldDecl;
+        else if (!Previous.empty())
+          OverloadedDecl = Previous.getRepresentativeDecl();
+        if (OverloadedDecl)
+          Diag(OverloadedDecl->getLocation(),
+               diag::note_attribute_overloadable_prev_overload);
+        NewFD->addAttr(::new (Context) OverloadableAttr(SourceLocation(),
+                                                        Context));
+      }
+    }
+
+    if (Redeclaration) {
+      // NewFD and OldDecl represent declarations that need to be
+      // merged.
+      if (MergeFunctionDecl(NewFD, OldDecl, S)) {
+        NewFD->setInvalidDecl();
+        return Redeclaration;
+      }
+
+      Previous.clear();
+      Previous.addDecl(OldDecl);
+
+      if (FunctionTemplateDecl *OldTemplateDecl
+                                    = dyn_cast<FunctionTemplateDecl>(OldDecl)) {
+        NewFD->setPreviousDeclaration(OldTemplateDecl->getTemplatedDecl());
+        FunctionTemplateDecl *NewTemplateDecl
+          = NewFD->getDescribedFunctionTemplate();
+        assert(NewTemplateDecl && "Template/non-template mismatch");
+        if (CXXMethodDecl *Method 
+              = dyn_cast<CXXMethodDecl>(NewTemplateDecl->getTemplatedDecl())) {
+          Method->setAccess(OldTemplateDecl->getAccess());
+          NewTemplateDecl->setAccess(OldTemplateDecl->getAccess());
+        }
+        
+        // If this is an explicit specialization of a member that is a function
+        // template, mark it as a member specialization.
+        if (IsExplicitSpecialization && 
+            NewTemplateDecl->getInstantiatedFromMemberTemplate()) {
+          NewTemplateDecl->setMemberSpecialization();
+          assert(OldTemplateDecl->isMemberSpecialization());
+        }
+        
+      } else {
+        if (isa<CXXMethodDecl>(NewFD)) // Set access for out-of-line definitions
+          NewFD->setAccess(OldDecl->getAccess());
+        NewFD->setPreviousDeclaration(cast<FunctionDecl>(OldDecl));
+      }
+    }
+  }
+
+  // Semantic checking for this function declaration (in isolation).
+  if (getLangOpts().CPlusPlus) {
+    // C++-specific checks.
+    if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(NewFD)) {
+      CheckConstructor(Constructor);
+    } else if (CXXDestructorDecl *Destructor = 
+                dyn_cast<CXXDestructorDecl>(NewFD)) {
+      CXXRecordDecl *Record = Destructor->getParent();
+      QualType ClassType = Context.getTypeDeclType(Record);
+      
+      // FIXME: Shouldn't we be able to perform this check even when the class
+      // type is dependent? Both gcc and edg can handle that.
+      if (!ClassType->isDependentType()) {
+        DeclarationName Name
+          = Context.DeclarationNames.getCXXDestructorName(
+                                        Context.getCanonicalType(ClassType));
+        if (NewFD->getDeclName() != Name) {
+          Diag(NewFD->getLocation(), diag::err_destructor_name);
+          NewFD->setInvalidDecl();
+          return Redeclaration;
+        }
+      }
+    } else if (CXXConversionDecl *Conversion
+               = dyn_cast<CXXConversionDecl>(NewFD)) {
+      ActOnConversionDeclarator(Conversion);
+    }
+
+    // Find any virtual functions that this function overrides.
+    if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(NewFD)) {
+      if (!Method->isFunctionTemplateSpecialization() && 
+          !Method->getDescribedFunctionTemplate()) {
+        if (AddOverriddenMethods(Method->getParent(), Method)) {
+          // If the function was marked as "static", we have a problem.
+          if (NewFD->getStorageClass() == SC_Static) {
+            Diag(NewFD->getLocation(), diag::err_static_overrides_virtual)
+              << NewFD->getDeclName();
+            for (CXXMethodDecl::method_iterator 
+                      Overridden = Method->begin_overridden_methods(),
+                   OverriddenEnd = Method->end_overridden_methods();
+                 Overridden != OverriddenEnd;
+                 ++Overridden) {
+              Diag((*Overridden)->getLocation(), 
+                   diag::note_overridden_virtual_function);
+            }
+          }
+        }
+      }
+      
+      if (Method->isStatic())
+        checkThisInStaticMemberFunctionType(Method);
+    }
+
+    // Extra checking for C++ overloaded operators (C++ [over.oper]).
+    if (NewFD->isOverloadedOperator() &&
+        CheckOverloadedOperatorDeclaration(NewFD)) {
+      NewFD->setInvalidDecl();
+      return Redeclaration;
+    }
+
+    // Extra checking for C++0x literal operators (C++0x [over.literal]).
+    if (NewFD->getLiteralIdentifier() &&
+        CheckLiteralOperatorDeclaration(NewFD)) {
+      NewFD->setInvalidDecl();
+      return Redeclaration;
+    }
+
+    // In C++, check default arguments now that we have merged decls. Unless
+    // the lexical context is the class, because in this case this is done
+    // during delayed parsing anyway.
+    if (!CurContext->isRecord())
+      CheckCXXDefaultArguments(NewFD);
+    
+    // If this function declares a builtin function, check the type of this
+    // declaration against the expected type for the builtin. 
+    if (unsigned BuiltinID = NewFD->getBuiltinID()) {
+      ASTContext::GetBuiltinTypeError Error;
+      QualType T = Context.GetBuiltinType(BuiltinID, Error);
+      if (!T.isNull() && !Context.hasSameType(T, NewFD->getType())) {
+        // The type of this function differs from the type of the builtin,
+        // so forget about the builtin entirely.
+        Context.BuiltinInfo.ForgetBuiltin(BuiltinID, Context.Idents);
+      }
+    }
+  
+    // If this function is declared as being extern "C", then check to see if 
+    // the function returns a UDT (class, struct, or union type) that is not C
+    // compatible, and if it does, warn the user.
+    if (NewFD->isExternC()) {
+      QualType R = NewFD->getResultType();
+      if (!R.isPODType(Context) && 
+          !R->isVoidType())
+        Diag( NewFD->getLocation(), diag::warn_return_value_udt ) 
+          << NewFD << R;
+    }
+  }
+  return Redeclaration;
+}
+
+void Sema::CheckMain(FunctionDecl* FD, const DeclSpec& DS) {
+  // C++11 [basic.start.main]p3:  A program that declares main to be inline,
+  //   static or constexpr is ill-formed.
+  // C99 6.7.4p4:  In a hosted environment, the inline function specifier
+  //   shall not appear in a declaration of main.
+  // static main is not an error under C99, but we should warn about it.
+  if (FD->getStorageClass() == SC_Static)
+    Diag(DS.getStorageClassSpecLoc(), getLangOpts().CPlusPlus 
+         ? diag::err_static_main : diag::warn_static_main) 
+      << FixItHint::CreateRemoval(DS.getStorageClassSpecLoc());
+  if (FD->isInlineSpecified())
+    Diag(DS.getInlineSpecLoc(), diag::err_inline_main) 
+      << FixItHint::CreateRemoval(DS.getInlineSpecLoc());
+  if (FD->isConstexpr()) {
+    Diag(DS.getConstexprSpecLoc(), diag::err_constexpr_main)
+      << FixItHint::CreateRemoval(DS.getConstexprSpecLoc());
+    FD->setConstexpr(false);
+  }
+
+  QualType T = FD->getType();
+  assert(T->isFunctionType() && "function decl is not of function type");
+  const FunctionType* FT = T->castAs<FunctionType>();
+
+  // All the standards say that main() should should return 'int'.
+  if (Context.hasSameUnqualifiedType(FT->getResultType(), Context.IntTy)) {
+    // In C and C++, main magically returns 0 if you fall off the end;
+    // set the flag which tells us that.
+    // This is C++ [basic.start.main]p5 and C99 5.1.2.2.3.
+    FD->setHasImplicitReturnZero(true);
+
+  // In C with GNU extensions we allow main() to have non-integer return
+  // type, but we should warn about the extension, and we disable the
+  // implicit-return-zero rule.
+  } else if (getLangOpts().GNUMode && !getLangOpts().CPlusPlus) {
+    Diag(FD->getTypeSpecStartLoc(), diag::ext_main_returns_nonint);
+
+  // Otherwise, this is just a flat-out error.
+  } else {
+    Diag(FD->getTypeSpecStartLoc(), diag::err_main_returns_nonint);
+    FD->setInvalidDecl(true);
+  }
+
+  // Treat protoless main() as nullary.
+  if (isa<FunctionNoProtoType>(FT)) return;
+
+  const FunctionProtoType* FTP = cast<const FunctionProtoType>(FT);
+  unsigned nparams = FTP->getNumArgs();
+  assert(FD->getNumParams() == nparams);
+
+  bool HasExtraParameters = (nparams > 3);
+
+  // Darwin passes an undocumented fourth argument of type char**.  If
+  // other platforms start sprouting these, the logic below will start
+  // getting shifty.
+  if (nparams == 4 && Context.getTargetInfo().getTriple().isOSDarwin())
+    HasExtraParameters = false;
+
+  if (HasExtraParameters) {
+    Diag(FD->getLocation(), diag::err_main_surplus_args) << nparams;
+    FD->setInvalidDecl(true);
+    nparams = 3;
+  }
+
+  // FIXME: a lot of the following diagnostics would be improved
+  // if we had some location information about types.
+
+  QualType CharPP =
+    Context.getPointerType(Context.getPointerType(Context.CharTy));
+  QualType Expected[] = { Context.IntTy, CharPP, CharPP, CharPP };
+
+  for (unsigned i = 0; i < nparams; ++i) {
+    QualType AT = FTP->getArgType(i);
+
+    bool mismatch = true;
+
+    if (Context.hasSameUnqualifiedType(AT, Expected[i]))
+      mismatch = false;
+    else if (Expected[i] == CharPP) {
+      // As an extension, the following forms are okay:
+      //   char const **
+      //   char const * const *
+      //   char * const *
+
+      QualifierCollector qs;
+      const PointerType* PT;
+      if ((PT = qs.strip(AT)->getAs<PointerType>()) &&
+          (PT = qs.strip(PT->getPointeeType())->getAs<PointerType>()) &&
+          (QualType(qs.strip(PT->getPointeeType()), 0) == Context.CharTy)) {
+        qs.removeConst();
+        mismatch = !qs.empty();
+      }
+    }
+
+    if (mismatch) {
+      Diag(FD->getLocation(), diag::err_main_arg_wrong) << i << Expected[i];
+      // TODO: suggest replacing given type with expected type
+      FD->setInvalidDecl(true);
+    }
+  }
+
+  if (nparams == 1 && !FD->isInvalidDecl()) {
+    Diag(FD->getLocation(), diag::warn_main_one_arg);
+  }
+  
+  if (!FD->isInvalidDecl() && FD->getDescribedFunctionTemplate()) {
+    Diag(FD->getLocation(), diag::err_main_template_decl);
+    FD->setInvalidDecl();
+  }
+}
+
+bool Sema::CheckForConstantInitializer(Expr *Init, QualType DclT) {
+  // FIXME: Need strict checking.  In C89, we need to check for
+  // any assignment, increment, decrement, function-calls, or
+  // commas outside of a sizeof.  In C99, it's the same list,
+  // except that the aforementioned are allowed in unevaluated
+  // expressions.  Everything else falls under the
+  // "may accept other forms of constant expressions" exception.
+  // (We never end up here for C++, so the constant expression
+  // rules there don't matter.)
+  if (Init->isConstantInitializer(Context, false))
+    return false;
+  Diag(Init->getExprLoc(), diag::err_init_element_not_constant)
+    << Init->getSourceRange();
+  return true;
+}
+
+namespace {
+  // Visits an initialization expression to see if OrigDecl is evaluated in
+  // its own initialization and throws a warning if it does.
+  class SelfReferenceChecker
+      : public EvaluatedExprVisitor<SelfReferenceChecker> {
+    Sema &S;
+    Decl *OrigDecl;
+    bool isRecordType;
+    bool isPODType;
+
+  public:
+    typedef EvaluatedExprVisitor<SelfReferenceChecker> Inherited;
+
+    SelfReferenceChecker(Sema &S, Decl *OrigDecl) : Inherited(S.Context),
+                                                    S(S), OrigDecl(OrigDecl) {
+      isPODType = false;
+      isRecordType = false;
+      if (ValueDecl *VD = dyn_cast<ValueDecl>(OrigDecl)) {
+        isPODType = VD->getType().isPODType(S.Context);
+        isRecordType = VD->getType()->isRecordType();
+      }
+    }
+
+    void VisitExpr(Expr *E) {
+      if (isa<ObjCMessageExpr>(*E)) return;
+      if (isRecordType) {
+        Expr *expr = E;
+        if (MemberExpr *ME = dyn_cast<MemberExpr>(E)) {
+          ValueDecl *VD = ME->getMemberDecl();
+          if (isa<EnumConstantDecl>(VD) || isa<VarDecl>(VD)) return;
+          expr = ME->getBase();
+        }
+        if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(expr)) {
+          HandleDeclRefExpr(DRE);
+          return;
+        }
+      }
+      Inherited::VisitExpr(E);
+    }
+
+    void VisitMemberExpr(MemberExpr *E) {
+      if (E->getType()->canDecayToPointerType()) return;
+      ValueDecl *VD = E->getMemberDecl();
+      if (isa<FieldDecl>(VD) || isa<CXXMethodDecl>(VD))
+        if (DeclRefExpr *DRE
+              = dyn_cast<DeclRefExpr>(E->getBase()->IgnoreParenImpCasts())) {
+          HandleDeclRefExpr(DRE);
+          return;
+        }
+      Inherited::VisitMemberExpr(E);
+    }
+
+    void VisitImplicitCastExpr(ImplicitCastExpr *E) {
+      if ((!isRecordType &&E->getCastKind() == CK_LValueToRValue) ||
+          (isRecordType && E->getCastKind() == CK_NoOp)) {
+        Expr* SubExpr = E->getSubExpr()->IgnoreParenImpCasts();
+        if (MemberExpr *ME = dyn_cast<MemberExpr>(SubExpr))
+          SubExpr = ME->getBase()->IgnoreParenImpCasts();
+        if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(SubExpr)) {
+          HandleDeclRefExpr(DRE);
+          return;
+        }
+      }
+      Inherited::VisitImplicitCastExpr(E);
+    }
+
+    void VisitUnaryOperator(UnaryOperator *E) {
+      // For POD record types, addresses of its own members are well-defined.
+      if (isRecordType && isPODType) return;
+      Inherited::VisitUnaryOperator(E);
+    } 
+    
+    void HandleDeclRefExpr(DeclRefExpr *DRE) {
+      Decl* ReferenceDecl = DRE->getDecl(); 
+      if (OrigDecl != ReferenceDecl) return;
+      LookupResult Result(S, DRE->getNameInfo(), Sema::LookupOrdinaryName,
+                          Sema::NotForRedeclaration);
+      S.DiagRuntimeBehavior(DRE->getLocStart(), DRE,
+                            S.PDiag(diag::warn_uninit_self_reference_in_init)
+                              << Result.getLookupName()
+                              << OrigDecl->getLocation()
+                              << DRE->getSourceRange());
+    }
+  };
+}
+
+/// CheckSelfReference - Warns if OrigDecl is used in expression E.
+void Sema::CheckSelfReference(Decl* OrigDecl, Expr *E) {
+  SelfReferenceChecker(*this, OrigDecl).VisitExpr(E);
+}
+
+/// AddInitializerToDecl - Adds the initializer Init to the
+/// declaration dcl. If DirectInit is true, this is C++ direct
+/// initialization rather than copy initialization.
+void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init,
+                                bool DirectInit, bool TypeMayContainAuto) {
+  // If there is no declaration, there was an error parsing it.  Just ignore
+  // the initializer.
+  if (RealDecl == 0 || RealDecl->isInvalidDecl())
+    return;
+
+  if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(RealDecl)) {
+    // With declarators parsed the way they are, the parser cannot
+    // distinguish between a normal initializer and a pure-specifier.
+    // Thus this grotesque test.
+    IntegerLiteral *IL;
+    if ((IL = dyn_cast<IntegerLiteral>(Init)) && IL->getValue() == 0 &&
+        Context.getCanonicalType(IL->getType()) == Context.IntTy)
+      CheckPureMethod(Method, Init->getSourceRange());
+    else {
+      Diag(Method->getLocation(), diag::err_member_function_initialization)
+        << Method->getDeclName() << Init->getSourceRange();
+      Method->setInvalidDecl();
+    }
+    return;
+  }
+
+  VarDecl *VDecl = dyn_cast<VarDecl>(RealDecl);
+  if (!VDecl) {
+    assert(!isa<FieldDecl>(RealDecl) && "field init shouldn't get here");
+    Diag(RealDecl->getLocation(), diag::err_illegal_initializer);
+    RealDecl->setInvalidDecl();
+    return;
+  }
+
+  // Check for self-references within variable initializers.
+  // Variables declared within a function/method body are handled
+  // by a dataflow analysis.
+  if (!VDecl->hasLocalStorage() && !VDecl->isStaticLocal())
+    CheckSelfReference(RealDecl, Init);
+
+  ParenListExpr *CXXDirectInit = dyn_cast<ParenListExpr>(Init);
+
+  // C++11 [decl.spec.auto]p6. Deduce the type which 'auto' stands in for.
+  if (TypeMayContainAuto && VDecl->getType()->getContainedAutoType()) {
+    Expr *DeduceInit = Init;
+    // Initializer could be a C++ direct-initializer. Deduction only works if it
+    // contains exactly one expression.
+    if (CXXDirectInit) {
+      if (CXXDirectInit->getNumExprs() == 0) {
+        // It isn't possible to write this directly, but it is possible to
+        // end up in this situation with "auto x(some_pack...);"
+        Diag(CXXDirectInit->getLocStart(),
+             diag::err_auto_var_init_no_expression)
+          << VDecl->getDeclName() << VDecl->getType()
+          << VDecl->getSourceRange();
+        RealDecl->setInvalidDecl();
+        return;
+      } else if (CXXDirectInit->getNumExprs() > 1) {
+        Diag(CXXDirectInit->getExpr(1)->getLocStart(),
+             diag::err_auto_var_init_multiple_expressions)
+          << VDecl->getDeclName() << VDecl->getType()
+          << VDecl->getSourceRange();
+        RealDecl->setInvalidDecl();
+        return;
+      } else {
+        DeduceInit = CXXDirectInit->getExpr(0);
+      }
+    }
+    TypeSourceInfo *DeducedType = 0;
+    if (DeduceAutoType(VDecl->getTypeSourceInfo(), DeduceInit, DeducedType) ==
+            DAR_Failed)
+      DiagnoseAutoDeductionFailure(VDecl, DeduceInit);
+    if (!DeducedType) {
+      RealDecl->setInvalidDecl();
+      return;
+    }
+    VDecl->setTypeSourceInfo(DeducedType);
+    VDecl->setType(DeducedType->getType());
+    VDecl->ClearLinkageCache();
+    
+    // In ARC, infer lifetime.
+    if (getLangOpts().ObjCAutoRefCount && inferObjCARCLifetime(VDecl))
+      VDecl->setInvalidDecl();
+
+    // If this is a redeclaration, check that the type we just deduced matches
+    // the previously declared type.
+    if (VarDecl *Old = VDecl->getPreviousDecl())
+      MergeVarDeclTypes(VDecl, Old);
+  }
+
+  if (VDecl->isLocalVarDecl() && VDecl->hasExternalStorage()) {
+    // C99 6.7.8p5. C++ has no such restriction, but that is a defect.
+    Diag(VDecl->getLocation(), diag::err_block_extern_cant_init);
+    VDecl->setInvalidDecl();
+    return;
+  }
+
+  if (!VDecl->getType()->isDependentType()) {
+    // A definition must end up with a complete type, which means it must be
+    // complete with the restriction that an array type might be completed by
+    // the initializer; note that later code assumes this restriction.
+    QualType BaseDeclType = VDecl->getType();
+    if (const ArrayType *Array = Context.getAsIncompleteArrayType(BaseDeclType))
+      BaseDeclType = Array->getElementType();
+    if (RequireCompleteType(VDecl->getLocation(), BaseDeclType,
+                            diag::err_typecheck_decl_incomplete_type)) {
+      RealDecl->setInvalidDecl();
+      return;
+    }
+
+    // The variable can not have an abstract class type.
+    if (RequireNonAbstractType(VDecl->getLocation(), VDecl->getType(),
+                               diag::err_abstract_type_in_decl,
+                               AbstractVariableType))
+      VDecl->setInvalidDecl();
+  }
+
+  const VarDecl *Def;
+  if ((Def = VDecl->getDefinition()) && Def != VDecl) {
+    Diag(VDecl->getLocation(), diag::err_redefinition)
+      << VDecl->getDeclName();
+    Diag(Def->getLocation(), diag::note_previous_definition);
+    VDecl->setInvalidDecl();
+    return;
+  }
+  
+  const VarDecl* PrevInit = 0;
+  if (getLangOpts().CPlusPlus) {
+    // C++ [class.static.data]p4
+    //   If a static data member is of const integral or const
+    //   enumeration type, its declaration in the class definition can
+    //   specify a constant-initializer which shall be an integral
+    //   constant expression (5.19). In that case, the member can appear
+    //   in integral constant expressions. The member shall still be
+    //   defined in a namespace scope if it is used in the program and the
+    //   namespace scope definition shall not contain an initializer.
+    //
+    // We already performed a redefinition check above, but for static
+    // data members we also need to check whether there was an in-class
+    // declaration with an initializer.
+    if (VDecl->isStaticDataMember() && VDecl->getAnyInitializer(PrevInit)) {
+      Diag(VDecl->getLocation(), diag::err_redefinition) 
+        << VDecl->getDeclName();
+      Diag(PrevInit->getLocation(), diag::note_previous_definition);
+      return;
+    }  
+
+    if (VDecl->hasLocalStorage())
+      getCurFunction()->setHasBranchProtectedScope();
+
+    if (DiagnoseUnexpandedParameterPack(Init, UPPC_Initializer)) {
+      VDecl->setInvalidDecl();
+      return;
+    }
+  }
+
+  // OpenCL 1.1 6.5.2: "Variables allocated in the __local address space inside
+  // a kernel function cannot be initialized."
+  if (VDecl->getStorageClass() == SC_OpenCLWorkGroupLocal) {
+    Diag(VDecl->getLocation(), diag::err_local_cant_init);
+    VDecl->setInvalidDecl();
+    return;
+  }
+
+  // Get the decls type and save a reference for later, since
+  // CheckInitializerTypes may change it.
+  QualType DclT = VDecl->getType(), SavT = DclT;
+  
+  // Top-level message sends default to 'id' when we're in a debugger
+  // and we are assigning it to a variable of 'id' type.
+  if (getLangOpts().DebuggerCastResultToId && DclT->isObjCIdType())
+    if (Init->getType() == Context.UnknownAnyTy && isa<ObjCMessageExpr>(Init)) {
+      ExprResult Result = forceUnknownAnyToType(Init, Context.getObjCIdType());
+      if (Result.isInvalid()) {
+        VDecl->setInvalidDecl();
+        return;
+      }
+      Init = Result.take();
+    }
+
+  // Perform the initialization.
+  if (!VDecl->isInvalidDecl()) {
+    InitializedEntity Entity = InitializedEntity::InitializeVariable(VDecl);
+    InitializationKind Kind
+      = DirectInit ?
+          CXXDirectInit ? InitializationKind::CreateDirect(VDecl->getLocation(),
+                                                           Init->getLocStart(),
+                                                           Init->getLocEnd())
+                        : InitializationKind::CreateDirectList(
+                                                          VDecl->getLocation())
+                   : InitializationKind::CreateCopy(VDecl->getLocation(),
+                                                    Init->getLocStart());
+
+    Expr **Args = &Init;
+    unsigned NumArgs = 1;
+    if (CXXDirectInit) {
+      Args = CXXDirectInit->getExprs();
+      NumArgs = CXXDirectInit->getNumExprs();
+    }
+    InitializationSequence InitSeq(*this, Entity, Kind, Args, NumArgs);
+    ExprResult Result = InitSeq.Perform(*this, Entity, Kind,
+                                              MultiExprArg(*this, Args,NumArgs),
+                                              &DclT);
+    if (Result.isInvalid()) {
+      VDecl->setInvalidDecl();
+      return;
+    }
+
+    Init = Result.takeAs<Expr>();
+  }
+
+  // If the type changed, it means we had an incomplete type that was
+  // completed by the initializer. For example:
+  //   int ary[] = { 1, 3, 5 };
+  // "ary" transitions from an IncompleteArrayType to a ConstantArrayType.
+  if (!VDecl->isInvalidDecl() && (DclT != SavT))
+    VDecl->setType(DclT);
+
+  // Check any implicit conversions within the expression.
+  CheckImplicitConversions(Init, VDecl->getLocation());
+
+  if (!VDecl->isInvalidDecl())
+    checkUnsafeAssigns(VDecl->getLocation(), VDecl->getType(), Init);
+
+  Init = MaybeCreateExprWithCleanups(Init);
+  // Attach the initializer to the decl.
+  VDecl->setInit(Init);
+
+  if (VDecl->isLocalVarDecl()) {
+    // C99 6.7.8p4: All the expressions in an initializer for an object that has
+    // static storage duration shall be constant expressions or string literals.
+    // C++ does not have this restriction.
+    if (!getLangOpts().CPlusPlus && !VDecl->isInvalidDecl() &&
+        VDecl->getStorageClass() == SC_Static)
+      CheckForConstantInitializer(Init, DclT);
+  } else if (VDecl->isStaticDataMember() &&
+             VDecl->getLexicalDeclContext()->isRecord()) {
+    // This is an in-class initialization for a static data member, e.g.,
+    //
+    // struct S {
+    //   static const int value = 17;
+    // };
+
+    // C++ [class.mem]p4:
+    //   A member-declarator can contain a constant-initializer only
+    //   if it declares a static member (9.4) of const integral or
+    //   const enumeration type, see 9.4.2.
+    //
+    // C++11 [class.static.data]p3:
+    //   If a non-volatile const static data member is of integral or
+    //   enumeration type, its declaration in the class definition can
+    //   specify a brace-or-equal-initializer in which every initalizer-clause
+    //   that is an assignment-expression is a constant expression. A static
+    //   data member of literal type can be declared in the class definition
+    //   with the constexpr specifier; if so, its declaration shall specify a
+    //   brace-or-equal-initializer in which every initializer-clause that is
+    //   an assignment-expression is a constant expression.
+
+    // Do nothing on dependent types.
+    if (DclT->isDependentType()) {
+
+    // Allow any 'static constexpr' members, whether or not they are of literal
+    // type. We separately check that every constexpr variable is of literal
+    // type.
+    } else if (VDecl->isConstexpr()) {
+
+    // Require constness.
+    } else if (!DclT.isConstQualified()) {
+      Diag(VDecl->getLocation(), diag::err_in_class_initializer_non_const)
+        << Init->getSourceRange();
+      VDecl->setInvalidDecl();
+
+    // We allow integer constant expressions in all cases.
+    } else if (DclT->isIntegralOrEnumerationType()) {
+      // Check whether the expression is a constant expression.
+      SourceLocation Loc;
+      if (getLangOpts().CPlusPlus0x && DclT.isVolatileQualified())
+        // In C++11, a non-constexpr const static data member with an
+        // in-class initializer cannot be volatile.
+        Diag(VDecl->getLocation(), diag::err_in_class_initializer_volatile);
+      else if (Init->isValueDependent())
+        ; // Nothing to check.
+      else if (Init->isIntegerConstantExpr(Context, &Loc))
+        ; // Ok, it's an ICE!
+      else if (Init->isEvaluatable(Context)) {
+        // If we can constant fold the initializer through heroics, accept it,
+        // but report this as a use of an extension for -pedantic.
+        Diag(Loc, diag::ext_in_class_initializer_non_constant)
+          << Init->getSourceRange();
+      } else {
+        // Otherwise, this is some crazy unknown case.  Report the issue at the
+        // location provided by the isIntegerConstantExpr failed check.
+        Diag(Loc, diag::err_in_class_initializer_non_constant)
+          << Init->getSourceRange();
+        VDecl->setInvalidDecl();
+      }
+
+    // We allow foldable floating-point constants as an extension.
+    } else if (DclT->isFloatingType()) { // also permits complex, which is ok
+      Diag(VDecl->getLocation(), diag::ext_in_class_initializer_float_type)
+        << DclT << Init->getSourceRange();
+      if (getLangOpts().CPlusPlus0x)
+        Diag(VDecl->getLocation(),
+             diag::note_in_class_initializer_float_type_constexpr)
+          << FixItHint::CreateInsertion(VDecl->getLocStart(), "constexpr ");
+
+      if (!Init->isValueDependent() && !Init->isEvaluatable(Context)) {
+        Diag(Init->getExprLoc(), diag::err_in_class_initializer_non_constant)
+          << Init->getSourceRange();
+        VDecl->setInvalidDecl();
+      }
+
+    // Suggest adding 'constexpr' in C++11 for literal types.
+    } else if (getLangOpts().CPlusPlus0x && DclT->isLiteralType()) {
+      Diag(VDecl->getLocation(), diag::err_in_class_initializer_literal_type)
+        << DclT << Init->getSourceRange()
+        << FixItHint::CreateInsertion(VDecl->getLocStart(), "constexpr ");
+      VDecl->setConstexpr(true);
+
+    } else {
+      Diag(VDecl->getLocation(), diag::err_in_class_initializer_bad_type)
+        << DclT << Init->getSourceRange();
+      VDecl->setInvalidDecl();
+    }
+  } else if (VDecl->isFileVarDecl()) {
+    if (VDecl->getStorageClassAsWritten() == SC_Extern &&
+        (!getLangOpts().CPlusPlus ||
+         !Context.getBaseElementType(VDecl->getType()).isConstQualified()))
+      Diag(VDecl->getLocation(), diag::warn_extern_init);
+
+    // C99 6.7.8p4. All file scoped initializers need to be constant.
+    if (!getLangOpts().CPlusPlus && !VDecl->isInvalidDecl())
+      CheckForConstantInitializer(Init, DclT);
+  }
+
+  // We will represent direct-initialization similarly to copy-initialization:
+  //    int x(1);  -as-> int x = 1;
+  //    ClassType x(a,b,c); -as-> ClassType x = ClassType(a,b,c);
+  //
+  // Clients that want to distinguish between the two forms, can check for
+  // direct initializer using VarDecl::getInitStyle().
+  // A major benefit is that clients that don't particularly care about which
+  // exactly form was it (like the CodeGen) can handle both cases without
+  // special case code.
+
+  // C++ 8.5p11:
+  // The form of initialization (using parentheses or '=') is generally
+  // insignificant, but does matter when the entity being initialized has a
+  // class type.
+  if (CXXDirectInit) {
+    assert(DirectInit && "Call-style initializer must be direct init.");
+    VDecl->setInitStyle(VarDecl::CallInit);
+  } else if (DirectInit) {
+    // This must be list-initialization. No other way is direct-initialization.
+    VDecl->setInitStyle(VarDecl::ListInit);
+  }
+
+  CheckCompleteVariableDeclaration(VDecl);
+}
+
+/// ActOnInitializerError - Given that there was an error parsing an
+/// initializer for the given declaration, try to return to some form
+/// of sanity.
+void Sema::ActOnInitializerError(Decl *D) {
+  // Our main concern here is re-establishing invariants like "a
+  // variable's type is either dependent or complete".
+  if (!D || D->isInvalidDecl()) return;
+
+  VarDecl *VD = dyn_cast<VarDecl>(D);
+  if (!VD) return;
+
+  // Auto types are meaningless if we can't make sense of the initializer.
+  if (ParsingInitForAutoVars.count(D)) {
+    D->setInvalidDecl();
+    return;
+  }
+
+  QualType Ty = VD->getType();
+  if (Ty->isDependentType()) return;
+
+  // Require a complete type.
+  if (RequireCompleteType(VD->getLocation(), 
+                          Context.getBaseElementType(Ty),
+                          diag::err_typecheck_decl_incomplete_type)) {
+    VD->setInvalidDecl();
+    return;
+  }
+
+  // Require an abstract type.
+  if (RequireNonAbstractType(VD->getLocation(), Ty,
+                             diag::err_abstract_type_in_decl,
+                             AbstractVariableType)) {
+    VD->setInvalidDecl();
+    return;
+  }
+
+  // Don't bother complaining about constructors or destructors,
+  // though.
+}
+
+void Sema::ActOnUninitializedDecl(Decl *RealDecl,
+                                  bool TypeMayContainAuto) {
+  // If there is no declaration, there was an error parsing it. Just ignore it.
+  if (RealDecl == 0)
+    return;
+
+  if (VarDecl *Var = dyn_cast<VarDecl>(RealDecl)) {
+    QualType Type = Var->getType();
+
+    // C++11 [dcl.spec.auto]p3
+    if (TypeMayContainAuto && Type->getContainedAutoType()) {
+      Diag(Var->getLocation(), diag::err_auto_var_requires_init)
+        << Var->getDeclName() << Type;
+      Var->setInvalidDecl();
+      return;
+    }
+
+    // C++11 [class.static.data]p3: A static data member can be declared with
+    // the constexpr specifier; if so, its declaration shall specify
+    // a brace-or-equal-initializer.
+    // C++11 [dcl.constexpr]p1: The constexpr specifier shall be applied only to
+    // the definition of a variable [...] or the declaration of a static data
+    // member.
+    if (Var->isConstexpr() && !Var->isThisDeclarationADefinition()) {
+      if (Var->isStaticDataMember())
+        Diag(Var->getLocation(),
+             diag::err_constexpr_static_mem_var_requires_init)
+          << Var->getDeclName();
+      else
+        Diag(Var->getLocation(), diag::err_invalid_constexpr_var_decl);
+      Var->setInvalidDecl();
+      return;
+    }
+
+    switch (Var->isThisDeclarationADefinition()) {
+    case VarDecl::Definition:
+      if (!Var->isStaticDataMember() || !Var->getAnyInitializer())
+        break;
+
+      // We have an out-of-line definition of a static data member
+      // that has an in-class initializer, so we type-check this like
+      // a declaration. 
+      //
+      // Fall through
+      
+    case VarDecl::DeclarationOnly:
+      // It's only a declaration. 
+
+      // Block scope. C99 6.7p7: If an identifier for an object is
+      // declared with no linkage (C99 6.2.2p6), the type for the
+      // object shall be complete.
+      if (!Type->isDependentType() && Var->isLocalVarDecl() && 
+          !Var->getLinkage() && !Var->isInvalidDecl() &&
+          RequireCompleteType(Var->getLocation(), Type,
+                              diag::err_typecheck_decl_incomplete_type))
+        Var->setInvalidDecl();
+
+      // Make sure that the type is not abstract.
+      if (!Type->isDependentType() && !Var->isInvalidDecl() &&
+          RequireNonAbstractType(Var->getLocation(), Type,
+                                 diag::err_abstract_type_in_decl,
+                                 AbstractVariableType))
+        Var->setInvalidDecl();
+      return;
+
+    case VarDecl::TentativeDefinition:
+      // File scope. C99 6.9.2p2: A declaration of an identifier for an
+      // object that has file scope without an initializer, and without a
+      // storage-class specifier or with the storage-class specifier "static",
+      // constitutes a tentative definition. Note: A tentative definition with
+      // external linkage is valid (C99 6.2.2p5).
+      if (!Var->isInvalidDecl()) {
+        if (const IncompleteArrayType *ArrayT
+                                    = Context.getAsIncompleteArrayType(Type)) {
+          if (RequireCompleteType(Var->getLocation(),
+                                  ArrayT->getElementType(),
+                                  diag::err_illegal_decl_array_incomplete_type))
+            Var->setInvalidDecl();
+        } else if (Var->getStorageClass() == SC_Static) {
+          // C99 6.9.2p3: If the declaration of an identifier for an object is
+          // a tentative definition and has internal linkage (C99 6.2.2p3), the
+          // declared type shall not be an incomplete type.
+          // NOTE: code such as the following
+          //     static struct s;
+          //     struct s { int a; };
+          // is accepted by gcc. Hence here we issue a warning instead of
+          // an error and we do not invalidate the static declaration.
+          // NOTE: to avoid multiple warnings, only check the first declaration.
+          if (Var->getPreviousDecl() == 0)
+            RequireCompleteType(Var->getLocation(), Type,
+                                diag::ext_typecheck_decl_incomplete_type);
+        }
+      }
+
+      // Record the tentative definition; we're done.
+      if (!Var->isInvalidDecl())
+        TentativeDefinitions.push_back(Var);
+      return;
+    }
+
+    // Provide a specific diagnostic for uninitialized variable
+    // definitions with incomplete array type.
+    if (Type->isIncompleteArrayType()) {
+      Diag(Var->getLocation(),
+           diag::err_typecheck_incomplete_array_needs_initializer);
+      Var->setInvalidDecl();
+      return;
+    }
+
+    // Provide a specific diagnostic for uninitialized variable
+    // definitions with reference type.
+    if (Type->isReferenceType()) {
+      Diag(Var->getLocation(), diag::err_reference_var_requires_init)
+        << Var->getDeclName()
+        << SourceRange(Var->getLocation(), Var->getLocation());
+      Var->setInvalidDecl();
+      return;
+    }
+
+    // Do not attempt to type-check the default initializer for a
+    // variable with dependent type.
+    if (Type->isDependentType())
+      return;
+
+    if (Var->isInvalidDecl())
+      return;
+
+    if (RequireCompleteType(Var->getLocation(), 
+                            Context.getBaseElementType(Type),
+                            diag::err_typecheck_decl_incomplete_type)) {
+      Var->setInvalidDecl();
+      return;
+    }
+
+    // The variable can not have an abstract class type.
+    if (RequireNonAbstractType(Var->getLocation(), Type,
+                               diag::err_abstract_type_in_decl,
+                               AbstractVariableType)) {
+      Var->setInvalidDecl();
+      return;
+    }
+
+    // Check for jumps past the implicit initializer.  C++0x
+    // clarifies that this applies to a "variable with automatic
+    // storage duration", not a "local variable".
+    // C++11 [stmt.dcl]p3
+    //   A program that jumps from a point where a variable with automatic
+    //   storage duration is not in scope to a point where it is in scope is
+    //   ill-formed unless the variable has scalar type, class type with a
+    //   trivial default constructor and a trivial destructor, a cv-qualified
+    //   version of one of these types, or an array of one of the preceding
+    //   types and is declared without an initializer.
+    if (getLangOpts().CPlusPlus && Var->hasLocalStorage()) {
+      if (const RecordType *Record
+            = Context.getBaseElementType(Type)->getAs<RecordType>()) {
+        CXXRecordDecl *CXXRecord = cast<CXXRecordDecl>(Record->getDecl());
+        // Mark the function for further checking even if the looser rules of
+        // C++11 do not require such checks, so that we can diagnose
+        // incompatibilities with C++98.
+        if (!CXXRecord->isPOD())
+          getCurFunction()->setHasBranchProtectedScope();
+      }
+    }
+    
+    // C++03 [dcl.init]p9:
+    //   If no initializer is specified for an object, and the
+    //   object is of (possibly cv-qualified) non-POD class type (or
+    //   array thereof), the object shall be default-initialized; if
+    //   the object is of const-qualified type, the underlying class
+    //   type shall have a user-declared default
+    //   constructor. Otherwise, if no initializer is specified for
+    //   a non- static object, the object and its subobjects, if
+    //   any, have an indeterminate initial value); if the object
+    //   or any of its subobjects are of const-qualified type, the
+    //   program is ill-formed.
+    // C++0x [dcl.init]p11:
+    //   If no initializer is specified for an object, the object is
+    //   default-initialized; [...].
+    InitializedEntity Entity = InitializedEntity::InitializeVariable(Var);
+    InitializationKind Kind
+      = InitializationKind::CreateDefault(Var->getLocation());
+    
+    InitializationSequence InitSeq(*this, Entity, Kind, 0, 0);
+    ExprResult Init = InitSeq.Perform(*this, Entity, Kind,
+                                      MultiExprArg(*this, 0, 0));
+    if (Init.isInvalid())
+      Var->setInvalidDecl();
+    else if (Init.get()) {
+      Var->setInit(MaybeCreateExprWithCleanups(Init.get()));
+      // This is important for template substitution.
+      Var->setInitStyle(VarDecl::CallInit);
+    }
+
+    CheckCompleteVariableDeclaration(Var);
+  }
+}
+
+void Sema::ActOnCXXForRangeDecl(Decl *D) {
+  VarDecl *VD = dyn_cast<VarDecl>(D);
+  if (!VD) {
+    Diag(D->getLocation(), diag::err_for_range_decl_must_be_var);
+    D->setInvalidDecl();
+    return;
+  }
+
+  VD->setCXXForRangeDecl(true);
+
+  // for-range-declaration cannot be given a storage class specifier.
+  int Error = -1;
+  switch (VD->getStorageClassAsWritten()) {
+  case SC_None:
+    break;
+  case SC_Extern:
+    Error = 0;
+    break;
+  case SC_Static:
+    Error = 1;
+    break;
+  case SC_PrivateExtern:
+    Error = 2;
+    break;
+  case SC_Auto:
+    Error = 3;
+    break;
+  case SC_Register:
+    Error = 4;
+    break;
+  case SC_OpenCLWorkGroupLocal:
+    llvm_unreachable("Unexpected storage class");
+  }
+  if (VD->isConstexpr())
+    Error = 5;
+  if (Error != -1) {
+    Diag(VD->getOuterLocStart(), diag::err_for_range_storage_class)
+      << VD->getDeclName() << Error;
+    D->setInvalidDecl();
+  }
+}
+
+void Sema::CheckCompleteVariableDeclaration(VarDecl *var) {
+  if (var->isInvalidDecl()) return;
+
+  // In ARC, don't allow jumps past the implicit initialization of a
+  // local retaining variable.
+  if (getLangOpts().ObjCAutoRefCount &&
+      var->hasLocalStorage()) {
+    switch (var->getType().getObjCLifetime()) {
+    case Qualifiers::OCL_None:
+    case Qualifiers::OCL_ExplicitNone:
+    case Qualifiers::OCL_Autoreleasing:
+      break;
+
+    case Qualifiers::OCL_Weak:
+    case Qualifiers::OCL_Strong:
+      getCurFunction()->setHasBranchProtectedScope();
+      break;
+    }
+  }
+
+  // All the following checks are C++ only.
+  if (!getLangOpts().CPlusPlus) return;
+
+  QualType baseType = Context.getBaseElementType(var->getType());
+  if (baseType->isDependentType()) return;
+
+  // __block variables might require us to capture a copy-initializer.
+  if (var->hasAttr<BlocksAttr>()) {
+    // It's currently invalid to ever have a __block variable with an
+    // array type; should we diagnose that here?
+
+    // Regardless, we don't want to ignore array nesting when
+    // constructing this copy.
+    QualType type = var->getType();
+
+    if (type->isStructureOrClassType()) {
+      SourceLocation poi = var->getLocation();
+      Expr *varRef =new (Context) DeclRefExpr(var, false, type, VK_LValue, poi);
+      ExprResult result =
+        PerformCopyInitialization(
+                        InitializedEntity::InitializeBlock(poi, type, false),
+                                  poi, Owned(varRef));
+      if (!result.isInvalid()) {
+        result = MaybeCreateExprWithCleanups(result);
+        Expr *init = result.takeAs<Expr>();
+        Context.setBlockVarCopyInits(var, init);
+      }
+    }
+  }
+
+  Expr *Init = var->getInit();
+  bool IsGlobal = var->hasGlobalStorage() && !var->isStaticLocal();
+
+  if (!var->getDeclContext()->isDependentContext() && Init) {
+    if (IsGlobal && !var->isConstexpr() &&
+        getDiagnostics().getDiagnosticLevel(diag::warn_global_constructor,
+                                            var->getLocation())
+          != DiagnosticsEngine::Ignored &&
+        !Init->isConstantInitializer(Context, baseType->isReferenceType()))
+      Diag(var->getLocation(), diag::warn_global_constructor)
+        << Init->getSourceRange();
+
+    if (var->isConstexpr()) {
+      llvm::SmallVector<PartialDiagnosticAt, 8> Notes;
+      if (!var->evaluateValue(Notes) || !var->isInitICE()) {
+        SourceLocation DiagLoc = var->getLocation();
+        // If the note doesn't add any useful information other than a source
+        // location, fold it into the primary diagnostic.
+        if (Notes.size() == 1 && Notes[0].second.getDiagID() ==
+              diag::note_invalid_subexpr_in_const_expr) {
+          DiagLoc = Notes[0].first;
+          Notes.clear();
+        }
+        Diag(DiagLoc, diag::err_constexpr_var_requires_const_init)
+          << var << Init->getSourceRange();
+        for (unsigned I = 0, N = Notes.size(); I != N; ++I)
+          Diag(Notes[I].first, Notes[I].second);
+      }
+    } else if (var->isUsableInConstantExpressions(Context)) {
+      // Check whether the initializer of a const variable of integral or
+      // enumeration type is an ICE now, since we can't tell whether it was
+      // initialized by a constant expression if we check later.
+      var->checkInitIsICE();
+    }
+  }
+
+  // Require the destructor.
+  if (const RecordType *recordType = baseType->getAs<RecordType>())
+    FinalizeVarWithDestructor(var, recordType);
+}
+
+/// FinalizeDeclaration - called by ParseDeclarationAfterDeclarator to perform
+/// any semantic actions necessary after any initializer has been attached.
+void
+Sema::FinalizeDeclaration(Decl *ThisDecl) {
+  // Note that we are no longer parsing the initializer for this declaration.
+  ParsingInitForAutoVars.erase(ThisDecl);
+}
+
+Sema::DeclGroupPtrTy
+Sema::FinalizeDeclaratorGroup(Scope *S, const DeclSpec &DS,
+                              Decl **Group, unsigned NumDecls) {
+  SmallVector<Decl*, 8> Decls;
+
+  if (DS.isTypeSpecOwned())
+    Decls.push_back(DS.getRepAsDecl());
+
+  for (unsigned i = 0; i != NumDecls; ++i)
+    if (Decl *D = Group[i])
+      Decls.push_back(D);
+
+  return BuildDeclaratorGroup(Decls.data(), Decls.size(),
+                              DS.getTypeSpecType() == DeclSpec::TST_auto);
+}
+
+/// BuildDeclaratorGroup - convert a list of declarations into a declaration
+/// group, performing any necessary semantic checking.
+Sema::DeclGroupPtrTy
+Sema::BuildDeclaratorGroup(Decl **Group, unsigned NumDecls,
+                           bool TypeMayContainAuto) {
+  // C++0x [dcl.spec.auto]p7:
+  //   If the type deduced for the template parameter U is not the same in each
+  //   deduction, the program is ill-formed.
+  // FIXME: When initializer-list support is added, a distinction is needed
+  // between the deduced type U and the deduced type which 'auto' stands for.
+  //   auto a = 0, b = { 1, 2, 3 };
+  // is legal because the deduced type U is 'int' in both cases.
+  if (TypeMayContainAuto && NumDecls > 1) {
+    QualType Deduced;
+    CanQualType DeducedCanon;
+    VarDecl *DeducedDecl = 0;
+    for (unsigned i = 0; i != NumDecls; ++i) {
+      if (VarDecl *D = dyn_cast<VarDecl>(Group[i])) {
+        AutoType *AT = D->getType()->getContainedAutoType();
+        // Don't reissue diagnostics when instantiating a template.
+        if (AT && D->isInvalidDecl())
+          break;
+        if (AT && AT->isDeduced()) {
+          QualType U = AT->getDeducedType();
+          CanQualType UCanon = Context.getCanonicalType(U);
+          if (Deduced.isNull()) {
+            Deduced = U;
+            DeducedCanon = UCanon;
+            DeducedDecl = D;
+          } else if (DeducedCanon != UCanon) {
+            Diag(D->getTypeSourceInfo()->getTypeLoc().getBeginLoc(),
+                 diag::err_auto_different_deductions)
+              << Deduced << DeducedDecl->getDeclName()
+              << U << D->getDeclName()
+              << DeducedDecl->getInit()->getSourceRange()
+              << D->getInit()->getSourceRange();
+            D->setInvalidDecl();
+            break;
+          }
+        }
+      }
+    }
+  }
+
+  return DeclGroupPtrTy::make(DeclGroupRef::Create(Context, Group, NumDecls));
+}
+
+
+/// ActOnParamDeclarator - Called from Parser::ParseFunctionDeclarator()
+/// to introduce parameters into function prototype scope.
+Decl *Sema::ActOnParamDeclarator(Scope *S, Declarator &D) {
+  const DeclSpec &DS = D.getDeclSpec();
+
+  // Verify C99 6.7.5.3p2: The only SCS allowed is 'register'.
+  // C++03 [dcl.stc]p2 also permits 'auto'.
+  VarDecl::StorageClass StorageClass = SC_None;
+  VarDecl::StorageClass StorageClassAsWritten = SC_None;
+  if (DS.getStorageClassSpec() == DeclSpec::SCS_register) {
+    StorageClass = SC_Register;
+    StorageClassAsWritten = SC_Register;
+  } else if (getLangOpts().CPlusPlus &&
+             DS.getStorageClassSpec() == DeclSpec::SCS_auto) {
+    StorageClass = SC_Auto;
+    StorageClassAsWritten = SC_Auto;
+  } else if (DS.getStorageClassSpec() != DeclSpec::SCS_unspecified) {
+    Diag(DS.getStorageClassSpecLoc(),
+         diag::err_invalid_storage_class_in_func_decl);
+    D.getMutableDeclSpec().ClearStorageClassSpecs();
+  }
+
+  if (D.getDeclSpec().isThreadSpecified())
+    Diag(D.getDeclSpec().getThreadSpecLoc(), diag::err_invalid_thread);
+  if (D.getDeclSpec().isConstexprSpecified())
+    Diag(D.getDeclSpec().getConstexprSpecLoc(), diag::err_invalid_constexpr)
+      << 0;
+
+  DiagnoseFunctionSpecifiers(D);
+
+  TypeSourceInfo *TInfo = GetTypeForDeclarator(D, S);
+  QualType parmDeclType = TInfo->getType();
+
+  if (getLangOpts().CPlusPlus) {
+    // Check that there are no default arguments inside the type of this
+    // parameter.
+    CheckExtraCXXDefaultArguments(D);
+    
+    // Parameter declarators cannot be qualified (C++ [dcl.meaning]p1).
+    if (D.getCXXScopeSpec().isSet()) {
+      Diag(D.getIdentifierLoc(), diag::err_qualified_param_declarator)
+        << D.getCXXScopeSpec().getRange();
+      D.getCXXScopeSpec().clear();
+    }
+  }
+
+  // Ensure we have a valid name
+  IdentifierInfo *II = 0;
+  if (D.hasName()) {
+    II = D.getIdentifier();
+    if (!II) {
+      Diag(D.getIdentifierLoc(), diag::err_bad_parameter_name)
+        << GetNameForDeclarator(D).getName().getAsString();
+      D.setInvalidType(true);
+    }
+  }
+
+  // Check for redeclaration of parameters, e.g. int foo(int x, int x);
+  if (II) {
+    LookupResult R(*this, II, D.getIdentifierLoc(), LookupOrdinaryName,
+                   ForRedeclaration);
+    LookupName(R, S);
+    if (R.isSingleResult()) {
+      NamedDecl *PrevDecl = R.getFoundDecl();
+      if (PrevDecl->isTemplateParameter()) {
+        // Maybe we will complain about the shadowed template parameter.
+        DiagnoseTemplateParameterShadow(D.getIdentifierLoc(), PrevDecl);
+        // Just pretend that we didn't see the previous declaration.
+        PrevDecl = 0;
+      } else if (S->isDeclScope(PrevDecl)) {
+        Diag(D.getIdentifierLoc(), diag::err_param_redefinition) << II;
+        Diag(PrevDecl->getLocation(), diag::note_previous_declaration);
+
+        // Recover by removing the name
+        II = 0;
+        D.SetIdentifier(0, D.getIdentifierLoc());
+        D.setInvalidType(true);
+      }
+    }
+  }
+
+  // Temporarily put parameter variables in the translation unit, not
+  // the enclosing context.  This prevents them from accidentally
+  // looking like class members in C++.
+  ParmVarDecl *New = CheckParameter(Context.getTranslationUnitDecl(),
+                                    D.getLocStart(),
+                                    D.getIdentifierLoc(), II,
+                                    parmDeclType, TInfo,
+                                    StorageClass, StorageClassAsWritten);
+
+  if (D.isInvalidType())
+    New->setInvalidDecl();
+
+  assert(S->isFunctionPrototypeScope());
+  assert(S->getFunctionPrototypeDepth() >= 1);
+  New->setScopeInfo(S->getFunctionPrototypeDepth() - 1,
+                    S->getNextFunctionPrototypeIndex());
+  
+  // Add the parameter declaration into this scope.
+  S->AddDecl(New);
+  if (II)
+    IdResolver.AddDecl(New);
+
+  ProcessDeclAttributes(S, New, D);
+
+  if (D.getDeclSpec().isModulePrivateSpecified())
+    Diag(New->getLocation(), diag::err_module_private_local)
+      << 1 << New->getDeclName()
+      << SourceRange(D.getDeclSpec().getModulePrivateSpecLoc())
+      << FixItHint::CreateRemoval(D.getDeclSpec().getModulePrivateSpecLoc());
+
+  if (New->hasAttr<BlocksAttr>()) {
+    Diag(New->getLocation(), diag::err_block_on_nonlocal);
+  }
+  return New;
+}
+
+/// \brief Synthesizes a variable for a parameter arising from a
+/// typedef.
+ParmVarDecl *Sema::BuildParmVarDeclForTypedef(DeclContext *DC,
+                                              SourceLocation Loc,
+                                              QualType T) {
+  /* FIXME: setting StartLoc == Loc.
+     Would it be worth to modify callers so as to provide proper source
+     location for the unnamed parameters, embedding the parameter's type? */
+  ParmVarDecl *Param = ParmVarDecl::Create(Context, DC, Loc, Loc, 0,
+                                T, Context.getTrivialTypeSourceInfo(T, Loc),
+                                           SC_None, SC_None, 0);
+  Param->setImplicit();
+  return Param;
+}
+
+void Sema::DiagnoseUnusedParameters(ParmVarDecl * const *Param,
+                                    ParmVarDecl * const *ParamEnd) {
+  // Don't diagnose unused-parameter errors in template instantiations; we
+  // will already have done so in the template itself.
+  if (!ActiveTemplateInstantiations.empty())
+    return;
+
+  for (; Param != ParamEnd; ++Param) {
+    if (!(*Param)->isReferenced() && (*Param)->getDeclName() &&
+        !(*Param)->hasAttr<UnusedAttr>()) {
+      Diag((*Param)->getLocation(), diag::warn_unused_parameter)
+        << (*Param)->getDeclName();
+    }
+  }
+}
+
+void Sema::DiagnoseSizeOfParametersAndReturnValue(ParmVarDecl * const *Param,
+                                                  ParmVarDecl * const *ParamEnd,
+                                                  QualType ReturnTy,
+                                                  NamedDecl *D) {
+  if (LangOpts.NumLargeByValueCopy == 0) // No check.
+    return;
+
+  // Warn if the return value is pass-by-value and larger than the specified
+  // threshold.
+  if (!ReturnTy->isDependentType() && ReturnTy.isPODType(Context)) {
+    unsigned Size = Context.getTypeSizeInChars(ReturnTy).getQuantity();
+    if (Size > LangOpts.NumLargeByValueCopy)
+      Diag(D->getLocation(), diag::warn_return_value_size)
+          << D->getDeclName() << Size;
+  }
+
+  // Warn if any parameter is pass-by-value and larger than the specified
+  // threshold.
+  for (; Param != ParamEnd; ++Param) {
+    QualType T = (*Param)->getType();
+    if (T->isDependentType() || !T.isPODType(Context))
+      continue;
+    unsigned Size = Context.getTypeSizeInChars(T).getQuantity();
+    if (Size > LangOpts.NumLargeByValueCopy)
+      Diag((*Param)->getLocation(), diag::warn_parameter_size)
+          << (*Param)->getDeclName() << Size;
+  }
+}
+
+ParmVarDecl *Sema::CheckParameter(DeclContext *DC, SourceLocation StartLoc,
+                                  SourceLocation NameLoc, IdentifierInfo *Name,
+                                  QualType T, TypeSourceInfo *TSInfo,
+                                  VarDecl::StorageClass StorageClass,
+                                  VarDecl::StorageClass StorageClassAsWritten) {
+  // In ARC, infer a lifetime qualifier for appropriate parameter types.
+  if (getLangOpts().ObjCAutoRefCount &&
+      T.getObjCLifetime() == Qualifiers::OCL_None &&
+      T->isObjCLifetimeType()) {
+
+    Qualifiers::ObjCLifetime lifetime;
+
+    // Special cases for arrays:
+    //   - if it's const, use __unsafe_unretained
+    //   - otherwise, it's an error
+    if (T->isArrayType()) {
+      if (!T.isConstQualified()) {
+        DelayedDiagnostics.add(
+            sema::DelayedDiagnostic::makeForbiddenType(
+            NameLoc, diag::err_arc_array_param_no_ownership, T, false));
+      }
+      lifetime = Qualifiers::OCL_ExplicitNone;
+    } else {
+      lifetime = T->getObjCARCImplicitLifetime();
+    }
+    T = Context.getLifetimeQualifiedType(T, lifetime);
+  }
+
+  ParmVarDecl *New = ParmVarDecl::Create(Context, DC, StartLoc, NameLoc, Name,
+                                         Context.getAdjustedParameterType(T), 
+                                         TSInfo,
+                                         StorageClass, StorageClassAsWritten,
+                                         0);
+
+  // Parameters can not be abstract class types.
+  // For record types, this is done by the AbstractClassUsageDiagnoser once
+  // the class has been completely parsed.
+  if (!CurContext->isRecord() &&
+      RequireNonAbstractType(NameLoc, T, diag::err_abstract_type_in_decl,
+                             AbstractParamType))
+    New->setInvalidDecl();
+
+  // Parameter declarators cannot be interface types. All ObjC objects are
+  // passed by reference.
+  if (T->isObjCObjectType()) {
+    Diag(NameLoc,
+         diag::err_object_cannot_be_passed_returned_by_value) << 1 << T
+      << FixItHint::CreateInsertion(NameLoc, "*");
+    T = Context.getObjCObjectPointerType(T);
+    New->setType(T);
+  }
+
+  // ISO/IEC TR 18037 S6.7.3: "The type of an object with automatic storage 
+  // duration shall not be qualified by an address-space qualifier."
+  // Since all parameters have automatic store duration, they can not have
+  // an address space.
+  if (T.getAddressSpace() != 0) {
+    Diag(NameLoc, diag::err_arg_with_address_space);
+    New->setInvalidDecl();
+  }   
+
+  return New;
+}
+
+void Sema::ActOnFinishKNRParamDeclarations(Scope *S, Declarator &D,
+                                           SourceLocation LocAfterDecls) {
+  DeclaratorChunk::FunctionTypeInfo &FTI = D.getFunctionTypeInfo();
+
+  // Verify 6.9.1p6: 'every identifier in the identifier list shall be declared'
+  // for a K&R function.
+  if (!FTI.hasPrototype) {
+    for (int i = FTI.NumArgs; i != 0; /* decrement in loop */) {
+      --i;
+      if (FTI.ArgInfo[i].Param == 0) {
+        SmallString<256> Code;
+        llvm::raw_svector_ostream(Code) << "  int "
+                                        << FTI.ArgInfo[i].Ident->getName()
+                                        << ";\n";
+        Diag(FTI.ArgInfo[i].IdentLoc, diag::ext_param_not_declared)
+          << FTI.ArgInfo[i].Ident
+          << FixItHint::CreateInsertion(LocAfterDecls, Code.str());
+
+        // Implicitly declare the argument as type 'int' for lack of a better
+        // type.
+        AttributeFactory attrs;
+        DeclSpec DS(attrs);
+        const char* PrevSpec; // unused
+        unsigned DiagID; // unused
+        DS.SetTypeSpecType(DeclSpec::TST_int, FTI.ArgInfo[i].IdentLoc,
+                           PrevSpec, DiagID);
+        Declarator ParamD(DS, Declarator::KNRTypeListContext);
+        ParamD.SetIdentifier(FTI.ArgInfo[i].Ident, FTI.ArgInfo[i].IdentLoc);
+        FTI.ArgInfo[i].Param = ActOnParamDeclarator(S, ParamD);
+      }
+    }
+  }
+}
+
+Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Declarator &D) {
+  assert(getCurFunctionDecl() == 0 && "Function parsing confused");
+  assert(D.isFunctionDeclarator() && "Not a function declarator!");
+  Scope *ParentScope = FnBodyScope->getParent();
+
+  D.setFunctionDefinitionKind(FDK_Definition);
+  Decl *DP = HandleDeclarator(ParentScope, D,
+                              MultiTemplateParamsArg(*this));
+  return ActOnStartOfFunctionDef(FnBodyScope, DP);
+}
+
+static bool ShouldWarnAboutMissingPrototype(const FunctionDecl *FD) {
+  // Don't warn about invalid declarations.
+  if (FD->isInvalidDecl())
+    return false;
+
+  // Or declarations that aren't global.
+  if (!FD->isGlobal())
+    return false;
+
+  // Don't warn about C++ member functions.
+  if (isa<CXXMethodDecl>(FD))
+    return false;
+
+  // Don't warn about 'main'.
+  if (FD->isMain())
+    return false;
+
+  // Don't warn about inline functions.
+  if (FD->isInlined())
+    return false;
+
+  // Don't warn about function templates.
+  if (FD->getDescribedFunctionTemplate())
+    return false;
+
+  // Don't warn about function template specializations.
+  if (FD->isFunctionTemplateSpecialization())
+    return false;
+
+  bool MissingPrototype = true;
+  for (const FunctionDecl *Prev = FD->getPreviousDecl();
+       Prev; Prev = Prev->getPreviousDecl()) {
+    // Ignore any declarations that occur in function or method
+    // scope, because they aren't visible from the header.
+    if (Prev->getDeclContext()->isFunctionOrMethod())
+      continue;
+      
+    MissingPrototype = !Prev->getType()->isFunctionProtoType();
+    break;
+  }
+    
+  return MissingPrototype;
+}
+
+void Sema::CheckForFunctionRedefinition(FunctionDecl *FD) {
+  // Don't complain if we're in GNU89 mode and the previous definition
+  // was an extern inline function.
+  const FunctionDecl *Definition;
+  if (FD->isDefined(Definition) &&
+      !canRedefineFunction(Definition, getLangOpts())) {
+    if (getLangOpts().GNUMode && Definition->isInlineSpecified() &&
+        Definition->getStorageClass() == SC_Extern)
+      Diag(FD->getLocation(), diag::err_redefinition_extern_inline)
+        << FD->getDeclName() << getLangOpts().CPlusPlus;
+    else
+      Diag(FD->getLocation(), diag::err_redefinition) << FD->getDeclName();
+    Diag(Definition->getLocation(), diag::note_previous_definition);
+  }
+}
+
+Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Decl *D) {
+  // Clear the last template instantiation error context.
+  LastTemplateInstantiationErrorContext = ActiveTemplateInstantiation();
+  
+  if (!D)
+    return D;
+  FunctionDecl *FD = 0;
+
+  if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(D))
+    FD = FunTmpl->getTemplatedDecl();
+  else
+    FD = cast<FunctionDecl>(D);
+
+  // Enter a new function scope
+  PushFunctionScope();
+
+  // See if this is a redefinition.
+  if (!FD->isLateTemplateParsed())
+    CheckForFunctionRedefinition(FD);
+
+  // Builtin functions cannot be defined.
+  if (unsigned BuiltinID = FD->getBuiltinID()) {
+    if (!Context.BuiltinInfo.isPredefinedLibFunction(BuiltinID)) {
+      Diag(FD->getLocation(), diag::err_builtin_definition) << FD;
+      FD->setInvalidDecl();
+    }
+  }
+
+  // The return type of a function definition must be complete
+  // (C99 6.9.1p3, C++ [dcl.fct]p6).
+  QualType ResultType = FD->getResultType();
+  if (!ResultType->isDependentType() && !ResultType->isVoidType() &&
+      !FD->isInvalidDecl() &&
+      RequireCompleteType(FD->getLocation(), ResultType,
+                          diag::err_func_def_incomplete_result))
+    FD->setInvalidDecl();
+
+  // GNU warning -Wmissing-prototypes:
+  //   Warn if a global function is defined without a previous
+  //   prototype declaration. This warning is issued even if the
+  //   definition itself provides a prototype. The aim is to detect
+  //   global functions that fail to be declared in header files.
+  if (ShouldWarnAboutMissingPrototype(FD))
+    Diag(FD->getLocation(), diag::warn_missing_prototype) << FD;
+
+  if (FnBodyScope)
+    PushDeclContext(FnBodyScope, FD);
+
+  // Check the validity of our function parameters
+  CheckParmsForFunctionDef(FD->param_begin(), FD->param_end(),
+                           /*CheckParameterNames=*/true);
+
+  // Introduce our parameters into the function scope
+  for (unsigned p = 0, NumParams = FD->getNumParams(); p < NumParams; ++p) {
+    ParmVarDecl *Param = FD->getParamDecl(p);
+    Param->setOwningFunction(FD);
+
+    // If this has an identifier, add it to the scope stack.
+    if (Param->getIdentifier() && FnBodyScope) {
+      CheckShadow(FnBodyScope, Param);
+
+      PushOnScopeChains(Param, FnBodyScope);
+    }
+  }
+
+  // If we had any tags defined in the function prototype,
+  // introduce them into the function scope.
+  if (FnBodyScope) {
+    for (llvm::ArrayRef<NamedDecl*>::iterator I = FD->getDeclsInPrototypeScope().begin(),
+           E = FD->getDeclsInPrototypeScope().end(); I != E; ++I) {
+      NamedDecl *D = *I;
+
+      // Some of these decls (like enums) may have been pinned to the translation unit
+      // for lack of a real context earlier. If so, remove from the translation unit
+      // and reattach to the current context.
+      if (D->getLexicalDeclContext() == Context.getTranslationUnitDecl()) {
+        // Is the decl actually in the context?
+        for (DeclContext::decl_iterator DI = Context.getTranslationUnitDecl()->decls_begin(),
+               DE = Context.getTranslationUnitDecl()->decls_end(); DI != DE; ++DI) {
+          if (*DI == D) {  
+            Context.getTranslationUnitDecl()->removeDecl(D);
+            break;
+          }
+        }
+        // Either way, reassign the lexical decl context to our FunctionDecl.
+        D->setLexicalDeclContext(CurContext);
+      }
+
+      // If the decl has a non-null name, make accessible in the current scope.
+      if (!D->getName().empty())
+        PushOnScopeChains(D, FnBodyScope, /*AddToContext=*/false);
+
+      // Similarly, dive into enums and fish their constants out, making them
+      // accessible in this scope.
+      if (EnumDecl *ED = dyn_cast<EnumDecl>(D)) {
+        for (EnumDecl::enumerator_iterator EI = ED->enumerator_begin(),
+               EE = ED->enumerator_end(); EI != EE; ++EI)
+          PushOnScopeChains(*EI, FnBodyScope, /*AddToContext=*/false);
+      }
+    }
+  }
+
+  // Ensure that the function's exception specification is instantiated.
+  if (const FunctionProtoType *FPT = FD->getType()->getAs<FunctionProtoType>())
+    ResolveExceptionSpec(D->getLocation(), FPT);
+
+  // Checking attributes of current function definition
+  // dllimport attribute.
+  DLLImportAttr *DA = FD->getAttr<DLLImportAttr>();
+  if (DA && (!FD->getAttr<DLLExportAttr>())) {
+    // dllimport attribute cannot be directly applied to definition.
+    // Microsoft accepts dllimport for functions defined within class scope. 
+    if (!DA->isInherited() &&
+        !(LangOpts.MicrosoftExt && FD->getLexicalDeclContext()->isRecord())) {
+      Diag(FD->getLocation(),
+           diag::err_attribute_can_be_applied_only_to_symbol_declaration)
+        << "dllimport";
+      FD->setInvalidDecl();
+      return FD;
+    }
+
+    // Visual C++ appears to not think this is an issue, so only issue
+    // a warning when Microsoft extensions are disabled.
+    if (!LangOpts.MicrosoftExt) {
+      // If a symbol previously declared dllimport is later defined, the
+      // attribute is ignored in subsequent references, and a warning is
+      // emitted.
+      Diag(FD->getLocation(),
+           diag::warn_redeclaration_without_attribute_prev_attribute_ignored)
+        << FD->getName() << "dllimport";
+    }
+  }
+  return FD;
+}
+
+/// \brief Given the set of return statements within a function body,
+/// compute the variables that are subject to the named return value 
+/// optimization.
+///
+/// Each of the variables that is subject to the named return value 
+/// optimization will be marked as NRVO variables in the AST, and any
+/// return statement that has a marked NRVO variable as its NRVO candidate can
+/// use the named return value optimization.
+///
+/// This function applies a very simplistic algorithm for NRVO: if every return
+/// statement in the function has the same NRVO candidate, that candidate is
+/// the NRVO variable.
+///
+/// FIXME: Employ a smarter algorithm that accounts for multiple return 
+/// statements and the lifetimes of the NRVO candidates. We should be able to
+/// find a maximal set of NRVO variables.
+void Sema::computeNRVO(Stmt *Body, FunctionScopeInfo *Scope) {
+  ReturnStmt **Returns = Scope->Returns.data();
+
+  const VarDecl *NRVOCandidate = 0;
+  for (unsigned I = 0, E = Scope->Returns.size(); I != E; ++I) {
+    if (!Returns[I]->getNRVOCandidate())
+      return;
+    
+    if (!NRVOCandidate)
+      NRVOCandidate = Returns[I]->getNRVOCandidate();
+    else if (NRVOCandidate != Returns[I]->getNRVOCandidate())
+      return;
+  }
+  
+  if (NRVOCandidate)
+    const_cast<VarDecl*>(NRVOCandidate)->setNRVOVariable(true);
+}
+
+Decl *Sema::ActOnFinishFunctionBody(Decl *D, Stmt *BodyArg) {
+  return ActOnFinishFunctionBody(D, move(BodyArg), false);
+}
+
+Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body,
+                                    bool IsInstantiation) {
+  FunctionDecl *FD = 0;
+  FunctionTemplateDecl *FunTmpl = dyn_cast_or_null<FunctionTemplateDecl>(dcl);
+  if (FunTmpl)
+    FD = FunTmpl->getTemplatedDecl();
+  else
+    FD = dyn_cast_or_null<FunctionDecl>(dcl);
+
+  sema::AnalysisBasedWarnings::Policy WP = AnalysisWarnings.getDefaultPolicy();
+  sema::AnalysisBasedWarnings::Policy *ActivePolicy = 0;
+
+  if (FD) {
+    FD->setBody(Body);
+
+    // If the function implicitly returns zero (like 'main') or is naked,
+    // don't complain about missing return statements.
+    if (FD->hasImplicitReturnZero() || FD->hasAttr<NakedAttr>())
+      WP.disableCheckFallThrough();
+
+    // MSVC permits the use of pure specifier (=0) on function definition,
+    // defined at class scope, warn about this non standard construct.
+    if (getLangOpts().MicrosoftExt && FD->isPure())
+      Diag(FD->getLocation(), diag::warn_pure_function_definition);
+
+    if (!FD->isInvalidDecl()) {
+      DiagnoseUnusedParameters(FD->param_begin(), FD->param_end());
+      DiagnoseSizeOfParametersAndReturnValue(FD->param_begin(), FD->param_end(),
+                                             FD->getResultType(), FD);
+      
+      // If this is a constructor, we need a vtable.
+      if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(FD))
+        MarkVTableUsed(FD->getLocation(), Constructor->getParent());
+      
+      computeNRVO(Body, getCurFunction());
+    }
+    
+    assert((FD == getCurFunctionDecl() || getCurLambda()->CallOperator == FD) &&
+           "Function parsing confused");
+  } else if (ObjCMethodDecl *MD = dyn_cast_or_null<ObjCMethodDecl>(dcl)) {
+    assert(MD == getCurMethodDecl() && "Method parsing confused");
+    MD->setBody(Body);
+    if (Body)
+      MD->setEndLoc(Body->getLocEnd());
+    if (!MD->isInvalidDecl()) {
+      DiagnoseUnusedParameters(MD->param_begin(), MD->param_end());
+      DiagnoseSizeOfParametersAndReturnValue(MD->param_begin(), MD->param_end(),
+                                             MD->getResultType(), MD);
+      
+      if (Body)
+        computeNRVO(Body, getCurFunction());
+    }
+    if (ObjCShouldCallSuperDealloc) {
+      Diag(MD->getLocEnd(), diag::warn_objc_missing_super_dealloc);
+      ObjCShouldCallSuperDealloc = false;
+    }
+    if (ObjCShouldCallSuperFinalize) {
+      Diag(MD->getLocEnd(), diag::warn_objc_missing_super_finalize);
+      ObjCShouldCallSuperFinalize = false;
+    }
+  } else {
+    return 0;
+  }
+
+  assert(!ObjCShouldCallSuperDealloc && "This should only be set for "
+         "ObjC methods, which should have been handled in the block above.");
+  assert(!ObjCShouldCallSuperFinalize && "This should only be set for "
+         "ObjC methods, which should have been handled in the block above.");
+
+  // Verify and clean out per-function state.
+  if (Body) {
+    // C++ constructors that have function-try-blocks can't have return
+    // statements in the handlers of that block. (C++ [except.handle]p14)
+    // Verify this.
+    if (FD && isa<CXXConstructorDecl>(FD) && isa<CXXTryStmt>(Body))
+      DiagnoseReturnInConstructorExceptionHandler(cast<CXXTryStmt>(Body));
+    
+    // Verify that gotos and switch cases don't jump into scopes illegally.
+    if (getCurFunction()->NeedsScopeChecking() &&
+        !dcl->isInvalidDecl() &&
+        !hasAnyUnrecoverableErrorsInThisFunction())
+      DiagnoseInvalidJumps(Body);
+
+    if (CXXDestructorDecl *Destructor = dyn_cast<CXXDestructorDecl>(dcl)) {
+      if (!Destructor->getParent()->isDependentType())
+        CheckDestructor(Destructor);
+
+      MarkBaseAndMemberDestructorsReferenced(Destructor->getLocation(),
+                                             Destructor->getParent());
+    }
+    
+    // If any errors have occurred, clear out any temporaries that may have
+    // been leftover. This ensures that these temporaries won't be picked up for
+    // deletion in some later function.
+    if (PP.getDiagnostics().hasErrorOccurred() ||
+        PP.getDiagnostics().getSuppressAllDiagnostics()) {
+      DiscardCleanupsInEvaluationContext();
+    } else if (!isa<FunctionTemplateDecl>(dcl)) {
+      // Since the body is valid, issue any analysis-based warnings that are
+      // enabled.
+      ActivePolicy = &WP;
+    }
+
+    if (!IsInstantiation && FD && FD->isConstexpr() && !FD->isInvalidDecl() &&
+        (!CheckConstexprFunctionDecl(FD) ||
+         !CheckConstexprFunctionBody(FD, Body)))
+      FD->setInvalidDecl();
+
+    assert(ExprCleanupObjects.empty() && "Leftover temporaries in function");
+    assert(!ExprNeedsCleanups && "Unaccounted cleanups in function");
+    assert(MaybeODRUseExprs.empty() &&
+           "Leftover expressions for odr-use checking");
+  }
+  
+  if (!IsInstantiation)
+    PopDeclContext();
+
+  PopFunctionScopeInfo(ActivePolicy, dcl);
+  
+  // If any errors have occurred, clear out any temporaries that may have
+  // been leftover. This ensures that these temporaries won't be picked up for
+  // deletion in some later function.
+  if (getDiagnostics().hasErrorOccurred()) {
+    DiscardCleanupsInEvaluationContext();
+  }
+
+  return dcl;
+}
+
+
+/// When we finish delayed parsing of an attribute, we must attach it to the
+/// relevant Decl.
+void Sema::ActOnFinishDelayedAttribute(Scope *S, Decl *D,
+                                       ParsedAttributes &Attrs) {
+  // Always attach attributes to the underlying decl.
+  if (TemplateDecl *TD = dyn_cast<TemplateDecl>(D))
+    D = TD->getTemplatedDecl();
+  ProcessDeclAttributeList(S, D, Attrs.getList());  
+  
+  if (CXXMethodDecl *Method = dyn_cast_or_null<CXXMethodDecl>(D))
+    if (Method->isStatic())
+      checkThisInStaticMemberFunctionAttributes(Method);
+}
+
+
+/// ImplicitlyDefineFunction - An undeclared identifier was used in a function
+/// call, forming a call to an implicitly defined function (per C99 6.5.1p2).
+NamedDecl *Sema::ImplicitlyDefineFunction(SourceLocation Loc,
+                                          IdentifierInfo &II, Scope *S) {
+  // Before we produce a declaration for an implicitly defined
+  // function, see whether there was a locally-scoped declaration of
+  // this name as a function or variable. If so, use that
+  // (non-visible) declaration, and complain about it.
+  llvm::DenseMap<DeclarationName, NamedDecl *>::iterator Pos
+    = findLocallyScopedExternalDecl(&II);
+  if (Pos != LocallyScopedExternalDecls.end()) {
+    Diag(Loc, diag::warn_use_out_of_scope_declaration) << Pos->second;
+    Diag(Pos->second->getLocation(), diag::note_previous_declaration);
+    return Pos->second;
+  }
+
+  // Extension in C99.  Legal in C90, but warn about it.
+  unsigned diag_id;
+  if (II.getName().startswith("__builtin_"))
+    diag_id = diag::warn_builtin_unknown;
+  else if (getLangOpts().C99)
+    diag_id = diag::ext_implicit_function_decl;
+  else
+    diag_id = diag::warn_implicit_function_decl;
+  Diag(Loc, diag_id) << &II;
+
+  // Because typo correction is expensive, only do it if the implicit
+  // function declaration is going to be treated as an error.
+  if (Diags.getDiagnosticLevel(diag_id, Loc) >= DiagnosticsEngine::Error) {
+    TypoCorrection Corrected;
+    DeclFilterCCC<FunctionDecl> Validator;
+    if (S && (Corrected = CorrectTypo(DeclarationNameInfo(&II, Loc),
+                                      LookupOrdinaryName, S, 0, Validator))) {
+      std::string CorrectedStr = Corrected.getAsString(getLangOpts());
+      std::string CorrectedQuotedStr = Corrected.getQuoted(getLangOpts());
+      FunctionDecl *Func = Corrected.getCorrectionDeclAs<FunctionDecl>();
+
+      Diag(Loc, diag::note_function_suggestion) << CorrectedQuotedStr
+          << FixItHint::CreateReplacement(Loc, CorrectedStr);
+
+      if (Func->getLocation().isValid()
+          && !II.getName().startswith("__builtin_"))
+        Diag(Func->getLocation(), diag::note_previous_decl)
+            << CorrectedQuotedStr;
+    }
+  }
+
+  // Set a Declarator for the implicit definition: int foo();
+  const char *Dummy;
+  AttributeFactory attrFactory;
+  DeclSpec DS(attrFactory);
+  unsigned DiagID;
+  bool Error = DS.SetTypeSpecType(DeclSpec::TST_int, Loc, Dummy, DiagID);
+  (void)Error; // Silence warning.
+  assert(!Error && "Error setting up implicit decl!");
+  Declarator D(DS, Declarator::BlockContext);
+  D.AddTypeInfo(DeclaratorChunk::getFunction(false, false, SourceLocation(), 0,
+                                             0, 0, true, SourceLocation(),
+                                             SourceLocation(), SourceLocation(),
+                                             SourceLocation(),
+                                             EST_None, SourceLocation(),
+                                             0, 0, 0, 0, Loc, Loc, D),
+                DS.getAttributes(),
+                SourceLocation());
+  D.SetIdentifier(&II, Loc);
+
+  // Insert this function into translation-unit scope.
+
+  DeclContext *PrevDC = CurContext;
+  CurContext = Context.getTranslationUnitDecl();
+
+  FunctionDecl *FD = dyn_cast<FunctionDecl>(ActOnDeclarator(TUScope, D));
+  FD->setImplicit();
+
+  CurContext = PrevDC;
+
+  AddKnownFunctionAttributes(FD);
+
+  return FD;
+}
+
+/// \brief Adds any function attributes that we know a priori based on
+/// the declaration of this function.
+///
+/// These attributes can apply both to implicitly-declared builtins
+/// (like __builtin___printf_chk) or to library-declared functions
+/// like NSLog or printf.
+///
+/// We need to check for duplicate attributes both here and where user-written
+/// attributes are applied to declarations.
+void Sema::AddKnownFunctionAttributes(FunctionDecl *FD) {
+  if (FD->isInvalidDecl())
+    return;
+
+  // If this is a built-in function, map its builtin attributes to
+  // actual attributes.
+  if (unsigned BuiltinID = FD->getBuiltinID()) {
+    // Handle printf-formatting attributes.
+    unsigned FormatIdx;
+    bool HasVAListArg;
+    if (Context.BuiltinInfo.isPrintfLike(BuiltinID, FormatIdx, HasVAListArg)) {
+      if (!FD->getAttr<FormatAttr>()) {
+        const char *fmt = "printf";
+        unsigned int NumParams = FD->getNumParams();
+        if (FormatIdx < NumParams && // NumParams may be 0 (e.g. vfprintf)
+            FD->getParamDecl(FormatIdx)->getType()->isObjCObjectPointerType())
+          fmt = "NSString";
+        FD->addAttr(::new (Context) FormatAttr(FD->getLocation(), Context,
+                                               fmt, FormatIdx+1,
+                                               HasVAListArg ? 0 : FormatIdx+2));
+      }
+    }
+    if (Context.BuiltinInfo.isScanfLike(BuiltinID, FormatIdx,
+                                             HasVAListArg)) {
+     if (!FD->getAttr<FormatAttr>())
+       FD->addAttr(::new (Context) FormatAttr(FD->getLocation(), Context,
+                                              "scanf", FormatIdx+1,
+                                              HasVAListArg ? 0 : FormatIdx+2));
+    }
+
+    // Mark const if we don't care about errno and that is the only
+    // thing preventing the function from being const. This allows
+    // IRgen to use LLVM intrinsics for such functions.
+    if (!getLangOpts().MathErrno &&
+        Context.BuiltinInfo.isConstWithoutErrno(BuiltinID)) {
+      if (!FD->getAttr<ConstAttr>())
+        FD->addAttr(::new (Context) ConstAttr(FD->getLocation(), Context));
+    }
+
+    if (Context.BuiltinInfo.isReturnsTwice(BuiltinID) &&
+        !FD->getAttr<ReturnsTwiceAttr>())
+      FD->addAttr(::new (Context) ReturnsTwiceAttr(FD->getLocation(), Context));
+    if (Context.BuiltinInfo.isNoThrow(BuiltinID) && !FD->getAttr<NoThrowAttr>())
+      FD->addAttr(::new (Context) NoThrowAttr(FD->getLocation(), Context));
+    if (Context.BuiltinInfo.isConst(BuiltinID) && !FD->getAttr<ConstAttr>())
+      FD->addAttr(::new (Context) ConstAttr(FD->getLocation(), Context));
+  }
+
+  IdentifierInfo *Name = FD->getIdentifier();
+  if (!Name)
+    return;
+  if ((!getLangOpts().CPlusPlus &&
+       FD->getDeclContext()->isTranslationUnit()) ||
+      (isa<LinkageSpecDecl>(FD->getDeclContext()) &&
+       cast<LinkageSpecDecl>(FD->getDeclContext())->getLanguage() ==
+       LinkageSpecDecl::lang_c)) {
+    // Okay: this could be a libc/libm/Objective-C function we know
+    // about.
+  } else
+    return;
+
+  if (Name->isStr("asprintf") || Name->isStr("vasprintf")) {
+    // FIXME: asprintf and vasprintf aren't C99 functions. Should they be
+    // target-specific builtins, perhaps?
+    if (!FD->getAttr<FormatAttr>())
+      FD->addAttr(::new (Context) FormatAttr(FD->getLocation(), Context,
+                                             "printf", 2,
+                                             Name->isStr("vasprintf") ? 0 : 3));
+  }
+}
+
+TypedefDecl *Sema::ParseTypedefDecl(Scope *S, Declarator &D, QualType T,
+                                    TypeSourceInfo *TInfo) {
+  assert(D.getIdentifier() && "Wrong callback for declspec without declarator");
+  assert(!T.isNull() && "GetTypeForDeclarator() returned null type");
+
+  if (!TInfo) {
+    assert(D.isInvalidType() && "no declarator info for valid type");
+    TInfo = Context.getTrivialTypeSourceInfo(T);
+  }
+
+  // Scope manipulation handled by caller.
+  TypedefDecl *NewTD = TypedefDecl::Create(Context, CurContext,
+                                           D.getLocStart(),
+                                           D.getIdentifierLoc(),
+                                           D.getIdentifier(),
+                                           TInfo);
+
+  // Bail out immediately if we have an invalid declaration.
+  if (D.isInvalidType()) {
+    NewTD->setInvalidDecl();
+    return NewTD;
+  }
+
+  if (D.getDeclSpec().isModulePrivateSpecified()) {
+    if (CurContext->isFunctionOrMethod())
+      Diag(NewTD->getLocation(), diag::err_module_private_local)
+        << 2 << NewTD->getDeclName()
+        << SourceRange(D.getDeclSpec().getModulePrivateSpecLoc())
+        << FixItHint::CreateRemoval(D.getDeclSpec().getModulePrivateSpecLoc());
+    else
+      NewTD->setModulePrivate();
+  }
+  
+  // C++ [dcl.typedef]p8:
+  //   If the typedef declaration defines an unnamed class (or
+  //   enum), the first typedef-name declared by the declaration
+  //   to be that class type (or enum type) is used to denote the
+  //   class type (or enum type) for linkage purposes only.
+  // We need to check whether the type was declared in the declaration.
+  switch (D.getDeclSpec().getTypeSpecType()) {
+  case TST_enum:
+  case TST_struct:
+  case TST_union:
+  case TST_class: {
+    TagDecl *tagFromDeclSpec = cast<TagDecl>(D.getDeclSpec().getRepAsDecl());
+
+    // Do nothing if the tag is not anonymous or already has an
+    // associated typedef (from an earlier typedef in this decl group).
+    if (tagFromDeclSpec->getIdentifier()) break;
+    if (tagFromDeclSpec->getTypedefNameForAnonDecl()) break;
+
+    // A well-formed anonymous tag must always be a TUK_Definition.
+    assert(tagFromDeclSpec->isThisDeclarationADefinition());
+
+    // The type must match the tag exactly;  no qualifiers allowed.
+    if (!Context.hasSameType(T, Context.getTagDeclType(tagFromDeclSpec)))
+      break;
+
+    // Otherwise, set this is the anon-decl typedef for the tag.
+    tagFromDeclSpec->setTypedefNameForAnonDecl(NewTD);
+    break;
+  }
+    
+  default:
+    break;
+  }
+
+  return NewTD;
+}
+
+
+/// \brief Check that this is a valid underlying type for an enum declaration.
+bool Sema::CheckEnumUnderlyingType(TypeSourceInfo *TI) {
+  SourceLocation UnderlyingLoc = TI->getTypeLoc().getBeginLoc();
+  QualType T = TI->getType();
+
+  if (T->isDependentType() || T->isIntegralType(Context))
+    return false;
+
+  Diag(UnderlyingLoc, diag::err_enum_invalid_underlying) << T;
+  return true;
+}
+
+/// Check whether this is a valid redeclaration of a previous enumeration.
+/// \return true if the redeclaration was invalid.
+bool Sema::CheckEnumRedeclaration(SourceLocation EnumLoc, bool IsScoped,
+                                  QualType EnumUnderlyingTy,
+                                  const EnumDecl *Prev) {
+  bool IsFixed = !EnumUnderlyingTy.isNull();
+
+  if (IsScoped != Prev->isScoped()) {
+    Diag(EnumLoc, diag::err_enum_redeclare_scoped_mismatch)
+      << Prev->isScoped();
+    Diag(Prev->getLocation(), diag::note_previous_use);
+    return true;
+  }
+
+  if (IsFixed && Prev->isFixed()) {
+    if (!EnumUnderlyingTy->isDependentType() &&
+        !Prev->getIntegerType()->isDependentType() &&
+        !Context.hasSameUnqualifiedType(EnumUnderlyingTy,
+                                        Prev->getIntegerType())) {
+      Diag(EnumLoc, diag::err_enum_redeclare_type_mismatch)
+        << EnumUnderlyingTy << Prev->getIntegerType();
+      Diag(Prev->getLocation(), diag::note_previous_use);
+      return true;
+    }
+  } else if (IsFixed != Prev->isFixed()) {
+    Diag(EnumLoc, diag::err_enum_redeclare_fixed_mismatch)
+      << Prev->isFixed();
+    Diag(Prev->getLocation(), diag::note_previous_use);
+    return true;
+  }
+
+  return false;
+}
+
+/// \brief Determine whether a tag with a given kind is acceptable
+/// as a redeclaration of the given tag declaration.
+///
+/// \returns true if the new tag kind is acceptable, false otherwise.
+bool Sema::isAcceptableTagRedeclaration(const TagDecl *Previous,
+                                        TagTypeKind NewTag, bool isDefinition,
+                                        SourceLocation NewTagLoc,
+                                        const IdentifierInfo &Name) {
+  // C++ [dcl.type.elab]p3:
+  //   The class-key or enum keyword present in the
+  //   elaborated-type-specifier shall agree in kind with the
+  //   declaration to which the name in the elaborated-type-specifier
+  //   refers. This rule also applies to the form of
+  //   elaborated-type-specifier that declares a class-name or
+  //   friend class since it can be construed as referring to the
+  //   definition of the class. Thus, in any
+  //   elaborated-type-specifier, the enum keyword shall be used to
+  //   refer to an enumeration (7.2), the union class-key shall be
+  //   used to refer to a union (clause 9), and either the class or
+  //   struct class-key shall be used to refer to a class (clause 9)
+  //   declared using the class or struct class-key.
+  TagTypeKind OldTag = Previous->getTagKind();
+  if (!isDefinition || (NewTag != TTK_Class && NewTag != TTK_Struct))
+    if (OldTag == NewTag)
+      return true;
+
+  if ((OldTag == TTK_Struct || OldTag == TTK_Class) &&
+      (NewTag == TTK_Struct || NewTag == TTK_Class)) {
+    // Warn about the struct/class tag mismatch.
+    bool isTemplate = false;
+    if (const CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(Previous))
+      isTemplate = Record->getDescribedClassTemplate();
+
+    if (!ActiveTemplateInstantiations.empty()) {
+      // In a template instantiation, do not offer fix-its for tag mismatches
+      // since they usually mess up the template instead of fixing the problem.
+      Diag(NewTagLoc, diag::warn_struct_class_tag_mismatch)
+        << (NewTag == TTK_Class) << isTemplate << &Name;
+      return true;
+    }
+
+    if (isDefinition) {
+      // On definitions, check previous tags and issue a fix-it for each
+      // one that doesn't match the current tag.
+      if (Previous->getDefinition()) {
+        // Don't suggest fix-its for redefinitions.
+        return true;
+      }
+
+      bool previousMismatch = false;
+      for (TagDecl::redecl_iterator I(Previous->redecls_begin()),
+           E(Previous->redecls_end()); I != E; ++I) {
+        if (I->getTagKind() != NewTag) {
+          if (!previousMismatch) {
+            previousMismatch = true;
+            Diag(NewTagLoc, diag::warn_struct_class_previous_tag_mismatch)
+              << (NewTag == TTK_Class) << isTemplate << &Name;
+          }
+          Diag(I->getInnerLocStart(), diag::note_struct_class_suggestion)
+            << (NewTag == TTK_Class)
+            << FixItHint::CreateReplacement(I->getInnerLocStart(),
+                                            NewTag == TTK_Class?
+                                            "class" : "struct");
+        }
+      }
+      return true;
+    }
+
+    // Check for a previous definition.  If current tag and definition
+    // are same type, do nothing.  If no definition, but disagree with
+    // with previous tag type, give a warning, but no fix-it.
+    const TagDecl *Redecl = Previous->getDefinition() ?
+                            Previous->getDefinition() : Previous;
+    if (Redecl->getTagKind() == NewTag) {
+      return true;
+    }
+
+    Diag(NewTagLoc, diag::warn_struct_class_tag_mismatch)
+      << (NewTag == TTK_Class)
+      << isTemplate << &Name;
+    Diag(Redecl->getLocation(), diag::note_previous_use);
+
+    // If there is a previous defintion, suggest a fix-it.
+    if (Previous->getDefinition()) {
+        Diag(NewTagLoc, diag::note_struct_class_suggestion)
+          << (Redecl->getTagKind() == TTK_Class)
+          << FixItHint::CreateReplacement(SourceRange(NewTagLoc),
+                        Redecl->getTagKind() == TTK_Class? "class" : "struct");
+    }
+
+    return true;
+  }
+  return false;
+}
+
+/// ActOnTag - This is invoked when we see 'struct foo' or 'struct {'.  In the
+/// former case, Name will be non-null.  In the later case, Name will be null.
+/// TagSpec indicates what kind of tag this is. TUK indicates whether this is a
+/// reference/declaration/definition of a tag.
+Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
+                     SourceLocation KWLoc, CXXScopeSpec &SS,
+                     IdentifierInfo *Name, SourceLocation NameLoc,
+                     AttributeList *Attr, AccessSpecifier AS,
+                     SourceLocation ModulePrivateLoc,
+                     MultiTemplateParamsArg TemplateParameterLists,
+                     bool &OwnedDecl, bool &IsDependent,
+                     SourceLocation ScopedEnumKWLoc,
+                     bool ScopedEnumUsesClassTag,
+                     TypeResult UnderlyingType) {
+  // If this is not a definition, it must have a name.
+  IdentifierInfo *OrigName = Name;
+  assert((Name != 0 || TUK == TUK_Definition) &&
+         "Nameless record must be a definition!");
+  assert(TemplateParameterLists.size() == 0 || TUK != TUK_Reference);
+
+  OwnedDecl = false;
+  TagTypeKind Kind = TypeWithKeyword::getTagTypeKindForTypeSpec(TagSpec);
+  bool ScopedEnum = ScopedEnumKWLoc.isValid();
+
+  // FIXME: Check explicit specializations more carefully.
+  bool isExplicitSpecialization = false;
+  bool Invalid = false;
+
+  // We only need to do this matching if we have template parameters
+  // or a scope specifier, which also conveniently avoids this work
+  // for non-C++ cases.
+  if (TemplateParameterLists.size() > 0 ||
+      (SS.isNotEmpty() && TUK != TUK_Reference)) {
+    if (TemplateParameterList *TemplateParams
+          = MatchTemplateParametersToScopeSpecifier(KWLoc, NameLoc, SS,
+                                                TemplateParameterLists.get(),
+                                                TemplateParameterLists.size(),
+                                                    TUK == TUK_Friend,
+                                                    isExplicitSpecialization,
+                                                    Invalid)) {
+      if (TemplateParams->size() > 0) {
+        // This is a declaration or definition of a class template (which may
+        // be a member of another template).
+
+        if (Invalid)
+          return 0;
+
+        OwnedDecl = false;
+        DeclResult Result = CheckClassTemplate(S, TagSpec, TUK, KWLoc,
+                                               SS, Name, NameLoc, Attr,
+                                               TemplateParams, AS,
+                                               ModulePrivateLoc,
+                                           TemplateParameterLists.size() - 1,
+                 (TemplateParameterList**) TemplateParameterLists.release());
+        return Result.get();
+      } else {
+        // The "template<>" header is extraneous.
+        Diag(TemplateParams->getTemplateLoc(), diag::err_template_tag_noparams)
+          << TypeWithKeyword::getTagTypeKindName(Kind) << Name;
+        isExplicitSpecialization = true;
+      }
+    }
+  }
+
+  // Figure out the underlying type if this a enum declaration. We need to do
+  // this early, because it's needed to detect if this is an incompatible
+  // redeclaration.
+  llvm::PointerUnion<const Type*, TypeSourceInfo*> EnumUnderlying;
+
+  if (Kind == TTK_Enum) {
+    if (UnderlyingType.isInvalid() || (!UnderlyingType.get() && ScopedEnum))
+      // No underlying type explicitly specified, or we failed to parse the
+      // type, default to int.
+      EnumUnderlying = Context.IntTy.getTypePtr();
+    else if (UnderlyingType.get()) {
+      // C++0x 7.2p2: The type-specifier-seq of an enum-base shall name an
+      // integral type; any cv-qualification is ignored.
+      TypeSourceInfo *TI = 0;
+      GetTypeFromParser(UnderlyingType.get(), &TI);
+      EnumUnderlying = TI;
+
+      if (CheckEnumUnderlyingType(TI))
+        // Recover by falling back to int.
+        EnumUnderlying = Context.IntTy.getTypePtr();
+
+      if (DiagnoseUnexpandedParameterPack(TI->getTypeLoc().getBeginLoc(), TI,
+                                          UPPC_FixedUnderlyingType))
+        EnumUnderlying = Context.IntTy.getTypePtr();
+
+    } else if (getLangOpts().MicrosoftMode)
+      // Microsoft enums are always of int type.
+      EnumUnderlying = Context.IntTy.getTypePtr();
+  }
+
+  DeclContext *SearchDC = CurContext;
+  DeclContext *DC = CurContext;
+  bool isStdBadAlloc = false;
+
+  RedeclarationKind Redecl = ForRedeclaration;
+  if (TUK == TUK_Friend || TUK == TUK_Reference)
+    Redecl = NotForRedeclaration;
+
+  LookupResult Previous(*this, Name, NameLoc, LookupTagName, Redecl);
+
+  if (Name && SS.isNotEmpty()) {
+    // We have a nested-name tag ('struct foo::bar').
+
+    // Check for invalid 'foo::'.
+    if (SS.isInvalid()) {
+      Name = 0;
+      goto CreateNewDecl;
+    }
+
+    // If this is a friend or a reference to a class in a dependent
+    // context, don't try to make a decl for it.
+    if (TUK == TUK_Friend || TUK == TUK_Reference) {
+      DC = computeDeclContext(SS, false);
+      if (!DC) {
+        IsDependent = true;
+        return 0;
+      }
+    } else {
+      DC = computeDeclContext(SS, true);
+      if (!DC) {
+        Diag(SS.getRange().getBegin(), diag::err_dependent_nested_name_spec)
+          << SS.getRange();
+        return 0;
+      }
+    }
+
+    if (RequireCompleteDeclContext(SS, DC))
+      return 0;
+
+    SearchDC = DC;
+    // Look-up name inside 'foo::'.
+    LookupQualifiedName(Previous, DC);
+
+    if (Previous.isAmbiguous())
+      return 0;
+
+    if (Previous.empty()) {
+      // Name lookup did not find anything. However, if the
+      // nested-name-specifier refers to the current instantiation,
+      // and that current instantiation has any dependent base
+      // classes, we might find something at instantiation time: treat
+      // this as a dependent elaborated-type-specifier.
+      // But this only makes any sense for reference-like lookups.
+      if (Previous.wasNotFoundInCurrentInstantiation() &&
+          (TUK == TUK_Reference || TUK == TUK_Friend)) {
+        IsDependent = true;
+        return 0;
+      }
+
+      // A tag 'foo::bar' must already exist.
+      Diag(NameLoc, diag::err_not_tag_in_scope) 
+        << Kind << Name << DC << SS.getRange();
+      Name = 0;
+      Invalid = true;
+      goto CreateNewDecl;
+    }
+  } else if (Name) {
+    // If this is a named struct, check to see if there was a previous forward
+    // declaration or definition.
+    // FIXME: We're looking into outer scopes here, even when we
+    // shouldn't be. Doing so can result in ambiguities that we
+    // shouldn't be diagnosing.
+    LookupName(Previous, S);
+
+    if (Previous.isAmbiguous() && 
+        (TUK == TUK_Definition || TUK == TUK_Declaration)) {
+      LookupResult::Filter F = Previous.makeFilter();
+      while (F.hasNext()) {
+        NamedDecl *ND = F.next();
+        if (ND->getDeclContext()->getRedeclContext() != SearchDC)
+          F.erase();
+      }
+      F.done();
+    }
+    
+    // Note:  there used to be some attempt at recovery here.
+    if (Previous.isAmbiguous())
+      return 0;
+
+    if (!getLangOpts().CPlusPlus && TUK != TUK_Reference) {
+      // FIXME: This makes sure that we ignore the contexts associated
+      // with C structs, unions, and enums when looking for a matching
+      // tag declaration or definition. See the similar lookup tweak
+      // in Sema::LookupName; is there a better way to deal with this?
+      while (isa<RecordDecl>(SearchDC) || isa<EnumDecl>(SearchDC))
+        SearchDC = SearchDC->getParent();
+    }
+  } else if (S->isFunctionPrototypeScope()) {
+    // If this is an enum declaration in function prototype scope, set its
+    // initial context to the translation unit.
+    // FIXME: [citation needed]
+    SearchDC = Context.getTranslationUnitDecl();
+  }
+
+  if (Previous.isSingleResult() &&
+      Previous.getFoundDecl()->isTemplateParameter()) {
+    // Maybe we will complain about the shadowed template parameter.
+    DiagnoseTemplateParameterShadow(NameLoc, Previous.getFoundDecl());
+    // Just pretend that we didn't see the previous declaration.
+    Previous.clear();
+  }
+
+  if (getLangOpts().CPlusPlus && Name && DC && StdNamespace &&
+      DC->Equals(getStdNamespace()) && Name->isStr("bad_alloc")) {
+    // This is a declaration of or a reference to "std::bad_alloc".
+    isStdBadAlloc = true;
+    
+    if (Previous.empty() && StdBadAlloc) {
+      // std::bad_alloc has been implicitly declared (but made invisible to
+      // name lookup). Fill in this implicit declaration as the previous 
+      // declaration, so that the declarations get chained appropriately.
+      Previous.addDecl(getStdBadAlloc());
+    }
+  }
+
+  // If we didn't find a previous declaration, and this is a reference
+  // (or friend reference), move to the correct scope.  In C++, we
+  // also need to do a redeclaration lookup there, just in case
+  // there's a shadow friend decl.
+  if (Name && Previous.empty() &&
+      (TUK == TUK_Reference || TUK == TUK_Friend)) {
+    if (Invalid) goto CreateNewDecl;
+    assert(SS.isEmpty());
+
+    if (TUK == TUK_Reference) {
+      // C++ [basic.scope.pdecl]p5:
+      //   -- for an elaborated-type-specifier of the form
+      //
+      //          class-key identifier
+      //
+      //      if the elaborated-type-specifier is used in the
+      //      decl-specifier-seq or parameter-declaration-clause of a
+      //      function defined in namespace scope, the identifier is
+      //      declared as a class-name in the namespace that contains
+      //      the declaration; otherwise, except as a friend
+      //      declaration, the identifier is declared in the smallest
+      //      non-class, non-function-prototype scope that contains the
+      //      declaration.
+      //
+      // C99 6.7.2.3p8 has a similar (but not identical!) provision for
+      // C structs and unions.
+      //
+      // It is an error in C++ to declare (rather than define) an enum
+      // type, including via an elaborated type specifier.  We'll
+      // diagnose that later; for now, declare the enum in the same
+      // scope as we would have picked for any other tag type.
+      //
+      // GNU C also supports this behavior as part of its incomplete
+      // enum types extension, while GNU C++ does not.
+      //
+      // Find the context where we'll be declaring the tag.
+      // FIXME: We would like to maintain the current DeclContext as the
+      // lexical context,
+      while (!SearchDC->isFileContext() && !SearchDC->isFunctionOrMethod())
+        SearchDC = SearchDC->getParent();
+
+      // Find the scope where we'll be declaring the tag.
+      while (S->isClassScope() ||
+             (getLangOpts().CPlusPlus &&
+              S->isFunctionPrototypeScope()) ||
+             ((S->getFlags() & Scope::DeclScope) == 0) ||
+             (S->getEntity() &&
+              ((DeclContext *)S->getEntity())->isTransparentContext()))
+        S = S->getParent();
+    } else {
+      assert(TUK == TUK_Friend);
+      // C++ [namespace.memdef]p3:
+      //   If a friend declaration in a non-local class first declares a
+      //   class or function, the friend class or function is a member of
+      //   the innermost enclosing namespace.
+      SearchDC = SearchDC->getEnclosingNamespaceContext();
+    }
+
+    // In C++, we need to do a redeclaration lookup to properly
+    // diagnose some problems.
+    if (getLangOpts().CPlusPlus) {
+      Previous.setRedeclarationKind(ForRedeclaration);
+      LookupQualifiedName(Previous, SearchDC);
+    }
+  }
+
+  if (!Previous.empty()) {
+    NamedDecl *PrevDecl = (*Previous.begin())->getUnderlyingDecl();
+
+    // It's okay to have a tag decl in the same scope as a typedef
+    // which hides a tag decl in the same scope.  Finding this
+    // insanity with a redeclaration lookup can only actually happen
+    // in C++.
+    //
+    // This is also okay for elaborated-type-specifiers, which is
+    // technically forbidden by the current standard but which is
+    // okay according to the likely resolution of an open issue;
+    // see http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#407
+    if (getLangOpts().CPlusPlus) {
+      if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(PrevDecl)) {
+        if (const TagType *TT = TD->getUnderlyingType()->getAs<TagType>()) {
+          TagDecl *Tag = TT->getDecl();
+          if (Tag->getDeclName() == Name &&
+              Tag->getDeclContext()->getRedeclContext()
+                          ->Equals(TD->getDeclContext()->getRedeclContext())) {
+            PrevDecl = Tag;
+            Previous.clear();
+            Previous.addDecl(Tag);
+            Previous.resolveKind();
+          }
+        }
+      }
+    }
+
+    if (TagDecl *PrevTagDecl = dyn_cast<TagDecl>(PrevDecl)) {
+      // If this is a use of a previous tag, or if the tag is already declared
+      // in the same scope (so that the definition/declaration completes or
+      // rementions the tag), reuse the decl.
+      if (TUK == TUK_Reference || TUK == TUK_Friend ||
+          isDeclInScope(PrevDecl, SearchDC, S, isExplicitSpecialization)) {
+        // Make sure that this wasn't declared as an enum and now used as a
+        // struct or something similar.
+        if (!isAcceptableTagRedeclaration(PrevTagDecl, Kind,
+                                          TUK == TUK_Definition, KWLoc,
+                                          *Name)) {
+          bool SafeToContinue
+            = (PrevTagDecl->getTagKind() != TTK_Enum &&
+               Kind != TTK_Enum);
+          if (SafeToContinue)
+            Diag(KWLoc, diag::err_use_with_wrong_tag)
+              << Name
+              << FixItHint::CreateReplacement(SourceRange(KWLoc),
+                                              PrevTagDecl->getKindName());
+          else
+            Diag(KWLoc, diag::err_use_with_wrong_tag) << Name;
+          Diag(PrevTagDecl->getLocation(), diag::note_previous_use);
+
+          if (SafeToContinue)
+            Kind = PrevTagDecl->getTagKind();
+          else {
+            // Recover by making this an anonymous redefinition.
+            Name = 0;
+            Previous.clear();
+            Invalid = true;
+          }
+        }
+
+        if (Kind == TTK_Enum && PrevTagDecl->getTagKind() == TTK_Enum) {
+          const EnumDecl *PrevEnum = cast<EnumDecl>(PrevTagDecl);
+
+          // If this is an elaborated-type-specifier for a scoped enumeration,
+          // the 'class' keyword is not necessary and not permitted.
+          if (TUK == TUK_Reference || TUK == TUK_Friend) {
+            if (ScopedEnum)
+              Diag(ScopedEnumKWLoc, diag::err_enum_class_reference)
+                << PrevEnum->isScoped()
+                << FixItHint::CreateRemoval(ScopedEnumKWLoc);
+            return PrevTagDecl;
+          }
+
+          QualType EnumUnderlyingTy;
+          if (TypeSourceInfo *TI = EnumUnderlying.dyn_cast<TypeSourceInfo*>())
+            EnumUnderlyingTy = TI->getType();
+          else if (const Type *T = EnumUnderlying.dyn_cast<const Type*>())
+            EnumUnderlyingTy = QualType(T, 0);
+
+          // All conflicts with previous declarations are recovered by
+          // returning the previous declaration, unless this is a definition,
+          // in which case we want the caller to bail out.
+          if (CheckEnumRedeclaration(NameLoc.isValid() ? NameLoc : KWLoc,
+                                     ScopedEnum, EnumUnderlyingTy, PrevEnum))
+            return TUK == TUK_Declaration ? PrevTagDecl : 0;
+        }
+
+        if (!Invalid) {
+          // If this is a use, just return the declaration we found.
+
+          // FIXME: In the future, return a variant or some other clue
+          // for the consumer of this Decl to know it doesn't own it.
+          // For our current ASTs this shouldn't be a problem, but will
+          // need to be changed with DeclGroups.
+          if ((TUK == TUK_Reference && (!PrevTagDecl->getFriendObjectKind() ||
+               getLangOpts().MicrosoftExt)) || TUK == TUK_Friend)
+            return PrevTagDecl;
+
+          // Diagnose attempts to redefine a tag.
+          if (TUK == TUK_Definition) {
+            if (TagDecl *Def = PrevTagDecl->getDefinition()) {
+              // If we're defining a specialization and the previous definition
+              // is from an implicit instantiation, don't emit an error
+              // here; we'll catch this in the general case below.
+              bool IsExplicitSpecializationAfterInstantiation = false;
+              if (isExplicitSpecialization) {
+                if (CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(Def))
+                  IsExplicitSpecializationAfterInstantiation =
+                    RD->getTemplateSpecializationKind() !=
+                    TSK_ExplicitSpecialization;
+                else if (EnumDecl *ED = dyn_cast<EnumDecl>(Def))
+                  IsExplicitSpecializationAfterInstantiation =
+                    ED->getTemplateSpecializationKind() !=
+                    TSK_ExplicitSpecialization;
+              }
+
+              if (!IsExplicitSpecializationAfterInstantiation) {
+                // A redeclaration in function prototype scope in C isn't
+                // visible elsewhere, so merely issue a warning.
+                if (!getLangOpts().CPlusPlus && S->containedInPrototypeScope())
+                  Diag(NameLoc, diag::warn_redefinition_in_param_list) << Name;
+                else
+                  Diag(NameLoc, diag::err_redefinition) << Name;
+                Diag(Def->getLocation(), diag::note_previous_definition);
+                // If this is a redefinition, recover by making this
+                // struct be anonymous, which will make any later
+                // references get the previous definition.
+                Name = 0;
+                Previous.clear();
+                Invalid = true;
+              }
+            } else {
+              // If the type is currently being defined, complain
+              // about a nested redefinition.
+              const TagType *Tag
+                = cast<TagType>(Context.getTagDeclType(PrevTagDecl));
+              if (Tag->isBeingDefined()) {
+                Diag(NameLoc, diag::err_nested_redefinition) << Name;
+                Diag(PrevTagDecl->getLocation(),
+                     diag::note_previous_definition);
+                Name = 0;
+                Previous.clear();
+                Invalid = true;
+              }
+            }
+
+            // Okay, this is definition of a previously declared or referenced
+            // tag PrevDecl. We're going to create a new Decl for it.
+          }
+        }
+        // If we get here we have (another) forward declaration or we
+        // have a definition.  Just create a new decl.
+
+      } else {
+        // If we get here, this is a definition of a new tag type in a nested
+        // scope, e.g. "struct foo; void bar() { struct foo; }", just create a
+        // new decl/type.  We set PrevDecl to NULL so that the entities
+        // have distinct types.
+        Previous.clear();
+      }
+      // If we get here, we're going to create a new Decl. If PrevDecl
+      // is non-NULL, it's a definition of the tag declared by
+      // PrevDecl. If it's NULL, we have a new definition.
+
+
+    // Otherwise, PrevDecl is not a tag, but was found with tag
+    // lookup.  This is only actually possible in C++, where a few
+    // things like templates still live in the tag namespace.
+    } else {
+      // Use a better diagnostic if an elaborated-type-specifier
+      // found the wrong kind of type on the first
+      // (non-redeclaration) lookup.
+      if ((TUK == TUK_Reference || TUK == TUK_Friend) &&
+          !Previous.isForRedeclaration()) {
+        unsigned Kind = 0;
+        if (isa<TypedefDecl>(PrevDecl)) Kind = 1;
+        else if (isa<TypeAliasDecl>(PrevDecl)) Kind = 2;
+        else if (isa<ClassTemplateDecl>(PrevDecl)) Kind = 3;
+        Diag(NameLoc, diag::err_tag_reference_non_tag) << Kind;
+        Diag(PrevDecl->getLocation(), diag::note_declared_at);
+        Invalid = true;
+
+      // Otherwise, only diagnose if the declaration is in scope.
+      } else if (!isDeclInScope(PrevDecl, SearchDC, S, 
+                                isExplicitSpecialization)) {
+        // do nothing
+
+      // Diagnose implicit declarations introduced by elaborated types.
+      } else if (TUK == TUK_Reference || TUK == TUK_Friend) {
+        unsigned Kind = 0;
+        if (isa<TypedefDecl>(PrevDecl)) Kind = 1;
+        else if (isa<TypeAliasDecl>(PrevDecl)) Kind = 2;
+        else if (isa<ClassTemplateDecl>(PrevDecl)) Kind = 3;
+        Diag(NameLoc, diag::err_tag_reference_conflict) << Kind;
+        Diag(PrevDecl->getLocation(), diag::note_previous_decl) << PrevDecl;
+        Invalid = true;
+
+      // Otherwise it's a declaration.  Call out a particularly common
+      // case here.
+      } else if (TypedefNameDecl *TND = dyn_cast<TypedefNameDecl>(PrevDecl)) {
+        unsigned Kind = 0;
+        if (isa<TypeAliasDecl>(PrevDecl)) Kind = 1;
+        Diag(NameLoc, diag::err_tag_definition_of_typedef)
+          << Name << Kind << TND->getUnderlyingType();
+        Diag(PrevDecl->getLocation(), diag::note_previous_decl) << PrevDecl;
+        Invalid = true;
+
+      // Otherwise, diagnose.
+      } else {
+        // The tag name clashes with something else in the target scope,
+        // issue an error and recover by making this tag be anonymous.
+        Diag(NameLoc, diag::err_redefinition_different_kind) << Name;
+        Diag(PrevDecl->getLocation(), diag::note_previous_definition);
+        Name = 0;
+        Invalid = true;
+      }
+
+      // The existing declaration isn't relevant to us; we're in a
+      // new scope, so clear out the previous declaration.
+      Previous.clear();
+    }
+  }
+
+CreateNewDecl:
+
+  TagDecl *PrevDecl = 0;
+  if (Previous.isSingleResult())
+    PrevDecl = cast<TagDecl>(Previous.getFoundDecl());
+
+  // If there is an identifier, use the location of the identifier as the
+  // location of the decl, otherwise use the location of the struct/union
+  // keyword.
+  SourceLocation Loc = NameLoc.isValid() ? NameLoc : KWLoc;
+
+  // Otherwise, create a new declaration. If there is a previous
+  // declaration of the same entity, the two will be linked via
+  // PrevDecl.
+  TagDecl *New;
+
+  bool IsForwardReference = false;
+  if (Kind == TTK_Enum) {
+    // FIXME: Tag decls should be chained to any simultaneous vardecls, e.g.:
+    // enum X { A, B, C } D;    D should chain to X.
+    New = EnumDecl::Create(Context, SearchDC, KWLoc, Loc, Name,
+                           cast_or_null<EnumDecl>(PrevDecl), ScopedEnum,
+                           ScopedEnumUsesClassTag, !EnumUnderlying.isNull());
+    // If this is an undefined enum, warn.
+    if (TUK != TUK_Definition && !Invalid) {
+      TagDecl *Def;
+      if (getLangOpts().CPlusPlus0x && cast<EnumDecl>(New)->isFixed()) {
+        // C++0x: 7.2p2: opaque-enum-declaration.
+        // Conflicts are diagnosed above. Do nothing.
+      }
+      else if (PrevDecl && (Def = cast<EnumDecl>(PrevDecl)->getDefinition())) {
+        Diag(Loc, diag::ext_forward_ref_enum_def)
+          << New;
+        Diag(Def->getLocation(), diag::note_previous_definition);
+      } else {
+        unsigned DiagID = diag::ext_forward_ref_enum;
+        if (getLangOpts().MicrosoftMode)
+          DiagID = diag::ext_ms_forward_ref_enum;
+        else if (getLangOpts().CPlusPlus)
+          DiagID = diag::err_forward_ref_enum;
+        Diag(Loc, DiagID);
+        
+        // If this is a forward-declared reference to an enumeration, make a 
+        // note of it; we won't actually be introducing the declaration into
+        // the declaration context.
+        if (TUK == TUK_Reference)
+          IsForwardReference = true;
+      }
+    }
+
+    if (EnumUnderlying) {
+      EnumDecl *ED = cast<EnumDecl>(New);
+      if (TypeSourceInfo *TI = EnumUnderlying.dyn_cast<TypeSourceInfo*>())
+        ED->setIntegerTypeSourceInfo(TI);
+      else
+        ED->setIntegerType(QualType(EnumUnderlying.get<const Type*>(), 0));
+      ED->setPromotionType(ED->getIntegerType());
+    }
+
+  } else {
+    // struct/union/class
+
+    // FIXME: Tag decls should be chained to any simultaneous vardecls, e.g.:
+    // struct X { int A; } D;    D should chain to X.
+    if (getLangOpts().CPlusPlus) {
+      // FIXME: Look for a way to use RecordDecl for simple structs.
+      New = CXXRecordDecl::Create(Context, Kind, SearchDC, KWLoc, Loc, Name,
+                                  cast_or_null<CXXRecordDecl>(PrevDecl));
+
+      if (isStdBadAlloc && (!StdBadAlloc || getStdBadAlloc()->isImplicit()))
+        StdBadAlloc = cast<CXXRecordDecl>(New);
+    } else
+      New = RecordDecl::Create(Context, Kind, SearchDC, KWLoc, Loc, Name,
+                               cast_or_null<RecordDecl>(PrevDecl));
+  }
+
+  // Maybe add qualifier info.
+  if (SS.isNotEmpty()) {
+    if (SS.isSet()) {
+      // If this is either a declaration or a definition, check the 
+      // nested-name-specifier against the current context. We don't do this
+      // for explicit specializations, because they have similar checking
+      // (with more specific diagnostics) in the call to 
+      // CheckMemberSpecialization, below.
+      if (!isExplicitSpecialization &&
+          (TUK == TUK_Definition || TUK == TUK_Declaration) &&
+          diagnoseQualifiedDeclaration(SS, DC, OrigName, NameLoc))
+        Invalid = true;
+
+      New->setQualifierInfo(SS.getWithLocInContext(Context));
+      if (TemplateParameterLists.size() > 0) {
+        New->setTemplateParameterListsInfo(Context,
+                                           TemplateParameterLists.size(),
+                    (TemplateParameterList**) TemplateParameterLists.release());
+      }
+    }
+    else
+      Invalid = true;
+  }
+
+  if (RecordDecl *RD = dyn_cast<RecordDecl>(New)) {
+    // Add alignment attributes if necessary; these attributes are checked when
+    // the ASTContext lays out the structure.
+    //
+    // It is important for implementing the correct semantics that this
+    // happen here (in act on tag decl). The #pragma pack stack is
+    // maintained as a result of parser callbacks which can occur at
+    // many points during the parsing of a struct declaration (because
+    // the #pragma tokens are effectively skipped over during the
+    // parsing of the struct).
+    AddAlignmentAttributesForRecord(RD);
+    
+    AddMsStructLayoutForRecord(RD);
+  }
+
+  if (ModulePrivateLoc.isValid()) {
+    if (isExplicitSpecialization)
+      Diag(New->getLocation(), diag::err_module_private_specialization)
+        << 2
+        << FixItHint::CreateRemoval(ModulePrivateLoc);
+    // __module_private__ does not apply to local classes. However, we only
+    // diagnose this as an error when the declaration specifiers are
+    // freestanding. Here, we just ignore the __module_private__.
+    else if (!SearchDC->isFunctionOrMethod())
+      New->setModulePrivate();
+  }
+  
+  // If this is a specialization of a member class (of a class template),
+  // check the specialization.
+  if (isExplicitSpecialization && CheckMemberSpecialization(New, Previous))
+    Invalid = true;
+           
+  if (Invalid)
+    New->setInvalidDecl();
+
+  if (Attr)
+    ProcessDeclAttributeList(S, New, Attr);
+
+  // If we're declaring or defining a tag in function prototype scope
+  // in C, note that this type can only be used within the function.
+  if (Name && S->isFunctionPrototypeScope() && !getLangOpts().CPlusPlus)
+    Diag(Loc, diag::warn_decl_in_param_list) << Context.getTagDeclType(New);
+
+  // Set the lexical context. If the tag has a C++ scope specifier, the
+  // lexical context will be different from the semantic context.
+  New->setLexicalDeclContext(CurContext);
+
+  // Mark this as a friend decl if applicable.
+  // In Microsoft mode, a friend declaration also acts as a forward
+  // declaration so we always pass true to setObjectOfFriendDecl to make
+  // the tag name visible.
+  if (TUK == TUK_Friend)
+    New->setObjectOfFriendDecl(/* PreviouslyDeclared = */ !Previous.empty() ||
+                               getLangOpts().MicrosoftExt);
+
+  // Set the access specifier.
+  if (!Invalid && SearchDC->isRecord())
+    SetMemberAccessSpecifier(New, PrevDecl, AS);
+
+  if (TUK == TUK_Definition)
+    New->startDefinition();
+
+  // If this has an identifier, add it to the scope stack.
+  if (TUK == TUK_Friend) {
+    // We might be replacing an existing declaration in the lookup tables;
+    // if so, borrow its access specifier.
+    if (PrevDecl)
+      New->setAccess(PrevDecl->getAccess());
+
+    DeclContext *DC = New->getDeclContext()->getRedeclContext();
+    DC->makeDeclVisibleInContext(New);
+    if (Name) // can be null along some error paths
+      if (Scope *EnclosingScope = getScopeForDeclContext(S, DC))
+        PushOnScopeChains(New, EnclosingScope, /* AddToContext = */ false);
+  } else if (Name) {
+    S = getNonFieldDeclScope(S);
+    PushOnScopeChains(New, S, !IsForwardReference);
+    if (IsForwardReference)
+      SearchDC->makeDeclVisibleInContext(New);
+
+  } else {
+    CurContext->addDecl(New);
+  }
+
+  // If this is the C FILE type, notify the AST context.
+  if (IdentifierInfo *II = New->getIdentifier())
+    if (!New->isInvalidDecl() &&
+        New->getDeclContext()->getRedeclContext()->isTranslationUnit() &&
+        II->isStr("FILE"))
+      Context.setFILEDecl(New);
+
+  // If we were in function prototype scope (and not in C++ mode), add this
+  // tag to the list of decls to inject into the function definition scope.
+  if (S->isFunctionPrototypeScope() && !getLangOpts().CPlusPlus &&
+      InFunctionDeclarator && Name)
+    DeclsInPrototypeScope.push_back(New);
+
+  OwnedDecl = true;
+  return New;
+}
+
+void Sema::ActOnTagStartDefinition(Scope *S, Decl *TagD) {
+  AdjustDeclIfTemplate(TagD);
+  TagDecl *Tag = cast<TagDecl>(TagD);
+  
+  // Enter the tag context.
+  PushDeclContext(S, Tag);
+}
+
+Decl *Sema::ActOnObjCContainerStartDefinition(Decl *IDecl) {
+  assert(isa<ObjCContainerDecl>(IDecl) && 
+         "ActOnObjCContainerStartDefinition - Not ObjCContainerDecl");
+  DeclContext *OCD = cast<DeclContext>(IDecl);
+  assert(getContainingDC(OCD) == CurContext &&
+      "The next DeclContext should be lexically contained in the current one.");
+  CurContext = OCD;
+  return IDecl;
+}
+
+void Sema::ActOnStartCXXMemberDeclarations(Scope *S, Decl *TagD,
+                                           SourceLocation FinalLoc,
+                                           SourceLocation LBraceLoc) {
+  AdjustDeclIfTemplate(TagD);
+  CXXRecordDecl *Record = cast<CXXRecordDecl>(TagD);
+
+  FieldCollector->StartClass();
+
+  if (!Record->getIdentifier())
+    return;
+
+  if (FinalLoc.isValid())
+    Record->addAttr(new (Context) FinalAttr(FinalLoc, Context));
+    
+  // C++ [class]p2:
+  //   [...] The class-name is also inserted into the scope of the
+  //   class itself; this is known as the injected-class-name. For
+  //   purposes of access checking, the injected-class-name is treated
+  //   as if it were a public member name.
+  CXXRecordDecl *InjectedClassName
+    = CXXRecordDecl::Create(Context, Record->getTagKind(), CurContext,
+                            Record->getLocStart(), Record->getLocation(),
+                            Record->getIdentifier(),
+                            /*PrevDecl=*/0,
+                            /*DelayTypeCreation=*/true);
+  Context.getTypeDeclType(InjectedClassName, Record);
+  InjectedClassName->setImplicit();
+  InjectedClassName->setAccess(AS_public);
+  if (ClassTemplateDecl *Template = Record->getDescribedClassTemplate())
+      InjectedClassName->setDescribedClassTemplate(Template);
+  PushOnScopeChains(InjectedClassName, S);
+  assert(InjectedClassName->isInjectedClassName() &&
+         "Broken injected-class-name");
+}
+
+void Sema::ActOnTagFinishDefinition(Scope *S, Decl *TagD,
+                                    SourceLocation RBraceLoc) {
+  AdjustDeclIfTemplate(TagD);
+  TagDecl *Tag = cast<TagDecl>(TagD);
+  Tag->setRBraceLoc(RBraceLoc);
+
+  // Make sure we "complete" the definition even it is invalid.
+  if (Tag->isBeingDefined()) {
+    assert(Tag->isInvalidDecl() && "We should already have completed it");
+    if (RecordDecl *RD = dyn_cast<RecordDecl>(Tag))
+      RD->completeDefinition();
+  }
+
+  if (isa<CXXRecordDecl>(Tag))
+    FieldCollector->FinishClass();
+
+  // Exit this scope of this tag's definition.
+  PopDeclContext();
+                                          
+  // Notify the consumer that we've defined a tag.
+  Consumer.HandleTagDeclDefinition(Tag);
+}
+
+void Sema::ActOnObjCContainerFinishDefinition() {
+  // Exit this scope of this interface definition.
+  PopDeclContext();
+}
+
+void Sema::ActOnObjCTemporaryExitContainerContext(DeclContext *DC) {
+  assert(DC == CurContext && "Mismatch of container contexts");
+  OriginalLexicalContext = DC;
+  ActOnObjCContainerFinishDefinition();
+}
+
+void Sema::ActOnObjCReenterContainerContext(DeclContext *DC) {
+  ActOnObjCContainerStartDefinition(cast<Decl>(DC));
+  OriginalLexicalContext = 0;
+}
+
+void Sema::ActOnTagDefinitionError(Scope *S, Decl *TagD) {
+  AdjustDeclIfTemplate(TagD);
+  TagDecl *Tag = cast<TagDecl>(TagD);
+  Tag->setInvalidDecl();
+
+  // Make sure we "complete" the definition even it is invalid.
+  if (Tag->isBeingDefined()) {
+    if (RecordDecl *RD = dyn_cast<RecordDecl>(Tag))
+      RD->completeDefinition();
+  }
+
+  // We're undoing ActOnTagStartDefinition here, not
+  // ActOnStartCXXMemberDeclarations, so we don't have to mess with
+  // the FieldCollector.
+
+  PopDeclContext();  
+}
+
+// Note that FieldName may be null for anonymous bitfields.
+ExprResult Sema::VerifyBitField(SourceLocation FieldLoc,
+                                IdentifierInfo *FieldName,
+                                QualType FieldTy, Expr *BitWidth,
+                                bool *ZeroWidth) {
+  // Default to true; that shouldn't confuse checks for emptiness
+  if (ZeroWidth)
+    *ZeroWidth = true;
+
+  // C99 6.7.2.1p4 - verify the field type.
+  // C++ 9.6p3: A bit-field shall have integral or enumeration type.
+  if (!FieldTy->isDependentType() && !FieldTy->isIntegralOrEnumerationType()) {
+    // Handle incomplete types with specific error.
+    if (RequireCompleteType(FieldLoc, FieldTy, diag::err_field_incomplete))
+      return ExprError();
+    if (FieldName)
+      return Diag(FieldLoc, diag::err_not_integral_type_bitfield)
+        << FieldName << FieldTy << BitWidth->getSourceRange();
+    return Diag(FieldLoc, diag::err_not_integral_type_anon_bitfield)
+      << FieldTy << BitWidth->getSourceRange();
+  } else if (DiagnoseUnexpandedParameterPack(const_cast<Expr *>(BitWidth),
+                                             UPPC_BitFieldWidth))
+    return ExprError();
+
+  // If the bit-width is type- or value-dependent, don't try to check
+  // it now.
+  if (BitWidth->isValueDependent() || BitWidth->isTypeDependent())
+    return Owned(BitWidth);
+
+  llvm::APSInt Value;
+  ExprResult ICE = VerifyIntegerConstantExpression(BitWidth, &Value);
+  if (ICE.isInvalid())
+    return ICE;
+  BitWidth = ICE.take();
+
+  if (Value != 0 && ZeroWidth)
+    *ZeroWidth = false;
+
+  // Zero-width bitfield is ok for anonymous field.
+  if (Value == 0 && FieldName)
+    return Diag(FieldLoc, diag::err_bitfield_has_zero_width) << FieldName;
+
+  if (Value.isSigned() && Value.isNegative()) {
+    if (FieldName)
+      return Diag(FieldLoc, diag::err_bitfield_has_negative_width)
+               << FieldName << Value.toString(10);
+    return Diag(FieldLoc, diag::err_anon_bitfield_has_negative_width)
+      << Value.toString(10);
+  }
+
+  if (!FieldTy->isDependentType()) {
+    uint64_t TypeSize = Context.getTypeSize(FieldTy);
+    if (Value.getZExtValue() > TypeSize) {
+      if (!getLangOpts().CPlusPlus) {
+        if (FieldName) 
+          return Diag(FieldLoc, diag::err_bitfield_width_exceeds_type_size)
+            << FieldName << (unsigned)Value.getZExtValue() 
+            << (unsigned)TypeSize;
+        
+        return Diag(FieldLoc, diag::err_anon_bitfield_width_exceeds_type_size)
+          << (unsigned)Value.getZExtValue() << (unsigned)TypeSize;
+      }
+      
+      if (FieldName)
+        Diag(FieldLoc, diag::warn_bitfield_width_exceeds_type_size)
+          << FieldName << (unsigned)Value.getZExtValue() 
+          << (unsigned)TypeSize;
+      else
+        Diag(FieldLoc, diag::warn_anon_bitfield_width_exceeds_type_size)
+          << (unsigned)Value.getZExtValue() << (unsigned)TypeSize;        
+    }
+  }
+
+  return Owned(BitWidth);
+}
+
+/// ActOnField - Each field of a C struct/union is passed into this in order
+/// to create a FieldDecl object for it.
+Decl *Sema::ActOnField(Scope *S, Decl *TagD, SourceLocation DeclStart,
+                       Declarator &D, Expr *BitfieldWidth) {
+  FieldDecl *Res = HandleField(S, cast_or_null<RecordDecl>(TagD),
+                               DeclStart, D, static_cast<Expr*>(BitfieldWidth),
+                               /*HasInit=*/false, AS_public);
+  return Res;
+}
+
+/// HandleField - Analyze a field of a C struct or a C++ data member.
+///
+FieldDecl *Sema::HandleField(Scope *S, RecordDecl *Record,
+                             SourceLocation DeclStart,
+                             Declarator &D, Expr *BitWidth, bool HasInit,
+                             AccessSpecifier AS) {
+  IdentifierInfo *II = D.getIdentifier();
+  SourceLocation Loc = DeclStart;
+  if (II) Loc = D.getIdentifierLoc();
+
+  TypeSourceInfo *TInfo = GetTypeForDeclarator(D, S);
+  QualType T = TInfo->getType();
+  if (getLangOpts().CPlusPlus) {
+    CheckExtraCXXDefaultArguments(D);
+
+    if (DiagnoseUnexpandedParameterPack(D.getIdentifierLoc(), TInfo,
+                                        UPPC_DataMemberType)) {
+      D.setInvalidType();
+      T = Context.IntTy;
+      TInfo = Context.getTrivialTypeSourceInfo(T, Loc);
+    }
+  }
+
+  DiagnoseFunctionSpecifiers(D);
+
+  if (D.getDeclSpec().isThreadSpecified())
+    Diag(D.getDeclSpec().getThreadSpecLoc(), diag::err_invalid_thread);
+  if (D.getDeclSpec().isConstexprSpecified())
+    Diag(D.getDeclSpec().getConstexprSpecLoc(), diag::err_invalid_constexpr)
+      << 2;
+  
+  // Check to see if this name was declared as a member previously
+  NamedDecl *PrevDecl = 0;
+  LookupResult Previous(*this, II, Loc, LookupMemberName, ForRedeclaration);
+  LookupName(Previous, S);
+  switch (Previous.getResultKind()) {
+    case LookupResult::Found:
+    case LookupResult::FoundUnresolvedValue:
+      PrevDecl = Previous.getAsSingle<NamedDecl>();
+      break;
+      
+    case LookupResult::FoundOverloaded:
+      PrevDecl = Previous.getRepresentativeDecl();
+      break;
+      
+    case LookupResult::NotFound:
+    case LookupResult::NotFoundInCurrentInstantiation:
+    case LookupResult::Ambiguous:
+      break;
+  }
+  Previous.suppressDiagnostics();
+
+  if (PrevDecl && PrevDecl->isTemplateParameter()) {
+    // Maybe we will complain about the shadowed template parameter.
+    DiagnoseTemplateParameterShadow(D.getIdentifierLoc(), PrevDecl);
+    // Just pretend that we didn't see the previous declaration.
+    PrevDecl = 0;
+  }
+
+  if (PrevDecl && !isDeclInScope(PrevDecl, Record, S))
+    PrevDecl = 0;
+
+  bool Mutable
+    = (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_mutable);
+  SourceLocation TSSL = D.getLocStart();
+  FieldDecl *NewFD
+    = CheckFieldDecl(II, T, TInfo, Record, Loc, Mutable, BitWidth, HasInit,
+                     TSSL, AS, PrevDecl, &D);
+
+  if (NewFD->isInvalidDecl())
+    Record->setInvalidDecl();
+
+  if (D.getDeclSpec().isModulePrivateSpecified())
+    NewFD->setModulePrivate();
+  
+  if (NewFD->isInvalidDecl() && PrevDecl) {
+    // Don't introduce NewFD into scope; there's already something
+    // with the same name in the same scope.
+  } else if (II) {
+    PushOnScopeChains(NewFD, S);
+  } else
+    Record->addDecl(NewFD);
+
+  return NewFD;
+}
+
+/// \brief Build a new FieldDecl and check its well-formedness.
+///
+/// This routine builds a new FieldDecl given the fields name, type,
+/// record, etc. \p PrevDecl should refer to any previous declaration
+/// with the same name and in the same scope as the field to be
+/// created.
+///
+/// \returns a new FieldDecl.
+///
+/// \todo The Declarator argument is a hack. It will be removed once
+FieldDecl *Sema::CheckFieldDecl(DeclarationName Name, QualType T,
+                                TypeSourceInfo *TInfo,
+                                RecordDecl *Record, SourceLocation Loc,
+                                bool Mutable, Expr *BitWidth, bool HasInit,
+                                SourceLocation TSSL,
+                                AccessSpecifier AS, NamedDecl *PrevDecl,
+                                Declarator *D) {
+  IdentifierInfo *II = Name.getAsIdentifierInfo();
+  bool InvalidDecl = false;
+  if (D) InvalidDecl = D->isInvalidType();
+
+  // If we receive a broken type, recover by assuming 'int' and
+  // marking this declaration as invalid.
+  if (T.isNull()) {
+    InvalidDecl = true;
+    T = Context.IntTy;
+  }
+
+  QualType EltTy = Context.getBaseElementType(T);
+  if (!EltTy->isDependentType()) {
+    if (RequireCompleteType(Loc, EltTy, diag::err_field_incomplete)) {
+      // Fields of incomplete type force their record to be invalid.
+      Record->setInvalidDecl();
+      InvalidDecl = true;
+    } else {
+      NamedDecl *Def;
+      EltTy->isIncompleteType(&Def);
+      if (Def && Def->isInvalidDecl()) {
+        Record->setInvalidDecl();
+        InvalidDecl = true;
+      }
+    }
+  }
+
+  // C99 6.7.2.1p8: A member of a structure or union may have any type other
+  // than a variably modified type.
+  if (!InvalidDecl && T->isVariablyModifiedType()) {
+    bool SizeIsNegative;
+    llvm::APSInt Oversized;
+    QualType FixedTy = TryToFixInvalidVariablyModifiedType(T, Context,
+                                                           SizeIsNegative,
+                                                           Oversized);
+    if (!FixedTy.isNull()) {
+      Diag(Loc, diag::warn_illegal_constant_array_size);
+      T = FixedTy;
+    } else {
+      if (SizeIsNegative)
+        Diag(Loc, diag::err_typecheck_negative_array_size);
+      else if (Oversized.getBoolValue())
+        Diag(Loc, diag::err_array_too_large)
+          << Oversized.toString(10);
+      else
+        Diag(Loc, diag::err_typecheck_field_variable_size);
+      InvalidDecl = true;
+    }
+  }
+
+  // Fields can not have abstract class types
+  if (!InvalidDecl && RequireNonAbstractType(Loc, T,
+                                             diag::err_abstract_type_in_decl,
+                                             AbstractFieldType))
+    InvalidDecl = true;
+
+  bool ZeroWidth = false;
+  // If this is declared as a bit-field, check the bit-field.
+  if (!InvalidDecl && BitWidth) {
+    BitWidth = VerifyBitField(Loc, II, T, BitWidth, &ZeroWidth).take();
+    if (!BitWidth) {
+      InvalidDecl = true;
+      BitWidth = 0;
+      ZeroWidth = false;
+    }
+  }
+
+  // Check that 'mutable' is consistent with the type of the declaration.
+  if (!InvalidDecl && Mutable) {
+    unsigned DiagID = 0;
+    if (T->isReferenceType())
+      DiagID = diag::err_mutable_reference;
+    else if (T.isConstQualified())
+      DiagID = diag::err_mutable_const;
+
+    if (DiagID) {
+      SourceLocation ErrLoc = Loc;
+      if (D && D->getDeclSpec().getStorageClassSpecLoc().isValid())
+        ErrLoc = D->getDeclSpec().getStorageClassSpecLoc();
+      Diag(ErrLoc, DiagID);
+      Mutable = false;
+      InvalidDecl = true;
+    }
+  }
+
+  FieldDecl *NewFD = FieldDecl::Create(Context, Record, TSSL, Loc, II, T, TInfo,
+                                       BitWidth, Mutable, HasInit);
+  if (InvalidDecl)
+    NewFD->setInvalidDecl();
+
+  if (PrevDecl && !isa<TagDecl>(PrevDecl)) {
+    Diag(Loc, diag::err_duplicate_member) << II;
+    Diag(PrevDecl->getLocation(), diag::note_previous_declaration);
+    NewFD->setInvalidDecl();
+  }
+
+  if (!InvalidDecl && getLangOpts().CPlusPlus) {
+    if (Record->isUnion()) {
+      if (const RecordType *RT = EltTy->getAs<RecordType>()) {
+        CXXRecordDecl* RDecl = cast<CXXRecordDecl>(RT->getDecl());
+        if (RDecl->getDefinition()) {
+          // C++ [class.union]p1: An object of a class with a non-trivial
+          // constructor, a non-trivial copy constructor, a non-trivial
+          // destructor, or a non-trivial copy assignment operator
+          // cannot be a member of a union, nor can an array of such
+          // objects.
+          if (CheckNontrivialField(NewFD))
+            NewFD->setInvalidDecl();
+        }
+      }
+
+      // C++ [class.union]p1: If a union contains a member of reference type,
+      // the program is ill-formed.
+      if (EltTy->isReferenceType()) {
+        Diag(NewFD->getLocation(), diag::err_union_member_of_reference_type)
+          << NewFD->getDeclName() << EltTy;
+        NewFD->setInvalidDecl();
+      }
+    }
+  }
+
+  // FIXME: We need to pass in the attributes given an AST
+  // representation, not a parser representation.
+  if (D)
+    // FIXME: What to pass instead of TUScope?
+    ProcessDeclAttributes(TUScope, NewFD, *D);
+
+  // In auto-retain/release, infer strong retension for fields of
+  // retainable type.
+  if (getLangOpts().ObjCAutoRefCount && inferObjCARCLifetime(NewFD))
+    NewFD->setInvalidDecl();
+
+  if (T.isObjCGCWeak())
+    Diag(Loc, diag::warn_attribute_weak_on_field);
+
+  NewFD->setAccess(AS);
+  return NewFD;
+}
+
+bool Sema::CheckNontrivialField(FieldDecl *FD) {
+  assert(FD);
+  assert(getLangOpts().CPlusPlus && "valid check only for C++");
+
+  if (FD->isInvalidDecl())
+    return true;
+
+  QualType EltTy = Context.getBaseElementType(FD->getType());
+  if (const RecordType *RT = EltTy->getAs<RecordType>()) {
+    CXXRecordDecl* RDecl = cast<CXXRecordDecl>(RT->getDecl());
+    if (RDecl->getDefinition()) {
+      // We check for copy constructors before constructors
+      // because otherwise we'll never get complaints about
+      // copy constructors.
+
+      CXXSpecialMember member = CXXInvalid;
+      if (!RDecl->hasTrivialCopyConstructor())
+        member = CXXCopyConstructor;
+      else if (!RDecl->hasTrivialDefaultConstructor())
+        member = CXXDefaultConstructor;
+      else if (!RDecl->hasTrivialCopyAssignment())
+        member = CXXCopyAssignment;
+      else if (!RDecl->hasTrivialDestructor())
+        member = CXXDestructor;
+
+      if (member != CXXInvalid) {
+        if (!getLangOpts().CPlusPlus0x &&
+            getLangOpts().ObjCAutoRefCount && RDecl->hasObjectMember()) {
+          // Objective-C++ ARC: it is an error to have a non-trivial field of
+          // a union. However, system headers in Objective-C programs 
+          // occasionally have Objective-C lifetime objects within unions,
+          // and rather than cause the program to fail, we make those 
+          // members unavailable.
+          SourceLocation Loc = FD->getLocation();
+          if (getSourceManager().isInSystemHeader(Loc)) {
+            if (!FD->hasAttr<UnavailableAttr>())
+              FD->addAttr(new (Context) UnavailableAttr(Loc, Context,
+                                  "this system field has retaining ownership"));
+            return false;
+          }
+        }
+
+        Diag(FD->getLocation(), getLangOpts().CPlusPlus0x ?
+               diag::warn_cxx98_compat_nontrivial_union_or_anon_struct_member :
+               diag::err_illegal_union_or_anon_struct_member)
+          << (int)FD->getParent()->isUnion() << FD->getDeclName() << member;
+        DiagnoseNontrivial(RT, member);
+        return !getLangOpts().CPlusPlus0x;
+      }
+    }
+  }
+  
+  return false;
+}
+
+/// If the given constructor is user-provided, produce a diagnostic explaining
+/// that it makes the class non-trivial.
+static bool DiagnoseNontrivialUserProvidedCtor(Sema &S, QualType QT,
+                                               CXXConstructorDecl *CD,
+                                               Sema::CXXSpecialMember CSM) {
+  if (!CD->isUserProvided())
+    return false;
+
+  SourceLocation CtorLoc = CD->getLocation();
+  S.Diag(CtorLoc, diag::note_nontrivial_user_defined) << QT << CSM;
+  return true;
+}
+
+/// DiagnoseNontrivial - Given that a class has a non-trivial
+/// special member, figure out why.
+void Sema::DiagnoseNontrivial(const RecordType* T, CXXSpecialMember member) {
+  QualType QT(T, 0U);
+  CXXRecordDecl* RD = cast<CXXRecordDecl>(T->getDecl());
+
+  // Check whether the member was user-declared.
+  switch (member) {
+  case CXXInvalid:
+    break;
+
+  case CXXDefaultConstructor:
+    if (RD->hasUserDeclaredConstructor()) {
+      typedef CXXRecordDecl::ctor_iterator ctor_iter;
+      for (ctor_iter CI = RD->ctor_begin(), CE = RD->ctor_end(); CI != CE; ++CI)
+        if (DiagnoseNontrivialUserProvidedCtor(*this, QT, *CI, member))
+          return;
+
+      // No user-provided constructors; look for constructor templates.
+      typedef CXXRecordDecl::specific_decl_iterator<FunctionTemplateDecl>
+          tmpl_iter;
+      for (tmpl_iter TI(RD->decls_begin()), TE(RD->decls_end());
+           TI != TE; ++TI) {
+        CXXConstructorDecl *CD =
+            dyn_cast<CXXConstructorDecl>(TI->getTemplatedDecl());
+        if (CD && DiagnoseNontrivialUserProvidedCtor(*this, QT, CD, member))
+          return;
+      }
+    }
+    break;
+
+  case CXXCopyConstructor:
+    if (RD->hasUserDeclaredCopyConstructor()) {
+      SourceLocation CtorLoc =
+        RD->getCopyConstructor(0)->getLocation();
+      Diag(CtorLoc, diag::note_nontrivial_user_defined) << QT << member;
+      return;
+    }
+    break;
+
+  case CXXMoveConstructor:
+    if (RD->hasUserDeclaredMoveConstructor()) {
+      SourceLocation CtorLoc = RD->getMoveConstructor()->getLocation();
+      Diag(CtorLoc, diag::note_nontrivial_user_defined) << QT << member;
+      return;
+    }
+    break;
+
+  case CXXCopyAssignment:
+    if (RD->hasUserDeclaredCopyAssignment()) {
+      // FIXME: this should use the location of the copy
+      // assignment, not the type.
+      SourceLocation TyLoc = RD->getLocStart();
+      Diag(TyLoc, diag::note_nontrivial_user_defined) << QT << member;
+      return;
+    }
+    break;
+
+  case CXXMoveAssignment:
+    if (RD->hasUserDeclaredMoveAssignment()) {
+      SourceLocation AssignLoc = RD->getMoveAssignmentOperator()->getLocation();
+      Diag(AssignLoc, diag::note_nontrivial_user_defined) << QT << member;
+      return;
+    }
+    break;
+
+  case CXXDestructor:
+    if (RD->hasUserDeclaredDestructor()) {
+      SourceLocation DtorLoc = LookupDestructor(RD)->getLocation();
+      Diag(DtorLoc, diag::note_nontrivial_user_defined) << QT << member;
+      return;
+    }
+    break;
+  }
+
+  typedef CXXRecordDecl::base_class_iterator base_iter;
+
+  // Virtual bases and members inhibit trivial copying/construction,
+  // but not trivial destruction.
+  if (member != CXXDestructor) {
+    // Check for virtual bases.  vbases includes indirect virtual bases,
+    // so we just iterate through the direct bases.
+    for (base_iter bi = RD->bases_begin(), be = RD->bases_end(); bi != be; ++bi)
+      if (bi->isVirtual()) {
+        SourceLocation BaseLoc = bi->getLocStart();
+        Diag(BaseLoc, diag::note_nontrivial_has_virtual) << QT << 1;
+        return;
+      }
+
+    // Check for virtual methods.
+    typedef CXXRecordDecl::method_iterator meth_iter;
+    for (meth_iter mi = RD->method_begin(), me = RD->method_end(); mi != me;
+         ++mi) {
+      if (mi->isVirtual()) {
+        SourceLocation MLoc = mi->getLocStart();
+        Diag(MLoc, diag::note_nontrivial_has_virtual) << QT << 0;
+        return;
+      }
+    }
+  }
+
+  bool (CXXRecordDecl::*hasTrivial)() const;
+  switch (member) {
+  case CXXDefaultConstructor:
+    hasTrivial = &CXXRecordDecl::hasTrivialDefaultConstructor; break;
+  case CXXCopyConstructor:
+    hasTrivial = &CXXRecordDecl::hasTrivialCopyConstructor; break;
+  case CXXCopyAssignment:
+    hasTrivial = &CXXRecordDecl::hasTrivialCopyAssignment; break;
+  case CXXDestructor:
+    hasTrivial = &CXXRecordDecl::hasTrivialDestructor; break;
+  default:
+    llvm_unreachable("unexpected special member");
+  }
+
+  // Check for nontrivial bases (and recurse).
+  for (base_iter bi = RD->bases_begin(), be = RD->bases_end(); bi != be; ++bi) {
+    const RecordType *BaseRT = bi->getType()->getAs<RecordType>();
+    assert(BaseRT && "Don't know how to handle dependent bases");
+    CXXRecordDecl *BaseRecTy = cast<CXXRecordDecl>(BaseRT->getDecl());
+    if (!(BaseRecTy->*hasTrivial)()) {
+      SourceLocation BaseLoc = bi->getLocStart();
+      Diag(BaseLoc, diag::note_nontrivial_has_nontrivial) << QT << 1 << member;
+      DiagnoseNontrivial(BaseRT, member);
+      return;
+    }
+  }
+
+  // Check for nontrivial members (and recurse).
+  typedef RecordDecl::field_iterator field_iter;
+  for (field_iter fi = RD->field_begin(), fe = RD->field_end(); fi != fe;
+       ++fi) {
+    QualType EltTy = Context.getBaseElementType((*fi)->getType());
+    if (const RecordType *EltRT = EltTy->getAs<RecordType>()) {
+      CXXRecordDecl* EltRD = cast<CXXRecordDecl>(EltRT->getDecl());
+
+      if (!(EltRD->*hasTrivial)()) {
+        SourceLocation FLoc = (*fi)->getLocation();
+        Diag(FLoc, diag::note_nontrivial_has_nontrivial) << QT << 0 << member;
+        DiagnoseNontrivial(EltRT, member);
+        return;
+      }
+    }
+    
+    if (EltTy->isObjCLifetimeType()) {
+      switch (EltTy.getObjCLifetime()) {
+      case Qualifiers::OCL_None:
+      case Qualifiers::OCL_ExplicitNone:
+        break;
+          
+      case Qualifiers::OCL_Autoreleasing:
+      case Qualifiers::OCL_Weak:
+      case Qualifiers::OCL_Strong:
+        Diag((*fi)->getLocation(), diag::note_nontrivial_objc_ownership)
+          << QT << EltTy.getObjCLifetime();
+        return;
+      }
+    }
+  }
+
+  llvm_unreachable("found no explanation for non-trivial member");
+}
+
+/// TranslateIvarVisibility - Translate visibility from a token ID to an
+///  AST enum value.
+static ObjCIvarDecl::AccessControl
+TranslateIvarVisibility(tok::ObjCKeywordKind ivarVisibility) {
+  switch (ivarVisibility) {
+  default: llvm_unreachable("Unknown visitibility kind");
+  case tok::objc_private: return ObjCIvarDecl::Private;
+  case tok::objc_public: return ObjCIvarDecl::Public;
+  case tok::objc_protected: return ObjCIvarDecl::Protected;
+  case tok::objc_package: return ObjCIvarDecl::Package;
+  }
+}
+
+/// ActOnIvar - Each ivar field of an objective-c class is passed into this
+/// in order to create an IvarDecl object for it.
+Decl *Sema::ActOnIvar(Scope *S,
+                                SourceLocation DeclStart,
+                                Declarator &D, Expr *BitfieldWidth,
+                                tok::ObjCKeywordKind Visibility) {
+
+  IdentifierInfo *II = D.getIdentifier();
+  Expr *BitWidth = (Expr*)BitfieldWidth;
+  SourceLocation Loc = DeclStart;
+  if (II) Loc = D.getIdentifierLoc();
+
+  // FIXME: Unnamed fields can be handled in various different ways, for
+  // example, unnamed unions inject all members into the struct namespace!
+
+  TypeSourceInfo *TInfo = GetTypeForDeclarator(D, S);
+  QualType T = TInfo->getType();
+
+  if (BitWidth) {
+    // 6.7.2.1p3, 6.7.2.1p4
+    BitWidth = VerifyBitField(Loc, II, T, BitWidth).take();
+    if (!BitWidth)
+      D.setInvalidType();
+  } else {
+    // Not a bitfield.
+
+    // validate II.
+
+  }
+  if (T->isReferenceType()) {
+    Diag(Loc, diag::err_ivar_reference_type);
+    D.setInvalidType();
+  }
+  // C99 6.7.2.1p8: A member of a structure or union may have any type other
+  // than a variably modified type.
+  else if (T->isVariablyModifiedType()) {
+    Diag(Loc, diag::err_typecheck_ivar_variable_size);
+    D.setInvalidType();
+  }
+
+  // Get the visibility (access control) for this ivar.
+  ObjCIvarDecl::AccessControl ac =
+    Visibility != tok::objc_not_keyword ? TranslateIvarVisibility(Visibility)
+                                        : ObjCIvarDecl::None;
+  // Must set ivar's DeclContext to its enclosing interface.
+  ObjCContainerDecl *EnclosingDecl = cast<ObjCContainerDecl>(CurContext);
+  if (!EnclosingDecl || EnclosingDecl->isInvalidDecl())
+    return 0;
+  ObjCContainerDecl *EnclosingContext;
+  if (ObjCImplementationDecl *IMPDecl =
+      dyn_cast<ObjCImplementationDecl>(EnclosingDecl)) {
+    if (!LangOpts.ObjCNonFragileABI2) {
+    // Case of ivar declared in an implementation. Context is that of its class.
+      EnclosingContext = IMPDecl->getClassInterface();
+      assert(EnclosingContext && "Implementation has no class interface!");
+    }
+    else
+      EnclosingContext = EnclosingDecl;
+  } else {
+    if (ObjCCategoryDecl *CDecl = 
+        dyn_cast<ObjCCategoryDecl>(EnclosingDecl)) {
+      if (!LangOpts.ObjCNonFragileABI2 || !CDecl->IsClassExtension()) {
+        Diag(Loc, diag::err_misplaced_ivar) << CDecl->IsClassExtension();
+        return 0;
+      }
+    }
+    EnclosingContext = EnclosingDecl;
+  }
+
+  // Construct the decl.
+  ObjCIvarDecl *NewID = ObjCIvarDecl::Create(Context, EnclosingContext,
+                                             DeclStart, Loc, II, T,
+                                             TInfo, ac, (Expr *)BitfieldWidth);
+
+  if (II) {
+    NamedDecl *PrevDecl = LookupSingleName(S, II, Loc, LookupMemberName,
+                                           ForRedeclaration);
+    if (PrevDecl && isDeclInScope(PrevDecl, EnclosingContext, S)
+        && !isa<TagDecl>(PrevDecl)) {
+      Diag(Loc, diag::err_duplicate_member) << II;
+      Diag(PrevDecl->getLocation(), diag::note_previous_declaration);
+      NewID->setInvalidDecl();
+    }
+  }
+
+  // Process attributes attached to the ivar.
+  ProcessDeclAttributes(S, NewID, D);
+
+  if (D.isInvalidType())
+    NewID->setInvalidDecl();
+
+  // In ARC, infer 'retaining' for ivars of retainable type.
+  if (getLangOpts().ObjCAutoRefCount && inferObjCARCLifetime(NewID))
+    NewID->setInvalidDecl();
+
+  if (D.getDeclSpec().isModulePrivateSpecified())
+    NewID->setModulePrivate();
+  
+  if (II) {
+    // FIXME: When interfaces are DeclContexts, we'll need to add
+    // these to the interface.
+    S->AddDecl(NewID);
+    IdResolver.AddDecl(NewID);
+  }
+
+  return NewID;
+}
+
+/// ActOnLastBitfield - This routine handles synthesized bitfields rules for 
+/// class and class extensions. For every class @interface and class 
+/// extension @interface, if the last ivar is a bitfield of any type, 
+/// then add an implicit `char :0` ivar to the end of that interface.
+void Sema::ActOnLastBitfield(SourceLocation DeclLoc,
+                             SmallVectorImpl<Decl *> &AllIvarDecls) {
+  if (!LangOpts.ObjCNonFragileABI2 || AllIvarDecls.empty())
+    return;
+  
+  Decl *ivarDecl = AllIvarDecls[AllIvarDecls.size()-1];
+  ObjCIvarDecl *Ivar = cast<ObjCIvarDecl>(ivarDecl);
+  
+  if (!Ivar->isBitField() || Ivar->getBitWidthValue(Context) == 0)
+    return;
+  ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(CurContext);
+  if (!ID) {
+    if (ObjCCategoryDecl *CD = dyn_cast<ObjCCategoryDecl>(CurContext)) {
+      if (!CD->IsClassExtension())
+        return;
+    }
+    // No need to add this to end of @implementation.
+    else
+      return;
+  }
+  // All conditions are met. Add a new bitfield to the tail end of ivars.
+  llvm::APInt Zero(Context.getTypeSize(Context.IntTy), 0);
+  Expr * BW = IntegerLiteral::Create(Context, Zero, Context.IntTy, DeclLoc);
+
+  Ivar = ObjCIvarDecl::Create(Context, cast<ObjCContainerDecl>(CurContext),
+                              DeclLoc, DeclLoc, 0,
+                              Context.CharTy, 
+                              Context.getTrivialTypeSourceInfo(Context.CharTy,
+                                                               DeclLoc),
+                              ObjCIvarDecl::Private, BW,
+                              true);
+  AllIvarDecls.push_back(Ivar);
+}
+
+void Sema::ActOnFields(Scope* S,
+                       SourceLocation RecLoc, Decl *EnclosingDecl,
+                       llvm::ArrayRef<Decl *> Fields,
+                       SourceLocation LBrac, SourceLocation RBrac,
+                       AttributeList *Attr) {
+  assert(EnclosingDecl && "missing record or interface decl");
+
+  // If the decl this is being inserted into is invalid, then it may be a
+  // redeclaration or some other bogus case.  Don't try to add fields to it.
+  if (EnclosingDecl->isInvalidDecl())
+    return;
+
+  RecordDecl *Record = dyn_cast<RecordDecl>(EnclosingDecl);
+
+  // Start counting up the number of named members; make sure to include
+  // members of anonymous structs and unions in the total.
+  unsigned NumNamedMembers = 0;
+  if (Record) {
+    for (RecordDecl::decl_iterator i = Record->decls_begin(),
+                                   e = Record->decls_end(); i != e; i++) {
+      if (IndirectFieldDecl *IFD = dyn_cast<IndirectFieldDecl>(*i))
+        if (IFD->getDeclName())
+          ++NumNamedMembers;
+    }
+  }
+
+  // Verify that all the fields are okay.
+  SmallVector<FieldDecl*, 32> RecFields;
+
+  bool ARCErrReported = false;
+  for (llvm::ArrayRef<Decl *>::iterator i = Fields.begin(), end = Fields.end();
+       i != end; ++i) {
+    FieldDecl *FD = cast<FieldDecl>(*i);
+
+    // Get the type for the field.
+    const Type *FDTy = FD->getType().getTypePtr();
+
+    if (!FD->isAnonymousStructOrUnion()) {
+      // Remember all fields written by the user.
+      RecFields.push_back(FD);
+    }
+
+    // If the field is already invalid for some reason, don't emit more
+    // diagnostics about it.
+    if (FD->isInvalidDecl()) {
+      EnclosingDecl->setInvalidDecl();
+      continue;
+    }
+
+    // C99 6.7.2.1p2:
+    //   A structure or union shall not contain a member with
+    //   incomplete or function type (hence, a structure shall not
+    //   contain an instance of itself, but may contain a pointer to
+    //   an instance of itself), except that the last member of a
+    //   structure with more than one named member may have incomplete
+    //   array type; such a structure (and any union containing,
+    //   possibly recursively, a member that is such a structure)
+    //   shall not be a member of a structure or an element of an
+    //   array.
+    if (FDTy->isFunctionType()) {
+      // Field declared as a function.
+      Diag(FD->getLocation(), diag::err_field_declared_as_function)
+        << FD->getDeclName();
+      FD->setInvalidDecl();
+      EnclosingDecl->setInvalidDecl();
+      continue;
+    } else if (FDTy->isIncompleteArrayType() && Record && 
+               ((i + 1 == Fields.end() && !Record->isUnion()) ||
+                ((getLangOpts().MicrosoftExt ||
+                  getLangOpts().CPlusPlus) &&
+                 (i + 1 == Fields.end() || Record->isUnion())))) {
+      // Flexible array member.
+      // Microsoft and g++ is more permissive regarding flexible array.
+      // It will accept flexible array in union and also
+      // as the sole element of a struct/class.
+      if (getLangOpts().MicrosoftExt) {
+        if (Record->isUnion()) 
+          Diag(FD->getLocation(), diag::ext_flexible_array_union_ms)
+            << FD->getDeclName();
+        else if (Fields.size() == 1) 
+          Diag(FD->getLocation(), diag::ext_flexible_array_empty_aggregate_ms)
+            << FD->getDeclName() << Record->getTagKind();
+      } else if (getLangOpts().CPlusPlus) {
+        if (Record->isUnion()) 
+          Diag(FD->getLocation(), diag::ext_flexible_array_union_gnu)
+            << FD->getDeclName();
+        else if (Fields.size() == 1) 
+          Diag(FD->getLocation(), diag::ext_flexible_array_empty_aggregate_gnu)
+            << FD->getDeclName() << Record->getTagKind();
+      } else if (!getLangOpts().C99) {
+      if (Record->isUnion())
+        Diag(FD->getLocation(), diag::ext_flexible_array_union_gnu)
+          << FD->getDeclName();
+      else
+        Diag(FD->getLocation(), diag::ext_c99_flexible_array_member)
+          << FD->getDeclName() << Record->getTagKind();
+      } else if (NumNamedMembers < 1) {
+        Diag(FD->getLocation(), diag::err_flexible_array_empty_struct)
+          << FD->getDeclName();
+        FD->setInvalidDecl();
+        EnclosingDecl->setInvalidDecl();
+        continue;
+      }
+      if (!FD->getType()->isDependentType() &&
+          !Context.getBaseElementType(FD->getType()).isPODType(Context)) {
+        Diag(FD->getLocation(), diag::err_flexible_array_has_nonpod_type)
+          << FD->getDeclName() << FD->getType();
+        FD->setInvalidDecl();
+        EnclosingDecl->setInvalidDecl();
+        continue;
+      }
+      // Okay, we have a legal flexible array member at the end of the struct.
+      if (Record)
+        Record->setHasFlexibleArrayMember(true);
+    } else if (!FDTy->isDependentType() &&
+               RequireCompleteType(FD->getLocation(), FD->getType(),
+                                   diag::err_field_incomplete)) {
+      // Incomplete type
+      FD->setInvalidDecl();
+      EnclosingDecl->setInvalidDecl();
+      continue;
+    } else if (const RecordType *FDTTy = FDTy->getAs<RecordType>()) {
+      if (FDTTy->getDecl()->hasFlexibleArrayMember()) {
+        // If this is a member of a union, then entire union becomes "flexible".
+        if (Record && Record->isUnion()) {
+          Record->setHasFlexibleArrayMember(true);
+        } else {
+          // If this is a struct/class and this is not the last element, reject
+          // it.  Note that GCC supports variable sized arrays in the middle of
+          // structures.
+          if (i + 1 != Fields.end())
+            Diag(FD->getLocation(), diag::ext_variable_sized_type_in_struct)
+              << FD->getDeclName() << FD->getType();
+          else {
+            // We support flexible arrays at the end of structs in
+            // other structs as an extension.
+            Diag(FD->getLocation(), diag::ext_flexible_array_in_struct)
+              << FD->getDeclName();
+            if (Record)
+              Record->setHasFlexibleArrayMember(true);
+          }
+        }
+      }
+      if (Record && FDTTy->getDecl()->hasObjectMember())
+        Record->setHasObjectMember(true);
+    } else if (FDTy->isObjCObjectType()) {
+      /// A field cannot be an Objective-c object
+      Diag(FD->getLocation(), diag::err_statically_allocated_object)
+        << FixItHint::CreateInsertion(FD->getLocation(), "*");
+      QualType T = Context.getObjCObjectPointerType(FD->getType());
+      FD->setType(T);
+    } 
+    else if (!getLangOpts().CPlusPlus) {
+      if (getLangOpts().ObjCAutoRefCount && Record && !ARCErrReported) {
+        // It's an error in ARC if a field has lifetime.
+        // We don't want to report this in a system header, though,
+        // so we just make the field unavailable.
+        // FIXME: that's really not sufficient; we need to make the type
+        // itself invalid to, say, initialize or copy.
+        QualType T = FD->getType();
+        Qualifiers::ObjCLifetime lifetime = T.getObjCLifetime();
+        if (lifetime && lifetime != Qualifiers::OCL_ExplicitNone) {
+          SourceLocation loc = FD->getLocation();
+          if (getSourceManager().isInSystemHeader(loc)) {
+            if (!FD->hasAttr<UnavailableAttr>()) {
+              FD->addAttr(new (Context) UnavailableAttr(loc, Context,
+                                "this system field has retaining ownership"));
+            }
+          } else {
+            Diag(FD->getLocation(), diag::err_arc_objc_object_in_struct) 
+              << T->isBlockPointerType();
+          }
+          ARCErrReported = true;
+        }
+      }
+      else if (getLangOpts().ObjC1 &&
+               getLangOpts().getGC() != LangOptions::NonGC &&
+               Record && !Record->hasObjectMember()) {
+        if (FD->getType()->isObjCObjectPointerType() ||
+            FD->getType().isObjCGCStrong())
+          Record->setHasObjectMember(true);
+        else if (Context.getAsArrayType(FD->getType())) {
+          QualType BaseType = Context.getBaseElementType(FD->getType());
+          if (BaseType->isRecordType() && 
+              BaseType->getAs<RecordType>()->getDecl()->hasObjectMember())
+            Record->setHasObjectMember(true);
+          else if (BaseType->isObjCObjectPointerType() ||
+                   BaseType.isObjCGCStrong())
+                 Record->setHasObjectMember(true);
+        }
+      }
+    }
+    // Keep track of the number of named members.
+    if (FD->getIdentifier())
+      ++NumNamedMembers;
+  }
+
+  // Okay, we successfully defined 'Record'.
+  if (Record) {
+    bool Completed = false;
+    if (CXXRecordDecl *CXXRecord = dyn_cast<CXXRecordDecl>(Record)) {
+      if (!CXXRecord->isInvalidDecl()) {
+        // Set access bits correctly on the directly-declared conversions.
+        UnresolvedSetImpl *Convs = CXXRecord->getConversionFunctions();
+        for (UnresolvedSetIterator I = Convs->begin(), E = Convs->end(); 
+             I != E; ++I)
+          Convs->setAccess(I, (*I)->getAccess());
+        
+        if (!CXXRecord->isDependentType()) {
+          // Objective-C Automatic Reference Counting:
+          //   If a class has a non-static data member of Objective-C pointer
+          //   type (or array thereof), it is a non-POD type and its
+          //   default constructor (if any), copy constructor, copy assignment
+          //   operator, and destructor are non-trivial.
+          //
+          // This rule is also handled by CXXRecordDecl::completeDefinition(). 
+          // However, here we check whether this particular class is only 
+          // non-POD because of the presence of an Objective-C pointer member. 
+          // If so, objects of this type cannot be shared between code compiled 
+          // with instant objects and code compiled with manual retain/release.
+          if (getLangOpts().ObjCAutoRefCount &&
+              CXXRecord->hasObjectMember() && 
+              CXXRecord->getLinkage() == ExternalLinkage) {
+            if (CXXRecord->isPOD()) {
+              Diag(CXXRecord->getLocation(), 
+                   diag::warn_arc_non_pod_class_with_object_member)
+               << CXXRecord;
+            } else {
+              // FIXME: Fix-Its would be nice here, but finding a good location
+              // for them is going to be tricky.
+              if (CXXRecord->hasTrivialCopyConstructor())
+                Diag(CXXRecord->getLocation(), 
+                     diag::warn_arc_trivial_member_function_with_object_member)
+                  << CXXRecord << 0;
+              if (CXXRecord->hasTrivialCopyAssignment())
+                Diag(CXXRecord->getLocation(), 
+                     diag::warn_arc_trivial_member_function_with_object_member)
+                << CXXRecord << 1;
+              if (CXXRecord->hasTrivialDestructor())
+                Diag(CXXRecord->getLocation(), 
+                     diag::warn_arc_trivial_member_function_with_object_member)
+                << CXXRecord << 2;
+            }
+          }
+          
+          // Adjust user-defined destructor exception spec.
+          if (getLangOpts().CPlusPlus0x &&
+              CXXRecord->hasUserDeclaredDestructor())
+            AdjustDestructorExceptionSpec(CXXRecord,CXXRecord->getDestructor());
+
+          // Add any implicitly-declared members to this class.
+          AddImplicitlyDeclaredMembersToClass(CXXRecord);
+
+          // If we have virtual base classes, we may end up finding multiple 
+          // final overriders for a given virtual function. Check for this 
+          // problem now.
+          if (CXXRecord->getNumVBases()) {
+            CXXFinalOverriderMap FinalOverriders;
+            CXXRecord->getFinalOverriders(FinalOverriders);
+            
+            for (CXXFinalOverriderMap::iterator M = FinalOverriders.begin(), 
+                                             MEnd = FinalOverriders.end();
+                 M != MEnd; ++M) {
+              for (OverridingMethods::iterator SO = M->second.begin(), 
+                                            SOEnd = M->second.end();
+                   SO != SOEnd; ++SO) {
+                assert(SO->second.size() > 0 && 
+                       "Virtual function without overridding functions?");
+                if (SO->second.size() == 1)
+                  continue;
+                
+                // C++ [class.virtual]p2:
+                //   In a derived class, if a virtual member function of a base
+                //   class subobject has more than one final overrider the
+                //   program is ill-formed.
+                Diag(Record->getLocation(), diag::err_multiple_final_overriders)
+                  << (NamedDecl *)M->first << Record;
+                Diag(M->first->getLocation(), 
+                     diag::note_overridden_virtual_function);
+                for (OverridingMethods::overriding_iterator 
+                          OM = SO->second.begin(), 
+                       OMEnd = SO->second.end();
+                     OM != OMEnd; ++OM)
+                  Diag(OM->Method->getLocation(), diag::note_final_overrider)
+                    << (NamedDecl *)M->first << OM->Method->getParent();
+                
+                Record->setInvalidDecl();
+              }
+            }
+            CXXRecord->completeDefinition(&FinalOverriders);
+            Completed = true;
+          }
+        }
+      }
+    }
+    
+    if (!Completed)
+      Record->completeDefinition();
+
+  } else {
+    ObjCIvarDecl **ClsFields =
+      reinterpret_cast<ObjCIvarDecl**>(RecFields.data());
+    if (ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(EnclosingDecl)) {
+      ID->setEndOfDefinitionLoc(RBrac);
+      // Add ivar's to class's DeclContext.
+      for (unsigned i = 0, e = RecFields.size(); i != e; ++i) {
+        ClsFields[i]->setLexicalDeclContext(ID);
+        ID->addDecl(ClsFields[i]);
+      }
+      // Must enforce the rule that ivars in the base classes may not be
+      // duplicates.
+      if (ID->getSuperClass())
+        DiagnoseDuplicateIvars(ID, ID->getSuperClass());
+    } else if (ObjCImplementationDecl *IMPDecl =
+                  dyn_cast<ObjCImplementationDecl>(EnclosingDecl)) {
+      assert(IMPDecl && "ActOnFields - missing ObjCImplementationDecl");
+      for (unsigned I = 0, N = RecFields.size(); I != N; ++I)
+        // Ivar declared in @implementation never belongs to the implementation.
+        // Only it is in implementation's lexical context.
+        ClsFields[I]->setLexicalDeclContext(IMPDecl);
+      CheckImplementationIvars(IMPDecl, ClsFields, RecFields.size(), RBrac);
+      IMPDecl->setIvarLBraceLoc(LBrac);
+      IMPDecl->setIvarRBraceLoc(RBrac);
+    } else if (ObjCCategoryDecl *CDecl = 
+                dyn_cast<ObjCCategoryDecl>(EnclosingDecl)) {
+      // case of ivars in class extension; all other cases have been
+      // reported as errors elsewhere.
+      // FIXME. Class extension does not have a LocEnd field.
+      // CDecl->setLocEnd(RBrac);
+      // Add ivar's to class extension's DeclContext.
+      // Diagnose redeclaration of private ivars.
+      ObjCInterfaceDecl *IDecl = CDecl->getClassInterface();
+      for (unsigned i = 0, e = RecFields.size(); i != e; ++i) {
+        if (IDecl) {
+          if (const ObjCIvarDecl *ClsIvar = 
+              IDecl->getIvarDecl(ClsFields[i]->getIdentifier())) {
+            Diag(ClsFields[i]->getLocation(), 
+                 diag::err_duplicate_ivar_declaration); 
+            Diag(ClsIvar->getLocation(), diag::note_previous_definition);
+            continue;
+          }
+          for (const ObjCCategoryDecl *ClsExtDecl = 
+                IDecl->getFirstClassExtension();
+               ClsExtDecl; ClsExtDecl = ClsExtDecl->getNextClassExtension()) {
+            if (const ObjCIvarDecl *ClsExtIvar = 
+                ClsExtDecl->getIvarDecl(ClsFields[i]->getIdentifier())) {
+              Diag(ClsFields[i]->getLocation(), 
+                   diag::err_duplicate_ivar_declaration); 
+              Diag(ClsExtIvar->getLocation(), diag::note_previous_definition);
+              continue;
+            }
+          }
+        }
+        ClsFields[i]->setLexicalDeclContext(CDecl);
+        CDecl->addDecl(ClsFields[i]);
+      }
+      CDecl->setIvarLBraceLoc(LBrac);
+      CDecl->setIvarRBraceLoc(RBrac);
+    }
+  }
+
+  if (Attr)
+    ProcessDeclAttributeList(S, Record, Attr);
+
+  // If there's a #pragma GCC visibility in scope, and this isn't a subclass,
+  // set the visibility of this record.
+  if (Record && !Record->getDeclContext()->isRecord())
+    AddPushedVisibilityAttribute(Record);
+}
+
+/// \brief Determine whether the given integral value is representable within
+/// the given type T.
+static bool isRepresentableIntegerValue(ASTContext &Context,
+                                        llvm::APSInt &Value,
+                                        QualType T) {
+  assert(T->isIntegralType(Context) && "Integral type required!");
+  unsigned BitWidth = Context.getIntWidth(T);
+  
+  if (Value.isUnsigned() || Value.isNonNegative()) {
+    if (T->isSignedIntegerOrEnumerationType()) 
+      --BitWidth;
+    return Value.getActiveBits() <= BitWidth;
+  }  
+  return Value.getMinSignedBits() <= BitWidth;
+}
+
+// \brief Given an integral type, return the next larger integral type
+// (or a NULL type of no such type exists).
+static QualType getNextLargerIntegralType(ASTContext &Context, QualType T) {
+  // FIXME: Int128/UInt128 support, which also needs to be introduced into 
+  // enum checking below.
+  assert(T->isIntegralType(Context) && "Integral type required!");
+  const unsigned NumTypes = 4;
+  QualType SignedIntegralTypes[NumTypes] = { 
+    Context.ShortTy, Context.IntTy, Context.LongTy, Context.LongLongTy
+  };
+  QualType UnsignedIntegralTypes[NumTypes] = { 
+    Context.UnsignedShortTy, Context.UnsignedIntTy, Context.UnsignedLongTy, 
+    Context.UnsignedLongLongTy
+  };
+  
+  unsigned BitWidth = Context.getTypeSize(T);
+  QualType *Types = T->isSignedIntegerOrEnumerationType()? SignedIntegralTypes
+                                                        : UnsignedIntegralTypes;
+  for (unsigned I = 0; I != NumTypes; ++I)
+    if (Context.getTypeSize(Types[I]) > BitWidth)
+      return Types[I];
+  
+  return QualType();
+}
+
+EnumConstantDecl *Sema::CheckEnumConstant(EnumDecl *Enum,
+                                          EnumConstantDecl *LastEnumConst,
+                                          SourceLocation IdLoc,
+                                          IdentifierInfo *Id,
+                                          Expr *Val) {
+  unsigned IntWidth = Context.getTargetInfo().getIntWidth();
+  llvm::APSInt EnumVal(IntWidth);
+  QualType EltTy;
+
+  if (Val && DiagnoseUnexpandedParameterPack(Val, UPPC_EnumeratorValue))
+    Val = 0;
+
+  if (Val)
+    Val = DefaultLvalueConversion(Val).take();
+
+  if (Val) {
+    if (Enum->isDependentType() || Val->isTypeDependent())
+      EltTy = Context.DependentTy;
+    else {
+      SourceLocation ExpLoc;
+      if (getLangOpts().CPlusPlus0x && Enum->isFixed() &&
+          !getLangOpts().MicrosoftMode) {
+        // C++11 [dcl.enum]p5: If the underlying type is fixed, [...] the
+        // constant-expression in the enumerator-definition shall be a converted
+        // constant expression of the underlying type.
+        EltTy = Enum->getIntegerType();
+        ExprResult Converted =
+          CheckConvertedConstantExpression(Val, EltTy, EnumVal,
+                                           CCEK_Enumerator);
+        if (Converted.isInvalid())
+          Val = 0;
+        else
+          Val = Converted.take();
+      } else if (!Val->isValueDependent() &&
+                 !(Val = VerifyIntegerConstantExpression(Val,
+                                                         &EnumVal).take())) {
+        // C99 6.7.2.2p2: Make sure we have an integer constant expression.
+      } else {
+        if (Enum->isFixed()) {
+          EltTy = Enum->getIntegerType();
+
+          // In Obj-C and Microsoft mode, require the enumeration value to be
+          // representable in the underlying type of the enumeration. In C++11,
+          // we perform a non-narrowing conversion as part of converted constant
+          // expression checking.
+          if (!isRepresentableIntegerValue(Context, EnumVal, EltTy)) {
+            if (getLangOpts().MicrosoftMode) {
+              Diag(IdLoc, diag::ext_enumerator_too_large) << EltTy;
+              Val = ImpCastExprToType(Val, EltTy, CK_IntegralCast).take();
+            } else
+              Diag(IdLoc, diag::err_enumerator_too_large) << EltTy;
+          } else
+            Val = ImpCastExprToType(Val, EltTy, CK_IntegralCast).take();
+        } else if (getLangOpts().CPlusPlus) {
+          // C++11 [dcl.enum]p5:
+          //   If the underlying type is not fixed, the type of each enumerator
+          //   is the type of its initializing value:
+          //     - If an initializer is specified for an enumerator, the 
+          //       initializing value has the same type as the expression.
+          EltTy = Val->getType();
+        } else {
+          // C99 6.7.2.2p2:
+          //   The expression that defines the value of an enumeration constant
+          //   shall be an integer constant expression that has a value
+          //   representable as an int.
+
+          // Complain if the value is not representable in an int.
+          if (!isRepresentableIntegerValue(Context, EnumVal, Context.IntTy))
+            Diag(IdLoc, diag::ext_enum_value_not_int)
+              << EnumVal.toString(10) << Val->getSourceRange()
+              << (EnumVal.isUnsigned() || EnumVal.isNonNegative());
+          else if (!Context.hasSameType(Val->getType(), Context.IntTy)) {
+            // Force the type of the expression to 'int'.
+            Val = ImpCastExprToType(Val, Context.IntTy, CK_IntegralCast).take();
+          }
+          EltTy = Val->getType();
+        }
+      }
+    }
+  }
+
+  if (!Val) {
+    if (Enum->isDependentType())
+      EltTy = Context.DependentTy;
+    else if (!LastEnumConst) {
+      // C++0x [dcl.enum]p5:
+      //   If the underlying type is not fixed, the type of each enumerator
+      //   is the type of its initializing value:
+      //     - If no initializer is specified for the first enumerator, the 
+      //       initializing value has an unspecified integral type.
+      //
+      // GCC uses 'int' for its unspecified integral type, as does 
+      // C99 6.7.2.2p3.
+      if (Enum->isFixed()) {
+        EltTy = Enum->getIntegerType();
+      }
+      else {
+        EltTy = Context.IntTy;
+      }
+    } else {
+      // Assign the last value + 1.
+      EnumVal = LastEnumConst->getInitVal();
+      ++EnumVal;
+      EltTy = LastEnumConst->getType();
+
+      // Check for overflow on increment.
+      if (EnumVal < LastEnumConst->getInitVal()) {
+        // C++0x [dcl.enum]p5:
+        //   If the underlying type is not fixed, the type of each enumerator
+        //   is the type of its initializing value:
+        //
+        //     - Otherwise the type of the initializing value is the same as
+        //       the type of the initializing value of the preceding enumerator
+        //       unless the incremented value is not representable in that type,
+        //       in which case the type is an unspecified integral type 
+        //       sufficient to contain the incremented value. If no such type
+        //       exists, the program is ill-formed.
+        QualType T = getNextLargerIntegralType(Context, EltTy);
+        if (T.isNull() || Enum->isFixed()) {
+          // There is no integral type larger enough to represent this 
+          // value. Complain, then allow the value to wrap around.
+          EnumVal = LastEnumConst->getInitVal();
+          EnumVal = EnumVal.zext(EnumVal.getBitWidth() * 2);
+          ++EnumVal;
+          if (Enum->isFixed())
+            // When the underlying type is fixed, this is ill-formed.
+            Diag(IdLoc, diag::err_enumerator_wrapped)
+              << EnumVal.toString(10)
+              << EltTy;
+          else
+            Diag(IdLoc, diag::warn_enumerator_too_large)
+              << EnumVal.toString(10);
+        } else {
+          EltTy = T;
+        }
+        
+        // Retrieve the last enumerator's value, extent that type to the
+        // type that is supposed to be large enough to represent the incremented
+        // value, then increment.
+        EnumVal = LastEnumConst->getInitVal();
+        EnumVal.setIsSigned(EltTy->isSignedIntegerOrEnumerationType());
+        EnumVal = EnumVal.zextOrTrunc(Context.getIntWidth(EltTy));
+        ++EnumVal;        
+        
+        // If we're not in C++, diagnose the overflow of enumerator values,
+        // which in C99 means that the enumerator value is not representable in
+        // an int (C99 6.7.2.2p2). However, we support GCC's extension that
+        // permits enumerator values that are representable in some larger
+        // integral type.
+        if (!getLangOpts().CPlusPlus && !T.isNull())
+          Diag(IdLoc, diag::warn_enum_value_overflow);
+      } else if (!getLangOpts().CPlusPlus &&
+                 !isRepresentableIntegerValue(Context, EnumVal, EltTy)) {
+        // Enforce C99 6.7.2.2p2 even when we compute the next value.
+        Diag(IdLoc, diag::ext_enum_value_not_int)
+          << EnumVal.toString(10) << 1;
+      }
+    }
+  }
+
+  if (!EltTy->isDependentType()) {
+    // Make the enumerator value match the signedness and size of the 
+    // enumerator's type.
+    EnumVal = EnumVal.extOrTrunc(Context.getIntWidth(EltTy));
+    EnumVal.setIsSigned(EltTy->isSignedIntegerOrEnumerationType());
+  }
+  
+  return EnumConstantDecl::Create(Context, Enum, IdLoc, Id, EltTy,
+                                  Val, EnumVal);
+}
+
+
+Decl *Sema::ActOnEnumConstant(Scope *S, Decl *theEnumDecl, Decl *lastEnumConst,
+                              SourceLocation IdLoc, IdentifierInfo *Id,
+                              AttributeList *Attr,
+                              SourceLocation EqualLoc, Expr *Val) {
+  EnumDecl *TheEnumDecl = cast<EnumDecl>(theEnumDecl);
+  EnumConstantDecl *LastEnumConst =
+    cast_or_null<EnumConstantDecl>(lastEnumConst);
+
+  // The scope passed in may not be a decl scope.  Zip up the scope tree until
+  // we find one that is.
+  S = getNonFieldDeclScope(S);
+
+  // Verify that there isn't already something declared with this name in this
+  // scope.
+  NamedDecl *PrevDecl = LookupSingleName(S, Id, IdLoc, LookupOrdinaryName,
+                                         ForRedeclaration);
+  if (PrevDecl && PrevDecl->isTemplateParameter()) {
+    // Maybe we will complain about the shadowed template parameter.
+    DiagnoseTemplateParameterShadow(IdLoc, PrevDecl);
+    // Just pretend that we didn't see the previous declaration.
+    PrevDecl = 0;
+  }
+
+  if (PrevDecl) {
+    // When in C++, we may get a TagDecl with the same name; in this case the
+    // enum constant will 'hide' the tag.
+    assert((getLangOpts().CPlusPlus || !isa<TagDecl>(PrevDecl)) &&
+           "Received TagDecl when not in C++!");
+    if (!isa<TagDecl>(PrevDecl) && isDeclInScope(PrevDecl, CurContext, S)) {
+      if (isa<EnumConstantDecl>(PrevDecl))
+        Diag(IdLoc, diag::err_redefinition_of_enumerator) << Id;
+      else
+        Diag(IdLoc, diag::err_redefinition) << Id;
+      Diag(PrevDecl->getLocation(), diag::note_previous_definition);
+      return 0;
+    }
+  }
+
+  // C++ [class.mem]p13:
+  //   If T is the name of a class, then each of the following shall have a 
+  //   name different from T:
+  //     - every enumerator of every member of class T that is an enumerated 
+  //       type
+  if (CXXRecordDecl *Record
+                      = dyn_cast<CXXRecordDecl>(
+                             TheEnumDecl->getDeclContext()->getRedeclContext()))
+    if (Record->getIdentifier() && Record->getIdentifier() == Id)
+      Diag(IdLoc, diag::err_member_name_of_class) << Id;
+  
+  EnumConstantDecl *New =
+    CheckEnumConstant(TheEnumDecl, LastEnumConst, IdLoc, Id, Val);
+
+  if (New) {
+    // Process attributes.
+    if (Attr) ProcessDeclAttributeList(S, New, Attr);
+
+    // Register this decl in the current scope stack.
+    New->setAccess(TheEnumDecl->getAccess());
+    PushOnScopeChains(New, S);
+  }
+
+  return New;
+}
+
+void Sema::ActOnEnumBody(SourceLocation EnumLoc, SourceLocation LBraceLoc,
+                         SourceLocation RBraceLoc, Decl *EnumDeclX,
+                         Decl **Elements, unsigned NumElements,
+                         Scope *S, AttributeList *Attr) {
+  EnumDecl *Enum = cast<EnumDecl>(EnumDeclX);
+  QualType EnumType = Context.getTypeDeclType(Enum);
+
+  if (Attr)
+    ProcessDeclAttributeList(S, Enum, Attr);
+
+  if (Enum->isDependentType()) {
+    for (unsigned i = 0; i != NumElements; ++i) {
+      EnumConstantDecl *ECD =
+        cast_or_null<EnumConstantDecl>(Elements[i]);
+      if (!ECD) continue;
+
+      ECD->setType(EnumType);
+    }
+
+    Enum->completeDefinition(Context.DependentTy, Context.DependentTy, 0, 0);
+    return;
+  }
+
+  // TODO: If the result value doesn't fit in an int, it must be a long or long
+  // long value.  ISO C does not support this, but GCC does as an extension,
+  // emit a warning.
+  unsigned IntWidth = Context.getTargetInfo().getIntWidth();
+  unsigned CharWidth = Context.getTargetInfo().getCharWidth();
+  unsigned ShortWidth = Context.getTargetInfo().getShortWidth();
+
+  // Verify that all the values are okay, compute the size of the values, and
+  // reverse the list.
+  unsigned NumNegativeBits = 0;
+  unsigned NumPositiveBits = 0;
+
+  // Keep track of whether all elements have type int.
+  bool AllElementsInt = true;
+
+  for (unsigned i = 0; i != NumElements; ++i) {
+    EnumConstantDecl *ECD =
+      cast_or_null<EnumConstantDecl>(Elements[i]);
+    if (!ECD) continue;  // Already issued a diagnostic.
+
+    const llvm::APSInt &InitVal = ECD->getInitVal();
+
+    // Keep track of the size of positive and negative values.
+    if (InitVal.isUnsigned() || InitVal.isNonNegative())
+      NumPositiveBits = std::max(NumPositiveBits,
+                                 (unsigned)InitVal.getActiveBits());
+    else
+      NumNegativeBits = std::max(NumNegativeBits,
+                                 (unsigned)InitVal.getMinSignedBits());
+
+    // Keep track of whether every enum element has type int (very commmon).
+    if (AllElementsInt)
+      AllElementsInt = ECD->getType() == Context.IntTy;
+  }
+
+  // Figure out the type that should be used for this enum.
+  QualType BestType;
+  unsigned BestWidth;
+
+  // C++0x N3000 [conv.prom]p3:
+  //   An rvalue of an unscoped enumeration type whose underlying
+  //   type is not fixed can be converted to an rvalue of the first
+  //   of the following types that can represent all the values of
+  //   the enumeration: int, unsigned int, long int, unsigned long
+  //   int, long long int, or unsigned long long int.
+  // C99 6.4.4.3p2:
+  //   An identifier declared as an enumeration constant has type int.
+  // The C99 rule is modified by a gcc extension 
+  QualType BestPromotionType;
+
+  bool Packed = Enum->getAttr<PackedAttr>() ? true : false;
+  // -fshort-enums is the equivalent to specifying the packed attribute on all
+  // enum definitions.
+  if (LangOpts.ShortEnums)
+    Packed = true;
+
+  if (Enum->isFixed()) {
+    BestType = Enum->getIntegerType();
+    if (BestType->isPromotableIntegerType())
+      BestPromotionType = Context.getPromotedIntegerType(BestType);
+    else
+      BestPromotionType = BestType;
+    // We don't need to set BestWidth, because BestType is going to be the type
+    // of the enumerators, but we do anyway because otherwise some compilers
+    // warn that it might be used uninitialized.
+    BestWidth = CharWidth;
+  }
+  else if (NumNegativeBits) {
+    // If there is a negative value, figure out the smallest integer type (of
+    // int/long/longlong) that fits.
+    // If it's packed, check also if it fits a char or a short.
+    if (Packed && NumNegativeBits <= CharWidth && NumPositiveBits < CharWidth) {
+      BestType = Context.SignedCharTy;
+      BestWidth = CharWidth;
+    } else if (Packed && NumNegativeBits <= ShortWidth &&
+               NumPositiveBits < ShortWidth) {
+      BestType = Context.ShortTy;
+      BestWidth = ShortWidth;
+    } else if (NumNegativeBits <= IntWidth && NumPositiveBits < IntWidth) {
+      BestType = Context.IntTy;
+      BestWidth = IntWidth;
+    } else {
+      BestWidth = Context.getTargetInfo().getLongWidth();
+
+      if (NumNegativeBits <= BestWidth && NumPositiveBits < BestWidth) {
+        BestType = Context.LongTy;
+      } else {
+        BestWidth = Context.getTargetInfo().getLongLongWidth();
+
+        if (NumNegativeBits > BestWidth || NumPositiveBits >= BestWidth)
+          Diag(Enum->getLocation(), diag::warn_enum_too_large);
+        BestType = Context.LongLongTy;
+      }
+    }
+    BestPromotionType = (BestWidth <= IntWidth ? Context.IntTy : BestType);
+  } else {
+    // If there is no negative value, figure out the smallest type that fits
+    // all of the enumerator values.
+    // If it's packed, check also if it fits a char or a short.
+    if (Packed && NumPositiveBits <= CharWidth) {
+      BestType = Context.UnsignedCharTy;
+      BestPromotionType = Context.IntTy;
+      BestWidth = CharWidth;
+    } else if (Packed && NumPositiveBits <= ShortWidth) {
+      BestType = Context.UnsignedShortTy;
+      BestPromotionType = Context.IntTy;
+      BestWidth = ShortWidth;
+    } else if (NumPositiveBits <= IntWidth) {
+      BestType = Context.UnsignedIntTy;
+      BestWidth = IntWidth;
+      BestPromotionType
+        = (NumPositiveBits == BestWidth || !getLangOpts().CPlusPlus)
+                           ? Context.UnsignedIntTy : Context.IntTy;
+    } else if (NumPositiveBits <=
+               (BestWidth = Context.getTargetInfo().getLongWidth())) {
+      BestType = Context.UnsignedLongTy;
+      BestPromotionType
+        = (NumPositiveBits == BestWidth || !getLangOpts().CPlusPlus)
+                           ? Context.UnsignedLongTy : Context.LongTy;
+    } else {
+      BestWidth = Context.getTargetInfo().getLongLongWidth();
+      assert(NumPositiveBits <= BestWidth &&
+             "How could an initializer get larger than ULL?");
+      BestType = Context.UnsignedLongLongTy;
+      BestPromotionType
+        = (NumPositiveBits == BestWidth || !getLangOpts().CPlusPlus)
+                           ? Context.UnsignedLongLongTy : Context.LongLongTy;
+    }
+  }
+
+  // Loop over all of the enumerator constants, changing their types to match
+  // the type of the enum if needed.
+  for (unsigned i = 0; i != NumElements; ++i) {
+    EnumConstantDecl *ECD = cast_or_null<EnumConstantDecl>(Elements[i]);
+    if (!ECD) continue;  // Already issued a diagnostic.
+
+    // Standard C says the enumerators have int type, but we allow, as an
+    // extension, the enumerators to be larger than int size.  If each
+    // enumerator value fits in an int, type it as an int, otherwise type it the
+    // same as the enumerator decl itself.  This means that in "enum { X = 1U }"
+    // that X has type 'int', not 'unsigned'.
+
+    // Determine whether the value fits into an int.
+    llvm::APSInt InitVal = ECD->getInitVal();
+
+    // If it fits into an integer type, force it.  Otherwise force it to match
+    // the enum decl type.
+    QualType NewTy;
+    unsigned NewWidth;
+    bool NewSign;
+    if (!getLangOpts().CPlusPlus &&
+        !Enum->isFixed() &&
+        isRepresentableIntegerValue(Context, InitVal, Context.IntTy)) {
+      NewTy = Context.IntTy;
+      NewWidth = IntWidth;
+      NewSign = true;
+    } else if (ECD->getType() == BestType) {
+      // Already the right type!
+      if (getLangOpts().CPlusPlus)
+        // C++ [dcl.enum]p4: Following the closing brace of an
+        // enum-specifier, each enumerator has the type of its
+        // enumeration.
+        ECD->setType(EnumType);
+      continue;
+    } else {
+      NewTy = BestType;
+      NewWidth = BestWidth;
+      NewSign = BestType->isSignedIntegerOrEnumerationType();
+    }
+
+    // Adjust the APSInt value.
+    InitVal = InitVal.extOrTrunc(NewWidth);
+    InitVal.setIsSigned(NewSign);
+    ECD->setInitVal(InitVal);
+
+    // Adjust the Expr initializer and type.
+    if (ECD->getInitExpr() &&
+        !Context.hasSameType(NewTy, ECD->getInitExpr()->getType()))
+      ECD->setInitExpr(ImplicitCastExpr::Create(Context, NewTy,
+                                                CK_IntegralCast,
+                                                ECD->getInitExpr(),
+                                                /*base paths*/ 0,
+                                                VK_RValue));
+    if (getLangOpts().CPlusPlus)
+      // C++ [dcl.enum]p4: Following the closing brace of an
+      // enum-specifier, each enumerator has the type of its
+      // enumeration.
+      ECD->setType(EnumType);
+    else
+      ECD->setType(NewTy);
+  }
+
+  Enum->completeDefinition(BestType, BestPromotionType,
+                           NumPositiveBits, NumNegativeBits);
+
+  // If we're declaring a function, ensure this decl isn't forgotten about -
+  // it needs to go into the function scope.
+  if (InFunctionDeclarator)
+    DeclsInPrototypeScope.push_back(Enum);
+
+}
+
+Decl *Sema::ActOnFileScopeAsmDecl(Expr *expr,
+                                  SourceLocation StartLoc,
+                                  SourceLocation EndLoc) {
+  StringLiteral *AsmString = cast<StringLiteral>(expr);
+
+  FileScopeAsmDecl *New = FileScopeAsmDecl::Create(Context, CurContext,
+                                                   AsmString, StartLoc,
+                                                   EndLoc);
+  CurContext->addDecl(New);
+  return New;
+}
+
+DeclResult Sema::ActOnModuleImport(SourceLocation AtLoc, 
+                                   SourceLocation ImportLoc, 
+                                   ModuleIdPath Path) {
+  Module *Mod = PP.getModuleLoader().loadModule(ImportLoc, Path, 
+                                                Module::AllVisible,
+                                                /*IsIncludeDirective=*/false);
+  if (!Mod)
+    return true;
+  
+  llvm::SmallVector<SourceLocation, 2> IdentifierLocs;
+  Module *ModCheck = Mod;
+  for (unsigned I = 0, N = Path.size(); I != N; ++I) {
+    // If we've run out of module parents, just drop the remaining identifiers.
+    // We need the length to be consistent.
+    if (!ModCheck)
+      break;
+    ModCheck = ModCheck->Parent;
+    
+    IdentifierLocs.push_back(Path[I].second);
+  }
+
+  ImportDecl *Import = ImportDecl::Create(Context, 
+                                          Context.getTranslationUnitDecl(),
+                                          AtLoc.isValid()? AtLoc : ImportLoc, 
+                                          Mod, IdentifierLocs);
+  Context.getTranslationUnitDecl()->addDecl(Import);
+  return Import;
+}
+
+void Sema::ActOnPragmaRedefineExtname(IdentifierInfo* Name,
+                                      IdentifierInfo* AliasName,
+                                      SourceLocation PragmaLoc,
+                                      SourceLocation NameLoc,
+                                      SourceLocation AliasNameLoc) {
+  Decl *PrevDecl = LookupSingleName(TUScope, Name, NameLoc,
+                                    LookupOrdinaryName);
+  AsmLabelAttr *Attr =
+     ::new (Context) AsmLabelAttr(AliasNameLoc, Context, AliasName->getName());
+
+  if (PrevDecl) 
+    PrevDecl->addAttr(Attr);
+  else 
+    (void)ExtnameUndeclaredIdentifiers.insert(
+      std::pair<IdentifierInfo*,AsmLabelAttr*>(Name, Attr));
+}
+
+void Sema::ActOnPragmaWeakID(IdentifierInfo* Name,
+                             SourceLocation PragmaLoc,
+                             SourceLocation NameLoc) {
+  Decl *PrevDecl = LookupSingleName(TUScope, Name, NameLoc, LookupOrdinaryName);
+
+  if (PrevDecl) {
+    PrevDecl->addAttr(::new (Context) WeakAttr(PragmaLoc, Context));
+  } else {
+    (void)WeakUndeclaredIdentifiers.insert(
+      std::pair<IdentifierInfo*,WeakInfo>
+        (Name, WeakInfo((IdentifierInfo*)0, NameLoc)));
+  }
+}
+
+void Sema::ActOnPragmaWeakAlias(IdentifierInfo* Name,
+                                IdentifierInfo* AliasName,
+                                SourceLocation PragmaLoc,
+                                SourceLocation NameLoc,
+                                SourceLocation AliasNameLoc) {
+  Decl *PrevDecl = LookupSingleName(TUScope, AliasName, AliasNameLoc,
+                                    LookupOrdinaryName);
+  WeakInfo W = WeakInfo(Name, NameLoc);
+
+  if (PrevDecl) {
+    if (!PrevDecl->hasAttr<AliasAttr>())
+      if (NamedDecl *ND = dyn_cast<NamedDecl>(PrevDecl))
+        DeclApplyPragmaWeak(TUScope, ND, W);
+  } else {
+    (void)WeakUndeclaredIdentifiers.insert(
+      std::pair<IdentifierInfo*,WeakInfo>(AliasName, W));
+  }
+}
+
+Decl *Sema::getObjCDeclContext() const {
+  return (dyn_cast_or_null<ObjCContainerDecl>(CurContext));
+}
+
+AvailabilityResult Sema::getCurContextAvailability() const {
+  const Decl *D = cast<Decl>(getCurLexicalContext());
+  // A category implicitly has the availability of the interface.
+  if (const ObjCCategoryDecl *CatD = dyn_cast<ObjCCategoryDecl>(D))
+    D = CatD->getClassInterface();
+  
+  return D->getAvailability();
+}
diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp
new file mode 100644
index 0000000..5c6ddd2
--- /dev/null
+++ b/clang/lib/Sema/SemaDeclAttr.cpp
@@ -0,0 +1,4171 @@
+//===--- SemaDeclAttr.cpp - Declaration Attribute Handling ----------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+//  This file implements decl-related attribute processing.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Sema/SemaInternal.h"
+#include "TargetAttributesSema.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/DeclCXX.h"
+#include "clang/AST/DeclTemplate.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/AST/Expr.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Basic/TargetInfo.h"
+#include "clang/Sema/DeclSpec.h"
+#include "clang/Sema/DelayedDiagnostic.h"
+#include "clang/Sema/Lookup.h"
+#include "llvm/ADT/StringExtras.h"
+using namespace clang;
+using namespace sema;
+
+/// These constants match the enumerated choices of
+/// warn_attribute_wrong_decl_type and err_attribute_wrong_decl_type.
+enum AttributeDeclKind {
+  ExpectedFunction,
+  ExpectedUnion,
+  ExpectedVariableOrFunction,
+  ExpectedFunctionOrMethod,
+  ExpectedParameter,
+  ExpectedFunctionMethodOrBlock,
+  ExpectedFunctionMethodOrParameter,
+  ExpectedClass,
+  ExpectedVariable,
+  ExpectedMethod,
+  ExpectedVariableFunctionOrLabel,
+  ExpectedFieldOrGlobalVar,
+  ExpectedStruct
+};
+
+//===----------------------------------------------------------------------===//
+//  Helper functions
+//===----------------------------------------------------------------------===//
+
+static const FunctionType *getFunctionType(const Decl *D,
+                                           bool blocksToo = true) {
+  QualType Ty;
+  if (const ValueDecl *decl = dyn_cast<ValueDecl>(D))
+    Ty = decl->getType();
+  else if (const FieldDecl *decl = dyn_cast<FieldDecl>(D))
+    Ty = decl->getType();
+  else if (const TypedefNameDecl* decl = dyn_cast<TypedefNameDecl>(D))
+    Ty = decl->getUnderlyingType();
+  else
+    return 0;
+
+  if (Ty->isFunctionPointerType())
+    Ty = Ty->getAs<PointerType>()->getPointeeType();
+  else if (blocksToo && Ty->isBlockPointerType())
+    Ty = Ty->getAs<BlockPointerType>()->getPointeeType();
+
+  return Ty->getAs<FunctionType>();
+}
+
+// FIXME: We should provide an abstraction around a method or function
+// to provide the following bits of information.
+
+/// isFunction - Return true if the given decl has function
+/// type (function or function-typed variable).
+static bool isFunction(const Decl *D) {
+  return getFunctionType(D, false) != NULL;
+}
+
+/// isFunctionOrMethod - Return true if the given decl has function
+/// type (function or function-typed variable) or an Objective-C
+/// method.
+static bool isFunctionOrMethod(const Decl *D) {
+  return isFunction(D)|| isa<ObjCMethodDecl>(D);
+}
+
+/// isFunctionOrMethodOrBlock - Return true if the given decl has function
+/// type (function or function-typed variable) or an Objective-C
+/// method or a block.
+static bool isFunctionOrMethodOrBlock(const Decl *D) {
+  if (isFunctionOrMethod(D))
+    return true;
+  // check for block is more involved.
+  if (const VarDecl *V = dyn_cast<VarDecl>(D)) {
+    QualType Ty = V->getType();
+    return Ty->isBlockPointerType();
+  }
+  return isa<BlockDecl>(D);
+}
+
+/// Return true if the given decl has a declarator that should have
+/// been processed by Sema::GetTypeForDeclarator.
+static bool hasDeclarator(const Decl *D) {
+  // In some sense, TypedefDecl really *ought* to be a DeclaratorDecl.
+  return isa<DeclaratorDecl>(D) || isa<BlockDecl>(D) || isa<TypedefNameDecl>(D) ||
+         isa<ObjCPropertyDecl>(D);
+}
+
+/// hasFunctionProto - Return true if the given decl has a argument
+/// information. This decl should have already passed
+/// isFunctionOrMethod or isFunctionOrMethodOrBlock.
+static bool hasFunctionProto(const Decl *D) {
+  if (const FunctionType *FnTy = getFunctionType(D))
+    return isa<FunctionProtoType>(FnTy);
+  else {
+    assert(isa<ObjCMethodDecl>(D) || isa<BlockDecl>(D));
+    return true;
+  }
+}
+
+/// getFunctionOrMethodNumArgs - Return number of function or method
+/// arguments. It is an error to call this on a K&R function (use
+/// hasFunctionProto first).
+static unsigned getFunctionOrMethodNumArgs(const Decl *D) {
+  if (const FunctionType *FnTy = getFunctionType(D))
+    return cast<FunctionProtoType>(FnTy)->getNumArgs();
+  if (const BlockDecl *BD = dyn_cast<BlockDecl>(D))
+    return BD->getNumParams();
+  return cast<ObjCMethodDecl>(D)->param_size();
+}
+
+static QualType getFunctionOrMethodArgType(const Decl *D, unsigned Idx) {
+  if (const FunctionType *FnTy = getFunctionType(D))
+    return cast<FunctionProtoType>(FnTy)->getArgType(Idx);
+  if (const BlockDecl *BD = dyn_cast<BlockDecl>(D))
+    return BD->getParamDecl(Idx)->getType();
+
+  return cast<ObjCMethodDecl>(D)->param_begin()[Idx]->getType();
+}
+
+static QualType getFunctionOrMethodResultType(const Decl *D) {
+  if (const FunctionType *FnTy = getFunctionType(D))
+    return cast<FunctionProtoType>(FnTy)->getResultType();
+  return cast<ObjCMethodDecl>(D)->getResultType();
+}
+
+static bool isFunctionOrMethodVariadic(const Decl *D) {
+  if (const FunctionType *FnTy = getFunctionType(D)) {
+    const FunctionProtoType *proto = cast<FunctionProtoType>(FnTy);
+    return proto->isVariadic();
+  } else if (const BlockDecl *BD = dyn_cast<BlockDecl>(D))
+    return BD->isVariadic();
+  else {
+    return cast<ObjCMethodDecl>(D)->isVariadic();
+  }
+}
+
+static bool isInstanceMethod(const Decl *D) {
+  if (const CXXMethodDecl *MethodDecl = dyn_cast<CXXMethodDecl>(D))
+    return MethodDecl->isInstance();
+  return false;
+}
+
+static inline bool isNSStringType(QualType T, ASTContext &Ctx) {
+  const ObjCObjectPointerType *PT = T->getAs<ObjCObjectPointerType>();
+  if (!PT)
+    return false;
+
+  ObjCInterfaceDecl *Cls = PT->getObjectType()->getInterface();
+  if (!Cls)
+    return false;
+
+  IdentifierInfo* ClsName = Cls->getIdentifier();
+
+  // FIXME: Should we walk the chain of classes?
+  return ClsName == &Ctx.Idents.get("NSString") ||
+         ClsName == &Ctx.Idents.get("NSMutableString");
+}
+
+static inline bool isCFStringType(QualType T, ASTContext &Ctx) {
+  const PointerType *PT = T->getAs<PointerType>();
+  if (!PT)
+    return false;
+
+  const RecordType *RT = PT->getPointeeType()->getAs<RecordType>();
+  if (!RT)
+    return false;
+
+  const RecordDecl *RD = RT->getDecl();
+  if (RD->getTagKind() != TTK_Struct)
+    return false;
+
+  return RD->getIdentifier() == &Ctx.Idents.get("__CFString");
+}
+
+/// \brief Check if the attribute has exactly as many args as Num. May
+/// output an error.
+static bool checkAttributeNumArgs(Sema &S, const AttributeList &Attr,
+                                  unsigned int Num) {
+  if (Attr.getNumArgs() != Num) {
+    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << Num;
+    return false;
+  }
+
+  return true;
+}
+
+
+/// \brief Check if the attribute has at least as many args as Num. May
+/// output an error.
+static bool checkAttributeAtLeastNumArgs(Sema &S, const AttributeList &Attr,
+                                  unsigned int Num) {
+  if (Attr.getNumArgs() < Num) {
+    S.Diag(Attr.getLoc(), diag::err_attribute_too_few_arguments) << Num;
+    return false;
+  }
+
+  return true;
+}
+
+///
+/// \brief Check if passed in Decl is a field or potentially shared global var
+/// \return true if the Decl is a field or potentially shared global variable
+///
+static bool mayBeSharedVariable(const Decl *D) {
+  if (isa<FieldDecl>(D))
+    return true;
+  if (const VarDecl *vd = dyn_cast<VarDecl>(D))
+    return (vd->hasGlobalStorage() && !(vd->isThreadSpecified()));
+
+  return false;
+}
+
+/// \brief Check if the passed-in expression is of type int or bool.
+static bool isIntOrBool(Expr *Exp) {
+  QualType QT = Exp->getType();
+  return QT->isBooleanType() || QT->isIntegerType();
+}
+
+///
+/// \brief Check if passed in Decl is a pointer type.
+/// Note that this function may produce an error message.
+/// \return true if the Decl is a pointer type; false otherwise
+///
+static bool checkIsPointer(Sema &S, const Decl *D, const AttributeList &Attr) {
+  if (const ValueDecl *vd = dyn_cast<ValueDecl>(D)) {
+    QualType QT = vd->getType();
+    if (QT->isAnyPointerType())
+      return true;
+    S.Diag(Attr.getLoc(), diag::warn_pointer_attribute_wrong_type)
+      << Attr.getName()->getName() << QT;
+  } else {
+    S.Diag(Attr.getLoc(), diag::err_attribute_can_be_applied_only_to_value_decl)
+      << Attr.getName();
+  }
+  return false;
+}
+
+/// \brief Checks that the passed in QualType either is of RecordType or points
+/// to RecordType. Returns the relevant RecordType, null if it does not exit.
+static const RecordType *getRecordType(QualType QT) {
+  if (const RecordType *RT = QT->getAs<RecordType>())
+    return RT;
+
+  // Now check if we point to record type.
+  if (const PointerType *PT = QT->getAs<PointerType>())
+    return PT->getPointeeType()->getAs<RecordType>();
+
+  return 0;
+}
+
+/// \brief Thread Safety Analysis: Checks that the passed in RecordType
+/// resolves to a lockable object. May flag an error.
+static void checkForLockableRecord(Sema &S, Decl *D, const AttributeList &Attr,
+                                   QualType Ty) {
+  const RecordType *RT = getRecordType(Ty);
+                                   
+  // Warn if could not get record type for this argument.
+  if (!RT) {
+    S.Diag(Attr.getLoc(), diag::warn_attribute_argument_not_class)
+      << Attr.getName() << Ty.getAsString();
+    return;
+  }
+  // Don't check for lockable if the class hasn't been defined yet. 
+  if (RT->isIncompleteType())
+    return;
+  // Warn if the type is not lockable.
+  if (!RT->getDecl()->getAttr<LockableAttr>()) {
+    S.Diag(Attr.getLoc(), diag::warn_attribute_argument_not_lockable)
+      << Attr.getName() << Ty.getAsString();
+    return;
+  }
+}
+
+/// \brief Thread Safety Analysis: Checks that all attribute arguments, starting
+/// from Sidx, resolve to a lockable object. May flag an error.
+/// \param Sidx The attribute argument index to start checking with.
+/// \param ParamIdxOk Whether an argument can be indexing into a function
+/// parameter list.
+static bool checkAttrArgsAreLockableObjs(Sema &S, Decl *D,
+                                         const AttributeList &Attr,
+                                         SmallVectorImpl<Expr*> &Args,
+                                         int Sidx = 0,
+                                         bool ParamIdxOk = false) {
+  for(unsigned Idx = Sidx; Idx < Attr.getNumArgs(); ++Idx) {
+    Expr *ArgExp = Attr.getArg(Idx);
+
+    if (ArgExp->isTypeDependent()) {
+      // FIXME -- need to processs this again on template instantiation
+      Args.push_back(ArgExp);
+      continue;
+    }
+
+    QualType ArgTy = ArgExp->getType();
+
+    // First see if we can just cast to record type, or point to record type.
+    const RecordType *RT = getRecordType(ArgTy);
+
+    // Now check if we index into a record type function param.
+    if(!RT && ParamIdxOk) {
+      FunctionDecl *FD = dyn_cast<FunctionDecl>(D);
+      IntegerLiteral *IL = dyn_cast<IntegerLiteral>(ArgExp);
+      if(FD && IL) {
+        unsigned int NumParams = FD->getNumParams();
+        llvm::APInt ArgValue = IL->getValue();
+        uint64_t ParamIdxFromOne = ArgValue.getZExtValue();
+        uint64_t ParamIdxFromZero = ParamIdxFromOne - 1;
+        if(!ArgValue.isStrictlyPositive() || ParamIdxFromOne > NumParams) {
+          S.Diag(Attr.getLoc(), diag::err_attribute_argument_out_of_range)
+            << Attr.getName() << Idx + 1 << NumParams;
+          return false;
+        }
+        ArgTy = FD->getParamDecl(ParamIdxFromZero)->getType();
+      }
+    }
+
+    checkForLockableRecord(S, D, Attr, ArgTy);
+
+    Args.push_back(ArgExp);
+  }
+  return true;
+}
+
+//===----------------------------------------------------------------------===//
+// Attribute Implementations
+//===----------------------------------------------------------------------===//
+
+// FIXME: All this manual attribute parsing code is gross. At the
+// least add some helper functions to check most argument patterns (#
+// and types of args).
+
+static void handleGuardedVarAttr(Sema &S, Decl *D, const AttributeList &Attr,
+                                 bool pointer = false) {
+  assert(!Attr.isInvalid());
+
+  if (!checkAttributeNumArgs(S, Attr, 0))
+    return;
+
+  // D must be either a member field or global (potentially shared) variable.
+  if (!mayBeSharedVariable(D)) {
+    S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
+      << Attr.getName() << ExpectedFieldOrGlobalVar;
+    return;
+  }
+
+  if (pointer && !checkIsPointer(S, D, Attr))
+    return;
+
+  if (pointer)
+    D->addAttr(::new (S.Context) PtGuardedVarAttr(Attr.getRange(), S.Context));
+  else
+    D->addAttr(::new (S.Context) GuardedVarAttr(Attr.getRange(), S.Context));
+}
+
+static void handleGuardedByAttr(Sema &S, Decl *D, const AttributeList &Attr,
+                                bool pointer = false) {
+  assert(!Attr.isInvalid());
+
+  if (!checkAttributeNumArgs(S, Attr, 1))
+    return;
+
+  Expr *Arg = Attr.getArg(0);
+
+  // D must be either a member field or global (potentially shared) variable.
+  if (!mayBeSharedVariable(D)) {
+    S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
+      << Attr.getName() << ExpectedFieldOrGlobalVar;
+    return;
+  }
+
+  if (pointer && !checkIsPointer(S, D, Attr))
+    return;
+
+  if (!Arg->isTypeDependent()) {
+    checkForLockableRecord(S, D, Attr, Arg->getType());
+  }
+
+  if (pointer)
+    D->addAttr(::new (S.Context) PtGuardedByAttr(Attr.getRange(),
+                                                 S.Context, Arg));
+  else
+    D->addAttr(::new (S.Context) GuardedByAttr(Attr.getRange(), S.Context, Arg));
+}
+
+
+static void handleLockableAttr(Sema &S, Decl *D, const AttributeList &Attr,
+                               bool scoped = false) {
+  assert(!Attr.isInvalid());
+
+  if (!checkAttributeNumArgs(S, Attr, 0))
+    return;
+
+  // FIXME: Lockable structs for C code.
+  if (!isa<CXXRecordDecl>(D)) {
+    S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
+      << Attr.getName() << ExpectedClass;
+    return;
+  }
+
+  if (scoped)
+    D->addAttr(::new (S.Context) ScopedLockableAttr(Attr.getRange(), S.Context));
+  else
+    D->addAttr(::new (S.Context) LockableAttr(Attr.getRange(), S.Context));
+}
+
+static void handleNoThreadSafetyAttr(Sema &S, Decl *D,
+                                     const AttributeList &Attr) {
+  assert(!Attr.isInvalid());
+
+  if (!checkAttributeNumArgs(S, Attr, 0))
+    return;
+
+  if (!isa<FunctionDecl>(D) && !isa<FunctionTemplateDecl>(D)) {
+    S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
+      << Attr.getName() << ExpectedFunctionOrMethod;
+    return;
+  }
+
+  D->addAttr(::new (S.Context) NoThreadSafetyAnalysisAttr(Attr.getRange(),
+                                                          S.Context));
+}
+
+static void handleNoAddressSafetyAttr(Sema &S, Decl *D,
+                                     const AttributeList &Attr) {
+  assert(!Attr.isInvalid());
+
+  if (!checkAttributeNumArgs(S, Attr, 0))
+    return;
+
+  if (!isa<FunctionDecl>(D) && !isa<FunctionTemplateDecl>(D)) {
+    S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
+      << Attr.getName() << ExpectedFunctionOrMethod;
+    return;
+  }
+
+  D->addAttr(::new (S.Context) NoAddressSafetyAnalysisAttr(Attr.getRange(),
+                                                          S.Context));
+}
+
+static void handleAcquireOrderAttr(Sema &S, Decl *D, const AttributeList &Attr,
+                                   bool before) {
+  assert(!Attr.isInvalid());
+
+  if (!checkAttributeAtLeastNumArgs(S, Attr, 1))
+    return;
+
+  // D must be either a member field or global (potentially shared) variable.
+  ValueDecl *VD = dyn_cast<ValueDecl>(D);
+  if (!VD || !mayBeSharedVariable(D)) {
+    S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
+      << Attr.getName() << ExpectedFieldOrGlobalVar;
+    return;
+  }
+
+  // Check that this attribute only applies to lockable types
+  QualType QT = VD->getType();
+  if (!QT->isDependentType()) {
+    const RecordType *RT = getRecordType(QT);
+    if (!RT || !RT->getDecl()->getAttr<LockableAttr>()) {
+      S.Diag(Attr.getLoc(), diag::warn_attribute_decl_not_lockable)
+              << Attr.getName();
+      return;
+    }
+  }
+
+  SmallVector<Expr*, 1> Args;
+  // check that all arguments are lockable objects
+  if (!checkAttrArgsAreLockableObjs(S, D, Attr, Args))
+    return;
+
+  unsigned Size = Args.size();
+  assert(Size == Attr.getNumArgs());
+  Expr **StartArg = Size == 0 ? 0 : &Args[0];
+
+  if (before)
+    D->addAttr(::new (S.Context) AcquiredBeforeAttr(Attr.getRange(), S.Context,
+                                                    StartArg, Size));
+  else
+    D->addAttr(::new (S.Context) AcquiredAfterAttr(Attr.getRange(), S.Context,
+                                                   StartArg, Size));
+}
+
+static void handleLockFunAttr(Sema &S, Decl *D, const AttributeList &Attr,
+                              bool exclusive = false) {
+  assert(!Attr.isInvalid());
+
+  // zero or more arguments ok
+
+  // check that the attribute is applied to a function
+  if (!isa<FunctionDecl>(D) && !isa<FunctionTemplateDecl>(D)) {
+    S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
+      << Attr.getName() << ExpectedFunctionOrMethod;
+    return;
+  }
+
+  // check that all arguments are lockable objects
+  SmallVector<Expr*, 1> Args;
+  if (!checkAttrArgsAreLockableObjs(S, D, Attr, Args, 0, /*ParamIdxOk=*/true))
+    return;
+
+  unsigned Size = Args.size();
+  assert(Size == Attr.getNumArgs());
+  Expr **StartArg = Size == 0 ? 0 : &Args[0];
+
+  if (exclusive)
+    D->addAttr(::new (S.Context) ExclusiveLockFunctionAttr(Attr.getRange(),
+                                                           S.Context, StartArg,
+                                                           Size));
+  else
+    D->addAttr(::new (S.Context) SharedLockFunctionAttr(Attr.getRange(),
+                                                        S.Context, StartArg,
+                                                        Size));
+}
+
+static void handleTrylockFunAttr(Sema &S, Decl *D, const AttributeList &Attr,
+                                 bool exclusive = false) {
+  assert(!Attr.isInvalid());
+
+  if (!checkAttributeAtLeastNumArgs(S, Attr, 1))
+    return;
+
+
+  if (!isa<FunctionDecl>(D) && !isa<FunctionTemplateDecl>(D)) {
+    S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
+      << Attr.getName() << ExpectedFunctionOrMethod;
+    return;
+  }
+
+  if (!isIntOrBool(Attr.getArg(0))) {
+    S.Diag(Attr.getLoc(), diag::err_attribute_first_argument_not_int_or_bool)
+        << Attr.getName();
+    return;
+  }
+
+  SmallVector<Expr*, 2> Args;
+  // check that all arguments are lockable objects
+  if (!checkAttrArgsAreLockableObjs(S, D, Attr, Args, 1))
+    return;
+
+  unsigned Size = Args.size();
+  Expr **StartArg = Size == 0 ? 0 : &Args[0];
+
+  if (exclusive)
+    D->addAttr(::new (S.Context) ExclusiveTrylockFunctionAttr(Attr.getRange(),
+                                                              S.Context,
+                                                              Attr.getArg(0),
+                                                              StartArg, Size));
+  else
+    D->addAttr(::new (S.Context) SharedTrylockFunctionAttr(Attr.getRange(),
+                                                           S.Context,
+                                                           Attr.getArg(0),
+                                                           StartArg, Size));
+}
+
+static void handleLocksRequiredAttr(Sema &S, Decl *D, const AttributeList &Attr,
+                                    bool exclusive = false) {
+  assert(!Attr.isInvalid());
+
+  if (!checkAttributeAtLeastNumArgs(S, Attr, 1))
+    return;
+
+  if (!isa<FunctionDecl>(D) && !isa<FunctionTemplateDecl>(D)) {
+    S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
+      << Attr.getName() << ExpectedFunctionOrMethod;
+    return;
+  }
+
+  // check that all arguments are lockable objects
+  SmallVector<Expr*, 1> Args;
+  if (!checkAttrArgsAreLockableObjs(S, D, Attr, Args))
+    return;
+
+  unsigned Size = Args.size();
+  assert(Size == Attr.getNumArgs());
+  Expr **StartArg = Size == 0 ? 0 : &Args[0];
+
+  if (exclusive)
+    D->addAttr(::new (S.Context) ExclusiveLocksRequiredAttr(Attr.getRange(),
+                                                            S.Context, StartArg,
+                                                            Size));
+  else
+    D->addAttr(::new (S.Context) SharedLocksRequiredAttr(Attr.getRange(),
+                                                         S.Context, StartArg,
+                                                         Size));
+}
+
+static void handleUnlockFunAttr(Sema &S, Decl *D,
+                                const AttributeList &Attr) {
+  assert(!Attr.isInvalid());
+
+  // zero or more arguments ok
+
+  if (!isa<FunctionDecl>(D) && !isa<FunctionTemplateDecl>(D)) {
+    S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
+      << Attr.getName() << ExpectedFunctionOrMethod;
+    return;
+  }
+
+  // check that all arguments are lockable objects
+  SmallVector<Expr*, 1> Args;
+  if (!checkAttrArgsAreLockableObjs(S, D, Attr, Args, 0, /*ParamIdxOk=*/true))
+    return;
+
+  unsigned Size = Args.size();
+  assert(Size == Attr.getNumArgs());
+  Expr **StartArg = Size == 0 ? 0 : &Args[0];
+
+  D->addAttr(::new (S.Context) UnlockFunctionAttr(Attr.getRange(), S.Context,
+                                                  StartArg, Size));
+}
+
+static void handleLockReturnedAttr(Sema &S, Decl *D,
+                                   const AttributeList &Attr) {
+  assert(!Attr.isInvalid());
+
+  if (!checkAttributeNumArgs(S, Attr, 1))
+    return;
+  Expr *Arg = Attr.getArg(0);
+
+  if (!isa<FunctionDecl>(D) && !isa<FunctionTemplateDecl>(D)) {
+    S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
+      << Attr.getName() << ExpectedFunctionOrMethod;
+    return;
+  }
+
+  if (Arg->isTypeDependent())
+    return;
+
+  // check that the argument is lockable object
+  checkForLockableRecord(S, D, Attr, Arg->getType());
+
+  D->addAttr(::new (S.Context) LockReturnedAttr(Attr.getRange(), S.Context, Arg));
+}
+
+static void handleLocksExcludedAttr(Sema &S, Decl *D,
+                                    const AttributeList &Attr) {
+  assert(!Attr.isInvalid());
+
+  if (!checkAttributeAtLeastNumArgs(S, Attr, 1))
+    return;
+
+  if (!isa<FunctionDecl>(D) && !isa<FunctionTemplateDecl>(D)) {
+    S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
+      << Attr.getName() << ExpectedFunctionOrMethod;
+    return;
+  }
+
+  // check that all arguments are lockable objects
+  SmallVector<Expr*, 1> Args;
+  if (!checkAttrArgsAreLockableObjs(S, D, Attr, Args))
+    return;
+
+  unsigned Size = Args.size();
+  assert(Size == Attr.getNumArgs());
+  Expr **StartArg = Size == 0 ? 0 : &Args[0];
+
+  D->addAttr(::new (S.Context) LocksExcludedAttr(Attr.getRange(), S.Context,
+                                                 StartArg, Size));
+}
+
+
+static void handleExtVectorTypeAttr(Sema &S, Scope *scope, Decl *D,
+                                    const AttributeList &Attr) {
+  TypedefNameDecl *tDecl = dyn_cast<TypedefNameDecl>(D);
+  if (tDecl == 0) {
+    S.Diag(Attr.getLoc(), diag::err_typecheck_ext_vector_not_typedef);
+    return;
+  }
+
+  QualType curType = tDecl->getUnderlyingType();
+
+  Expr *sizeExpr;
+
+  // Special case where the argument is a template id.
+  if (Attr.getParameterName()) {
+    CXXScopeSpec SS;
+    SourceLocation TemplateKWLoc;
+    UnqualifiedId id;
+    id.setIdentifier(Attr.getParameterName(), Attr.getLoc());
+    
+    ExprResult Size = S.ActOnIdExpression(scope, SS, TemplateKWLoc, id,
+                                          false, false);
+    if (Size.isInvalid())
+      return;
+    
+    sizeExpr = Size.get();
+  } else {
+    // check the attribute arguments.
+    if (!checkAttributeNumArgs(S, Attr, 1))
+      return;
+
+    sizeExpr = Attr.getArg(0);
+  }
+
+  // Instantiate/Install the vector type, and let Sema build the type for us.
+  // This will run the reguired checks.
+  QualType T = S.BuildExtVectorType(curType, sizeExpr, Attr.getLoc());
+  if (!T.isNull()) {
+    // FIXME: preserve the old source info.
+    tDecl->setTypeSourceInfo(S.Context.getTrivialTypeSourceInfo(T));
+
+    // Remember this typedef decl, we will need it later for diagnostics.
+    S.ExtVectorDecls.push_back(tDecl);
+  }
+}
+
+static void handlePackedAttr(Sema &S, Decl *D, const AttributeList &Attr) {
+  // check the attribute arguments.
+  if (!checkAttributeNumArgs(S, Attr, 0))
+    return;
+
+  if (TagDecl *TD = dyn_cast<TagDecl>(D))
+    TD->addAttr(::new (S.Context) PackedAttr(Attr.getRange(), S.Context));
+  else if (FieldDecl *FD = dyn_cast<FieldDecl>(D)) {
+    // If the alignment is less than or equal to 8 bits, the packed attribute
+    // has no effect.
+    if (!FD->getType()->isIncompleteType() &&
+        S.Context.getTypeAlign(FD->getType()) <= 8)
+      S.Diag(Attr.getLoc(), diag::warn_attribute_ignored_for_field_of_type)
+        << Attr.getName() << FD->getType();
+    else
+      FD->addAttr(::new (S.Context) PackedAttr(Attr.getRange(), S.Context));
+  } else
+    S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName();
+}
+
+static void handleMsStructAttr(Sema &S, Decl *D, const AttributeList &Attr) {
+  if (TagDecl *TD = dyn_cast<TagDecl>(D))
+    TD->addAttr(::new (S.Context) MsStructAttr(Attr.getRange(), S.Context));
+  else
+    S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName();
+}
+
+static void handleIBAction(Sema &S, Decl *D, const AttributeList &Attr) {
+  // check the attribute arguments.
+  if (!checkAttributeNumArgs(S, Attr, 0))
+    return;
+
+  // The IBAction attributes only apply to instance methods.
+  if (ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D))
+    if (MD->isInstanceMethod()) {
+      D->addAttr(::new (S.Context) IBActionAttr(Attr.getRange(), S.Context));
+      return;
+    }
+
+  S.Diag(Attr.getLoc(), diag::warn_attribute_ibaction) << Attr.getName();
+}
+
+static bool checkIBOutletCommon(Sema &S, Decl *D, const AttributeList &Attr) {
+  // The IBOutlet/IBOutletCollection attributes only apply to instance
+  // variables or properties of Objective-C classes.  The outlet must also
+  // have an object reference type.
+  if (const ObjCIvarDecl *VD = dyn_cast<ObjCIvarDecl>(D)) {
+    if (!VD->getType()->getAs<ObjCObjectPointerType>()) {
+      S.Diag(Attr.getLoc(), diag::warn_iboutlet_object_type)
+        << Attr.getName() << VD->getType() << 0;
+      return false;
+    }
+  }
+  else if (const ObjCPropertyDecl *PD = dyn_cast<ObjCPropertyDecl>(D)) {
+    if (!PD->getType()->getAs<ObjCObjectPointerType>()) {
+      S.Diag(Attr.getLoc(), diag::warn_iboutlet_object_type)
+        << Attr.getName() << PD->getType() << 1;
+      return false;
+    }
+  }
+  else {
+    S.Diag(Attr.getLoc(), diag::warn_attribute_iboutlet) << Attr.getName();
+    return false;
+  }
+
+  return true;
+}
+
+static void handleIBOutlet(Sema &S, Decl *D, const AttributeList &Attr) {
+  // check the attribute arguments.
+  if (!checkAttributeNumArgs(S, Attr, 0))
+    return;
+  
+  if (!checkIBOutletCommon(S, D, Attr))
+    return;
+
+  D->addAttr(::new (S.Context) IBOutletAttr(Attr.getRange(), S.Context));
+}
+
+static void handleIBOutletCollection(Sema &S, Decl *D,
+                                     const AttributeList &Attr) {
+
+  // The iboutletcollection attribute can have zero or one arguments.
+  if (Attr.getParameterName() && Attr.getNumArgs() > 0) {
+    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
+    return;
+  }
+
+  if (!checkIBOutletCommon(S, D, Attr))
+    return;
+
+  IdentifierInfo *II = Attr.getParameterName();
+  if (!II)
+    II = &S.Context.Idents.get("NSObject");
+  
+  ParsedType TypeRep = S.getTypeName(*II, Attr.getLoc(), 
+                        S.getScopeForContext(D->getDeclContext()->getParent()));
+  if (!TypeRep) {
+    S.Diag(Attr.getLoc(), diag::err_iboutletcollection_type) << II;
+    return;
+  }
+  QualType QT = TypeRep.get();
+  // Diagnose use of non-object type in iboutletcollection attribute.
+  // FIXME. Gnu attribute extension ignores use of builtin types in
+  // attributes. So, __attribute__((iboutletcollection(char))) will be
+  // treated as __attribute__((iboutletcollection())).
+  if (!QT->isObjCIdType() && !QT->isObjCObjectType()) {
+    S.Diag(Attr.getLoc(), diag::err_iboutletcollection_type) << II;
+    return;
+  }
+  D->addAttr(::new (S.Context) IBOutletCollectionAttr(Attr.getRange(),S.Context,
+                                                   QT, Attr.getParameterLoc()));
+}
+
+static void possibleTransparentUnionPointerType(QualType &T) {
+  if (const RecordType *UT = T->getAsUnionType())
+    if (UT && UT->getDecl()->hasAttr<TransparentUnionAttr>()) {
+      RecordDecl *UD = UT->getDecl();
+      for (RecordDecl::field_iterator it = UD->field_begin(),
+           itend = UD->field_end(); it != itend; ++it) {
+        QualType QT = it->getType();
+        if (QT->isAnyPointerType() || QT->isBlockPointerType()) {
+          T = QT;
+          return;
+        }
+      }
+    }
+}
+
+static void handleNonNullAttr(Sema &S, Decl *D, const AttributeList &Attr) {
+  // GCC ignores the nonnull attribute on K&R style function prototypes, so we
+  // ignore it as well
+  if (!isFunctionOrMethod(D) || !hasFunctionProto(D)) {
+    S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
+      << Attr.getName() << ExpectedFunction;
+    return;
+  }
+
+  // In C++ the implicit 'this' function parameter also counts, and they are
+  // counted from one.
+  bool HasImplicitThisParam = isInstanceMethod(D);
+  unsigned NumArgs  = getFunctionOrMethodNumArgs(D) + HasImplicitThisParam;
+
+  // The nonnull attribute only applies to pointers.
+  SmallVector<unsigned, 10> NonNullArgs;
+
+  for (AttributeList::arg_iterator I=Attr.arg_begin(),
+                                   E=Attr.arg_end(); I!=E; ++I) {
+
+
+    // The argument must be an integer constant expression.
+    Expr *Ex = *I;
+    llvm::APSInt ArgNum(32);
+    if (Ex->isTypeDependent() || Ex->isValueDependent() ||
+        !Ex->isIntegerConstantExpr(ArgNum, S.Context)) {
+      S.Diag(Attr.getLoc(), diag::err_attribute_argument_not_int)
+        << "nonnull" << Ex->getSourceRange();
+      return;
+    }
+
+    unsigned x = (unsigned) ArgNum.getZExtValue();
+
+    if (x < 1 || x > NumArgs) {
+      S.Diag(Attr.getLoc(), diag::err_attribute_argument_out_of_bounds)
+       << "nonnull" << I.getArgNum() << Ex->getSourceRange();
+      return;
+    }
+
+    --x;
+    if (HasImplicitThisParam) {
+      if (x == 0) {
+        S.Diag(Attr.getLoc(),
+               diag::err_attribute_invalid_implicit_this_argument)
+          << "nonnull" << Ex->getSourceRange();
+        return;
+      }
+      --x;
+    }
+
+    // Is the function argument a pointer type?
+    QualType T = getFunctionOrMethodArgType(D, x).getNonReferenceType();
+    possibleTransparentUnionPointerType(T);
+    
+    if (!T->isAnyPointerType() && !T->isBlockPointerType()) {
+      // FIXME: Should also highlight argument in decl.
+      S.Diag(Attr.getLoc(), diag::warn_nonnull_pointers_only)
+        << "nonnull" << Ex->getSourceRange();
+      continue;
+    }
+
+    NonNullArgs.push_back(x);
+  }
+
+  // If no arguments were specified to __attribute__((nonnull)) then all pointer
+  // arguments have a nonnull attribute.
+  if (NonNullArgs.empty()) {
+    for (unsigned I = 0, E = getFunctionOrMethodNumArgs(D); I != E; ++I) {
+      QualType T = getFunctionOrMethodArgType(D, I).getNonReferenceType();
+      possibleTransparentUnionPointerType(T);
+      if (T->isAnyPointerType() || T->isBlockPointerType())
+        NonNullArgs.push_back(I);
+    }
+
+    // No pointer arguments?
+    if (NonNullArgs.empty()) {
+      // Warn the trivial case only if attribute is not coming from a
+      // macro instantiation.
+      if (Attr.getLoc().isFileID())
+        S.Diag(Attr.getLoc(), diag::warn_attribute_nonnull_no_pointers);
+      return;
+    }
+  }
+
+  unsigned* start = &NonNullArgs[0];
+  unsigned size = NonNullArgs.size();
+  llvm::array_pod_sort(start, start + size);
+  D->addAttr(::new (S.Context) NonNullAttr(Attr.getRange(), S.Context, start,
+                                           size));
+}
+
+static void handleOwnershipAttr(Sema &S, Decl *D, const AttributeList &AL) {
+  // This attribute must be applied to a function declaration.
+  // The first argument to the attribute must be a string,
+  // the name of the resource, for example "malloc".
+  // The following arguments must be argument indexes, the arguments must be
+  // of integer type for Returns, otherwise of pointer type.
+  // The difference between Holds and Takes is that a pointer may still be used
+  // after being held.  free() should be __attribute((ownership_takes)), whereas
+  // a list append function may well be __attribute((ownership_holds)).
+
+  if (!AL.getParameterName()) {
+    S.Diag(AL.getLoc(), diag::err_attribute_argument_n_not_string)
+        << AL.getName()->getName() << 1;
+    return;
+  }
+  // Figure out our Kind, and check arguments while we're at it.
+  OwnershipAttr::OwnershipKind K;
+  switch (AL.getKind()) {
+  case AttributeList::AT_ownership_takes:
+    K = OwnershipAttr::Takes;
+    if (AL.getNumArgs() < 1) {
+      S.Diag(AL.getLoc(), diag::err_attribute_wrong_number_arguments) << 2;
+      return;
+    }
+    break;
+  case AttributeList::AT_ownership_holds:
+    K = OwnershipAttr::Holds;
+    if (AL.getNumArgs() < 1) {
+      S.Diag(AL.getLoc(), diag::err_attribute_wrong_number_arguments) << 2;
+      return;
+    }
+    break;
+  case AttributeList::AT_ownership_returns:
+    K = OwnershipAttr::Returns;
+    if (AL.getNumArgs() > 1) {
+      S.Diag(AL.getLoc(), diag::err_attribute_wrong_number_arguments)
+          << AL.getNumArgs() + 1;
+      return;
+    }
+    break;
+  default:
+    // This should never happen given how we are called.
+    llvm_unreachable("Unknown ownership attribute");
+  }
+
+  if (!isFunction(D) || !hasFunctionProto(D)) {
+    S.Diag(AL.getLoc(), diag::warn_attribute_wrong_decl_type)
+      << AL.getName() << ExpectedFunction;
+    return;
+  }
+
+  // In C++ the implicit 'this' function parameter also counts, and they are
+  // counted from one.
+  bool HasImplicitThisParam = isInstanceMethod(D);
+  unsigned NumArgs  = getFunctionOrMethodNumArgs(D) + HasImplicitThisParam;
+
+  StringRef Module = AL.getParameterName()->getName();
+
+  // Normalize the argument, __foo__ becomes foo.
+  if (Module.startswith("__") && Module.endswith("__"))
+    Module = Module.substr(2, Module.size() - 4);
+
+  SmallVector<unsigned, 10> OwnershipArgs;
+
+  for (AttributeList::arg_iterator I = AL.arg_begin(), E = AL.arg_end(); I != E;
+       ++I) {
+
+    Expr *IdxExpr = *I;
+    llvm::APSInt ArgNum(32);
+    if (IdxExpr->isTypeDependent() || IdxExpr->isValueDependent()
+        || !IdxExpr->isIntegerConstantExpr(ArgNum, S.Context)) {
+      S.Diag(AL.getLoc(), diag::err_attribute_argument_not_int)
+          << AL.getName()->getName() << IdxExpr->getSourceRange();
+      continue;
+    }
+
+    unsigned x = (unsigned) ArgNum.getZExtValue();
+
+    if (x > NumArgs || x < 1) {
+      S.Diag(AL.getLoc(), diag::err_attribute_argument_out_of_bounds)
+          << AL.getName()->getName() << x << IdxExpr->getSourceRange();
+      continue;
+    }
+    --x;
+    if (HasImplicitThisParam) {
+      if (x == 0) {
+        S.Diag(AL.getLoc(), diag::err_attribute_invalid_implicit_this_argument)
+          << "ownership" << IdxExpr->getSourceRange();
+        return;
+      }
+      --x;
+    }
+
+    switch (K) {
+    case OwnershipAttr::Takes:
+    case OwnershipAttr::Holds: {
+      // Is the function argument a pointer type?
+      QualType T = getFunctionOrMethodArgType(D, x);
+      if (!T->isAnyPointerType() && !T->isBlockPointerType()) {
+        // FIXME: Should also highlight argument in decl.
+        S.Diag(AL.getLoc(), diag::err_ownership_type)
+            << ((K==OwnershipAttr::Takes)?"ownership_takes":"ownership_holds")
+            << "pointer"
+            << IdxExpr->getSourceRange();
+        continue;
+      }
+      break;
+    }
+    case OwnershipAttr::Returns: {
+      if (AL.getNumArgs() > 1) {
+          // Is the function argument an integer type?
+          Expr *IdxExpr = AL.getArg(0);
+          llvm::APSInt ArgNum(32);
+          if (IdxExpr->isTypeDependent() || IdxExpr->isValueDependent()
+              || !IdxExpr->isIntegerConstantExpr(ArgNum, S.Context)) {
+            S.Diag(AL.getLoc(), diag::err_ownership_type)
+                << "ownership_returns" << "integer"
+                << IdxExpr->getSourceRange();
+            return;
+          }
+      }
+      break;
+    }
+    } // switch
+
+    // Check we don't have a conflict with another ownership attribute.
+    for (specific_attr_iterator<OwnershipAttr>
+          i = D->specific_attr_begin<OwnershipAttr>(),
+          e = D->specific_attr_end<OwnershipAttr>();
+        i != e; ++i) {
+      if ((*i)->getOwnKind() != K) {
+        for (const unsigned *I = (*i)->args_begin(), *E = (*i)->args_end();
+             I!=E; ++I) {
+          if (x == *I) {
+            S.Diag(AL.getLoc(), diag::err_attributes_are_not_compatible)
+                << AL.getName()->getName() << "ownership_*";
+          }
+        }
+      }
+    }
+    OwnershipArgs.push_back(x);
+  }
+
+  unsigned* start = OwnershipArgs.data();
+  unsigned size = OwnershipArgs.size();
+  llvm::array_pod_sort(start, start + size);
+
+  if (K != OwnershipAttr::Returns && OwnershipArgs.empty()) {
+    S.Diag(AL.getLoc(), diag::err_attribute_wrong_number_arguments) << 2;
+    return;
+  }
+
+  D->addAttr(::new (S.Context) OwnershipAttr(AL.getLoc(), S.Context, K, Module,
+                                             start, size));
+}
+
+/// Whether this declaration has internal linkage for the purposes of
+/// things that want to complain about things not have internal linkage.
+static bool hasEffectivelyInternalLinkage(NamedDecl *D) {
+  switch (D->getLinkage()) {
+  case NoLinkage:
+  case InternalLinkage:
+    return true;
+
+  // Template instantiations that go from external to unique-external
+  // shouldn't get diagnosed.
+  case UniqueExternalLinkage:
+    return true;
+
+  case ExternalLinkage:
+    return false;
+  }
+  llvm_unreachable("unknown linkage kind!");
+}
+
+static void handleWeakRefAttr(Sema &S, Decl *D, const AttributeList &Attr) {
+  // Check the attribute arguments.
+  if (Attr.getNumArgs() > 1) {
+    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
+    return;
+  }
+
+  if (!isa<VarDecl>(D) && !isa<FunctionDecl>(D)) {
+    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type)
+      << Attr.getName() << ExpectedVariableOrFunction;
+    return;
+  }
+
+  NamedDecl *nd = cast<NamedDecl>(D);
+
+  // gcc rejects
+  // class c {
+  //   static int a __attribute__((weakref ("v2")));
+  //   static int b() __attribute__((weakref ("f3")));
+  // };
+  // and ignores the attributes of
+  // void f(void) {
+  //   static int a __attribute__((weakref ("v2")));
+  // }
+  // we reject them
+  const DeclContext *Ctx = D->getDeclContext()->getRedeclContext();
+  if (!Ctx->isFileContext()) {
+    S.Diag(Attr.getLoc(), diag::err_attribute_weakref_not_global_context) <<
+        nd->getNameAsString();
+    return;
+  }
+
+  // The GCC manual says
+  //
+  // At present, a declaration to which `weakref' is attached can only
+  // be `static'.
+  //
+  // It also says
+  //
+  // Without a TARGET,
+  // given as an argument to `weakref' or to `alias', `weakref' is
+  // equivalent to `weak'.
+  //
+  // gcc 4.4.1 will accept
+  // int a7 __attribute__((weakref));
+  // as
+  // int a7 __attribute__((weak));
+  // This looks like a bug in gcc. We reject that for now. We should revisit
+  // it if this behaviour is actually used.
+
+  if (!hasEffectivelyInternalLinkage(nd)) {
+    S.Diag(Attr.getLoc(), diag::err_attribute_weakref_not_static);
+    return;
+  }
+
+  // GCC rejects
+  // static ((alias ("y"), weakref)).
+  // Should we? How to check that weakref is before or after alias?
+
+  if (Attr.getNumArgs() == 1) {
+    Expr *Arg = Attr.getArg(0);
+    Arg = Arg->IgnoreParenCasts();
+    StringLiteral *Str = dyn_cast<StringLiteral>(Arg);
+
+    if (!Str || !Str->isAscii()) {
+      S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_string)
+          << "weakref" << 1;
+      return;
+    }
+    // GCC will accept anything as the argument of weakref. Should we
+    // check for an existing decl?
+    D->addAttr(::new (S.Context) AliasAttr(Attr.getRange(), S.Context,
+                                           Str->getString()));
+  }
+
+  D->addAttr(::new (S.Context) WeakRefAttr(Attr.getRange(), S.Context));
+}
+
+static void handleAliasAttr(Sema &S, Decl *D, const AttributeList &Attr) {
+  // check the attribute arguments.
+  if (Attr.getNumArgs() != 1) {
+    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
+    return;
+  }
+
+  Expr *Arg = Attr.getArg(0);
+  Arg = Arg->IgnoreParenCasts();
+  StringLiteral *Str = dyn_cast<StringLiteral>(Arg);
+
+  if (!Str || !Str->isAscii()) {
+    S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_string)
+      << "alias" << 1;
+    return;
+  }
+
+  if (S.Context.getTargetInfo().getTriple().isOSDarwin()) {
+    S.Diag(Attr.getLoc(), diag::err_alias_not_supported_on_darwin);
+    return;
+  }
+
+  // FIXME: check if target symbol exists in current file
+
+  D->addAttr(::new (S.Context) AliasAttr(Attr.getRange(), S.Context,
+                                         Str->getString()));
+}
+
+static void handleNakedAttr(Sema &S, Decl *D, const AttributeList &Attr) {
+  // Check the attribute arguments.
+  if (!checkAttributeNumArgs(S, Attr, 0))
+    return;
+
+  if (!isa<FunctionDecl>(D)) {
+    S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
+      << Attr.getName() << ExpectedFunction;
+    return;
+  }
+
+  D->addAttr(::new (S.Context) NakedAttr(Attr.getRange(), S.Context));
+}
+
+static void handleAlwaysInlineAttr(Sema &S, Decl *D,
+                                   const AttributeList &Attr) {
+  // Check the attribute arguments.
+  if (Attr.hasParameterOrArguments()) {
+    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
+    return;
+  }
+
+  if (!isa<FunctionDecl>(D)) {
+    S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
+      << Attr.getName() << ExpectedFunction;
+    return;
+  }
+
+  D->addAttr(::new (S.Context) AlwaysInlineAttr(Attr.getRange(), S.Context));
+}
+
+static void handleMallocAttr(Sema &S, Decl *D, const AttributeList &Attr) {
+  // Check the attribute arguments.
+  if (Attr.hasParameterOrArguments()) {
+    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
+    return;
+  }
+
+  if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
+    QualType RetTy = FD->getResultType();
+    if (RetTy->isAnyPointerType() || RetTy->isBlockPointerType()) {
+      D->addAttr(::new (S.Context) MallocAttr(Attr.getRange(), S.Context));
+      return;
+    }
+  }
+
+  S.Diag(Attr.getLoc(), diag::warn_attribute_malloc_pointer_only);
+}
+
+static void handleMayAliasAttr(Sema &S, Decl *D, const AttributeList &Attr) {
+  // check the attribute arguments.
+  if (!checkAttributeNumArgs(S, Attr, 0))
+    return;
+
+  D->addAttr(::new (S.Context) MayAliasAttr(Attr.getRange(), S.Context));
+}
+
+static void handleNoCommonAttr(Sema &S, Decl *D, const AttributeList &Attr) {
+  assert(!Attr.isInvalid());
+  if (isa<VarDecl>(D))
+    D->addAttr(::new (S.Context) NoCommonAttr(Attr.getRange(), S.Context));
+  else
+    S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
+      << Attr.getName() << ExpectedVariable;
+}
+
+static void handleCommonAttr(Sema &S, Decl *D, const AttributeList &Attr) {
+  assert(!Attr.isInvalid());
+  if (isa<VarDecl>(D))
+    D->addAttr(::new (S.Context) CommonAttr(Attr.getRange(), S.Context));
+  else
+    S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
+      << Attr.getName() << ExpectedVariable;
+}
+
+static void handleNoReturnAttr(Sema &S, Decl *D, const AttributeList &attr) {
+  if (hasDeclarator(D)) return;
+
+  if (S.CheckNoReturnAttr(attr)) return;
+
+  if (!isa<ObjCMethodDecl>(D)) {
+    S.Diag(attr.getLoc(), diag::warn_attribute_wrong_decl_type)
+      << attr.getName() << ExpectedFunctionOrMethod;
+    return;
+  }
+
+  D->addAttr(::new (S.Context) NoReturnAttr(attr.getRange(), S.Context));
+}
+
+bool Sema::CheckNoReturnAttr(const AttributeList &attr) {
+  if (attr.hasParameterOrArguments()) {
+    Diag(attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
+    attr.setInvalid();
+    return true;
+  }
+
+  return false;
+}
+
+static void handleAnalyzerNoReturnAttr(Sema &S, Decl *D,
+                                       const AttributeList &Attr) {
+  
+  // The checking path for 'noreturn' and 'analyzer_noreturn' are different
+  // because 'analyzer_noreturn' does not impact the type.
+  
+  if(!checkAttributeNumArgs(S, Attr, 0))
+      return;
+  
+  if (!isFunctionOrMethod(D) && !isa<BlockDecl>(D)) {
+    ValueDecl *VD = dyn_cast<ValueDecl>(D);
+    if (VD == 0 || (!VD->getType()->isBlockPointerType()
+                    && !VD->getType()->isFunctionPointerType())) {
+      S.Diag(Attr.getLoc(),
+             Attr.isCXX0XAttribute() ? diag::err_attribute_wrong_decl_type
+             : diag::warn_attribute_wrong_decl_type)
+        << Attr.getName() << ExpectedFunctionMethodOrBlock;
+      return;
+    }
+  }
+  
+  D->addAttr(::new (S.Context) AnalyzerNoReturnAttr(Attr.getRange(), S.Context));
+}
+
+// PS3 PPU-specific.
+static void handleVecReturnAttr(Sema &S, Decl *D, const AttributeList &Attr) {
+/*
+  Returning a Vector Class in Registers
+  
+  According to the PPU ABI specifications, a class with a single member of 
+  vector type is returned in memory when used as the return value of a function.
+  This results in inefficient code when implementing vector classes. To return
+  the value in a single vector register, add the vecreturn attribute to the
+  class definition. This attribute is also applicable to struct types.
+  
+  Example:
+  
+  struct Vector
+  {
+    __vector float xyzw;
+  } __attribute__((vecreturn));
+  
+  Vector Add(Vector lhs, Vector rhs)
+  {
+    Vector result;
+    result.xyzw = vec_add(lhs.xyzw, rhs.xyzw);
+    return result; // This will be returned in a register
+  }
+*/
+  if (!isa<RecordDecl>(D)) {
+    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type)
+      << Attr.getName() << ExpectedClass;
+    return;
+  }
+
+  if (D->getAttr<VecReturnAttr>()) {
+    S.Diag(Attr.getLoc(), diag::err_repeat_attribute) << "vecreturn";
+    return;
+  }
+
+  RecordDecl *record = cast<RecordDecl>(D);
+  int count = 0;
+
+  if (!isa<CXXRecordDecl>(record)) {
+    S.Diag(Attr.getLoc(), diag::err_attribute_vecreturn_only_vector_member);
+    return;
+  }
+
+  if (!cast<CXXRecordDecl>(record)->isPOD()) {
+    S.Diag(Attr.getLoc(), diag::err_attribute_vecreturn_only_pod_record);
+    return;
+  }
+
+  for (RecordDecl::field_iterator iter = record->field_begin();
+       iter != record->field_end(); iter++) {
+    if ((count == 1) || !iter->getType()->isVectorType()) {
+      S.Diag(Attr.getLoc(), diag::err_attribute_vecreturn_only_vector_member);
+      return;
+    }
+    count++;
+  }
+
+  D->addAttr(::new (S.Context) VecReturnAttr(Attr.getRange(), S.Context));
+}
+
+static void handleDependencyAttr(Sema &S, Decl *D, const AttributeList &Attr) {
+  if (!isFunctionOrMethod(D) && !isa<ParmVarDecl>(D)) {
+    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type)
+      << Attr.getName() << ExpectedFunctionMethodOrParameter;
+    return;
+  }
+  // FIXME: Actually store the attribute on the declaration
+}
+
+static void handleUnusedAttr(Sema &S, Decl *D, const AttributeList &Attr) {
+  // check the attribute arguments.
+  if (Attr.hasParameterOrArguments()) {
+    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
+    return;
+  }
+
+  if (!isa<VarDecl>(D) && !isa<ObjCIvarDecl>(D) && !isFunctionOrMethod(D) &&
+      !isa<TypeDecl>(D) && !isa<LabelDecl>(D)) {
+    S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
+      << Attr.getName() << ExpectedVariableFunctionOrLabel;
+    return;
+  }
+
+  D->addAttr(::new (S.Context) UnusedAttr(Attr.getRange(), S.Context));
+}
+
+static void handleReturnsTwiceAttr(Sema &S, Decl *D,
+                                   const AttributeList &Attr) {
+  // check the attribute arguments.
+  if (Attr.hasParameterOrArguments()) {
+    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
+    return;
+  }
+
+  if (!isa<FunctionDecl>(D)) {
+    S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
+      << Attr.getName() << ExpectedFunction;
+    return;
+  }
+
+  D->addAttr(::new (S.Context) ReturnsTwiceAttr(Attr.getRange(), S.Context));
+}
+
+static void handleUsedAttr(Sema &S, Decl *D, const AttributeList &Attr) {
+  // check the attribute arguments.
+  if (Attr.hasParameterOrArguments()) {
+    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
+    return;
+  }
+
+  if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
+    if (VD->hasLocalStorage() || VD->hasExternalStorage()) {
+      S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "used";
+      return;
+    }
+  } else if (!isFunctionOrMethod(D)) {
+    S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
+      << Attr.getName() << ExpectedVariableOrFunction;
+    return;
+  }
+
+  D->addAttr(::new (S.Context) UsedAttr(Attr.getRange(), S.Context));
+}
+
+static void handleConstructorAttr(Sema &S, Decl *D, const AttributeList &Attr) {
+  // check the attribute arguments.
+  if (Attr.getNumArgs() > 1) {
+    S.Diag(Attr.getLoc(), diag::err_attribute_too_many_arguments) << 1;
+    return;
+  }
+
+  int priority = 65535; // FIXME: Do not hardcode such constants.
+  if (Attr.getNumArgs() > 0) {
+    Expr *E = Attr.getArg(0);
+    llvm::APSInt Idx(32);
+    if (E->isTypeDependent() || E->isValueDependent() ||
+        !E->isIntegerConstantExpr(Idx, S.Context)) {
+      S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_int)
+        << "constructor" << 1 << E->getSourceRange();
+      return;
+    }
+    priority = Idx.getZExtValue();
+  }
+
+  if (!isa<FunctionDecl>(D)) {
+    S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
+      << Attr.getName() << ExpectedFunction;
+    return;
+  }
+
+  D->addAttr(::new (S.Context) ConstructorAttr(Attr.getRange(), S.Context,
+                                               priority));
+}
+
+static void handleDestructorAttr(Sema &S, Decl *D, const AttributeList &Attr) {
+  // check the attribute arguments.
+  if (Attr.getNumArgs() > 1) {
+    S.Diag(Attr.getLoc(), diag::err_attribute_too_many_arguments) << 1;
+    return;
+  }
+
+  int priority = 65535; // FIXME: Do not hardcode such constants.
+  if (Attr.getNumArgs() > 0) {
+    Expr *E = Attr.getArg(0);
+    llvm::APSInt Idx(32);
+    if (E->isTypeDependent() || E->isValueDependent() ||
+        !E->isIntegerConstantExpr(Idx, S.Context)) {
+      S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_int)
+        << "destructor" << 1 << E->getSourceRange();
+      return;
+    }
+    priority = Idx.getZExtValue();
+  }
+
+  if (!isa<FunctionDecl>(D)) {
+    S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
+      << Attr.getName() << ExpectedFunction;
+    return;
+  }
+
+  D->addAttr(::new (S.Context) DestructorAttr(Attr.getRange(), S.Context,
+                                              priority));
+}
+
+static void handleDeprecatedAttr(Sema &S, Decl *D, const AttributeList &Attr) {
+  unsigned NumArgs = Attr.getNumArgs();
+  if (NumArgs > 1) {
+    S.Diag(Attr.getLoc(), diag::err_attribute_too_many_arguments) << 1;
+    return;
+  }
+  
+  // Handle the case where deprecated attribute has a text message.
+  StringRef Str;
+  if (NumArgs == 1) {
+    StringLiteral *SE = dyn_cast<StringLiteral>(Attr.getArg(0));
+    if (!SE) {
+      S.Diag(Attr.getArg(0)->getLocStart(), diag::err_attribute_not_string)
+        << "deprecated";
+      return;
+    }
+    Str = SE->getString();
+  }
+
+  D->addAttr(::new (S.Context) DeprecatedAttr(Attr.getRange(), S.Context, Str));
+}
+
+static void handleUnavailableAttr(Sema &S, Decl *D, const AttributeList &Attr) {
+  unsigned NumArgs = Attr.getNumArgs();
+  if (NumArgs > 1) {
+    S.Diag(Attr.getLoc(), diag::err_attribute_too_many_arguments) << 1;
+    return;
+  }
+  
+  // Handle the case where unavailable attribute has a text message.
+  StringRef Str;
+  if (NumArgs == 1) {
+    StringLiteral *SE = dyn_cast<StringLiteral>(Attr.getArg(0));
+    if (!SE) {
+      S.Diag(Attr.getArg(0)->getLocStart(), 
+             diag::err_attribute_not_string) << "unavailable";
+      return;
+    }
+    Str = SE->getString();
+  }
+  D->addAttr(::new (S.Context) UnavailableAttr(Attr.getRange(), S.Context, Str));
+}
+
+static void handleArcWeakrefUnavailableAttr(Sema &S, Decl *D, 
+                                            const AttributeList &Attr) {
+  unsigned NumArgs = Attr.getNumArgs();
+  if (NumArgs > 0) {
+    S.Diag(Attr.getLoc(), diag::err_attribute_too_many_arguments) << 0;
+    return;
+  }
+  
+  D->addAttr(::new (S.Context) ArcWeakrefUnavailableAttr(
+                                          Attr.getRange(), S.Context));
+}
+
+static void handleObjCRootClassAttr(Sema &S, Decl *D, 
+                                    const AttributeList &Attr) {
+  if (!isa<ObjCInterfaceDecl>(D)) {
+    S.Diag(Attr.getLoc(), diag::err_attribute_requires_objc_interface);
+    return;
+  }
+  
+  unsigned NumArgs = Attr.getNumArgs();
+  if (NumArgs > 0) {
+    S.Diag(Attr.getLoc(), diag::err_attribute_too_many_arguments) << 0;
+    return;
+  }
+  
+  D->addAttr(::new (S.Context) ObjCRootClassAttr(Attr.getRange(), S.Context));
+}
+
+static void handleObjCRequiresPropertyDefsAttr(Sema &S, Decl *D, 
+                                            const AttributeList &Attr) {
+  if (!isa<ObjCInterfaceDecl>(D)) {
+    S.Diag(Attr.getLoc(), diag::err_suppress_autosynthesis);
+    return;
+  }
+  
+  unsigned NumArgs = Attr.getNumArgs();
+  if (NumArgs > 0) {
+    S.Diag(Attr.getLoc(), diag::err_attribute_too_many_arguments) << 0;
+    return;
+  }
+  
+  D->addAttr(::new (S.Context) ObjCRequiresPropertyDefsAttr(
+                                 Attr.getRange(), S.Context));
+}
+
+static void handleAvailabilityAttr(Sema &S, Decl *D,
+                                   const AttributeList &Attr) {
+  IdentifierInfo *Platform = Attr.getParameterName();
+  SourceLocation PlatformLoc = Attr.getParameterLoc();
+
+  StringRef PlatformName
+    = AvailabilityAttr::getPrettyPlatformName(Platform->getName());
+  if (PlatformName.empty()) {
+    S.Diag(PlatformLoc, diag::warn_availability_unknown_platform)
+      << Platform;
+
+    PlatformName = Platform->getName();
+  }
+
+  AvailabilityChange Introduced = Attr.getAvailabilityIntroduced();
+  AvailabilityChange Deprecated = Attr.getAvailabilityDeprecated();
+  AvailabilityChange Obsoleted = Attr.getAvailabilityObsoleted();
+  bool IsUnavailable = Attr.getUnavailableLoc().isValid();
+
+  // Ensure that Introduced <= Deprecated <= Obsoleted (although not all
+  // of these steps are needed).
+  if (Introduced.isValid() && Deprecated.isValid() &&
+      !(Introduced.Version <= Deprecated.Version)) {
+    S.Diag(Introduced.KeywordLoc, diag::warn_availability_version_ordering)
+      << 1 << PlatformName << Deprecated.Version.getAsString()
+      << 0 << Introduced.Version.getAsString();
+    return;
+  }
+
+  if (Introduced.isValid() && Obsoleted.isValid() &&
+      !(Introduced.Version <= Obsoleted.Version)) {
+    S.Diag(Introduced.KeywordLoc, diag::warn_availability_version_ordering)
+      << 2 << PlatformName << Obsoleted.Version.getAsString()
+      << 0 << Introduced.Version.getAsString();
+    return;
+  }
+
+  if (Deprecated.isValid() && Obsoleted.isValid() &&
+      !(Deprecated.Version <= Obsoleted.Version)) {
+    S.Diag(Deprecated.KeywordLoc, diag::warn_availability_version_ordering)
+      << 2 << PlatformName << Obsoleted.Version.getAsString()
+      << 1 << Deprecated.Version.getAsString();
+    return;
+  }
+
+  StringRef Str;
+  const StringLiteral *SE = 
+    dyn_cast_or_null<const StringLiteral>(Attr.getMessageExpr());
+  if (SE)
+    Str = SE->getString();
+  
+  D->addAttr(::new (S.Context) AvailabilityAttr(Attr.getRange(), S.Context,
+                                                Platform,
+                                                Introduced.Version,
+                                                Deprecated.Version,
+                                                Obsoleted.Version,
+                                                IsUnavailable, 
+                                                Str));
+}
+
+static void handleVisibilityAttr(Sema &S, Decl *D, const AttributeList &Attr) {
+  // check the attribute arguments.
+  if(!checkAttributeNumArgs(S, Attr, 1))
+    return;
+
+  Expr *Arg = Attr.getArg(0);
+  Arg = Arg->IgnoreParenCasts();
+  StringLiteral *Str = dyn_cast<StringLiteral>(Arg);
+
+  if (!Str || !Str->isAscii()) {
+    S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_string)
+      << "visibility" << 1;
+    return;
+  }
+
+  StringRef TypeStr = Str->getString();
+  VisibilityAttr::VisibilityType type;
+
+  if (TypeStr == "default")
+    type = VisibilityAttr::Default;
+  else if (TypeStr == "hidden")
+    type = VisibilityAttr::Hidden;
+  else if (TypeStr == "internal")
+    type = VisibilityAttr::Hidden; // FIXME
+  else if (TypeStr == "protected") {
+    // Complain about attempts to use protected visibility on targets
+    // (like Darwin) that don't support it.
+    if (!S.Context.getTargetInfo().hasProtectedVisibility()) {
+      S.Diag(Attr.getLoc(), diag::warn_attribute_protected_visibility);
+      type = VisibilityAttr::Default;
+    } else {
+      type = VisibilityAttr::Protected;
+    }
+  } else {
+    S.Diag(Attr.getLoc(), diag::warn_attribute_unknown_visibility) << TypeStr;
+    return;
+  }
+
+  D->addAttr(::new (S.Context) VisibilityAttr(Attr.getRange(), S.Context, type));
+}
+
+static void handleObjCMethodFamilyAttr(Sema &S, Decl *decl,
+                                       const AttributeList &Attr) {
+  ObjCMethodDecl *method = dyn_cast<ObjCMethodDecl>(decl);
+  if (!method) {
+    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type)
+      << ExpectedMethod;
+    return;
+  }
+
+  if (Attr.getNumArgs() != 0 || !Attr.getParameterName()) {
+    if (!Attr.getParameterName() && Attr.getNumArgs() == 1) {
+      S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_string)
+        << "objc_method_family" << 1;
+    } else {
+      S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
+    }
+    Attr.setInvalid();
+    return;
+  }
+
+  StringRef param = Attr.getParameterName()->getName();
+  ObjCMethodFamilyAttr::FamilyKind family;
+  if (param == "none")
+    family = ObjCMethodFamilyAttr::OMF_None;
+  else if (param == "alloc")
+    family = ObjCMethodFamilyAttr::OMF_alloc;
+  else if (param == "copy")
+    family = ObjCMethodFamilyAttr::OMF_copy;
+  else if (param == "init")
+    family = ObjCMethodFamilyAttr::OMF_init;
+  else if (param == "mutableCopy")
+    family = ObjCMethodFamilyAttr::OMF_mutableCopy;
+  else if (param == "new")
+    family = ObjCMethodFamilyAttr::OMF_new;
+  else {
+    // Just warn and ignore it.  This is future-proof against new
+    // families being used in system headers.
+    S.Diag(Attr.getParameterLoc(), diag::warn_unknown_method_family);
+    return;
+  }
+
+  if (family == ObjCMethodFamilyAttr::OMF_init && 
+      !method->getResultType()->isObjCObjectPointerType()) {
+    S.Diag(method->getLocation(), diag::err_init_method_bad_return_type)
+      << method->getResultType();
+    // Ignore the attribute.
+    return;
+  }
+
+  method->addAttr(new (S.Context) ObjCMethodFamilyAttr(Attr.getRange(),
+                                                       S.Context, family));
+}
+
+static void handleObjCExceptionAttr(Sema &S, Decl *D,
+                                    const AttributeList &Attr) {
+  if (!checkAttributeNumArgs(S, Attr, 0))
+    return;
+
+  ObjCInterfaceDecl *OCI = dyn_cast<ObjCInterfaceDecl>(D);
+  if (OCI == 0) {
+    S.Diag(Attr.getLoc(), diag::err_attribute_requires_objc_interface);
+    return;
+  }
+
+  D->addAttr(::new (S.Context) ObjCExceptionAttr(Attr.getRange(), S.Context));
+}
+
+static void handleObjCNSObject(Sema &S, Decl *D, const AttributeList &Attr) {
+  if (Attr.getNumArgs() != 0) {
+    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
+    return;
+  }
+  if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(D)) {
+    QualType T = TD->getUnderlyingType();
+    if (!T->isPointerType() ||
+        !T->getAs<PointerType>()->getPointeeType()->isRecordType()) {
+      S.Diag(TD->getLocation(), diag::err_nsobject_attribute);
+      return;
+    }
+  }
+  else if (!isa<ObjCPropertyDecl>(D)) {
+    // It is okay to include this attribute on properties, e.g.:
+    //
+    //  @property (retain, nonatomic) struct Bork *Q __attribute__((NSObject));
+    //
+    // In this case it follows tradition and suppresses an error in the above
+    // case.    
+    S.Diag(D->getLocation(), diag::warn_nsobject_attribute);
+  }
+  D->addAttr(::new (S.Context) ObjCNSObjectAttr(Attr.getRange(), S.Context));
+}
+
+static void
+handleOverloadableAttr(Sema &S, Decl *D, const AttributeList &Attr) {
+  if (Attr.getNumArgs() != 0) {
+    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
+    return;
+  }
+
+  if (!isa<FunctionDecl>(D)) {
+    S.Diag(Attr.getLoc(), diag::err_attribute_overloadable_not_function);
+    return;
+  }
+
+  D->addAttr(::new (S.Context) OverloadableAttr(Attr.getRange(), S.Context));
+}
+
+static void handleBlocksAttr(Sema &S, Decl *D, const AttributeList &Attr) {
+  if (!Attr.getParameterName()) {
+    S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_string)
+      << "blocks" << 1;
+    return;
+  }
+
+  if (Attr.getNumArgs() != 0) {
+    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
+    return;
+  }
+
+  BlocksAttr::BlockType type;
+  if (Attr.getParameterName()->isStr("byref"))
+    type = BlocksAttr::ByRef;
+  else {
+    S.Diag(Attr.getLoc(), diag::warn_attribute_type_not_supported)
+      << "blocks" << Attr.getParameterName();
+    return;
+  }
+
+  D->addAttr(::new (S.Context) BlocksAttr(Attr.getRange(), S.Context, type));
+}
+
+static void handleSentinelAttr(Sema &S, Decl *D, const AttributeList &Attr) {
+  // check the attribute arguments.
+  if (Attr.getNumArgs() > 2) {
+    S.Diag(Attr.getLoc(), diag::err_attribute_too_many_arguments) << 2;
+    return;
+  }
+
+  unsigned sentinel = 0;
+  if (Attr.getNumArgs() > 0) {
+    Expr *E = Attr.getArg(0);
+    llvm::APSInt Idx(32);
+    if (E->isTypeDependent() || E->isValueDependent() ||
+        !E->isIntegerConstantExpr(Idx, S.Context)) {
+      S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_int)
+       << "sentinel" << 1 << E->getSourceRange();
+      return;
+    }
+
+    if (Idx.isSigned() && Idx.isNegative()) {
+      S.Diag(Attr.getLoc(), diag::err_attribute_sentinel_less_than_zero)
+        << E->getSourceRange();
+      return;
+    }
+
+    sentinel = Idx.getZExtValue();
+  }
+
+  unsigned nullPos = 0;
+  if (Attr.getNumArgs() > 1) {
+    Expr *E = Attr.getArg(1);
+    llvm::APSInt Idx(32);
+    if (E->isTypeDependent() || E->isValueDependent() ||
+        !E->isIntegerConstantExpr(Idx, S.Context)) {
+      S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_int)
+        << "sentinel" << 2 << E->getSourceRange();
+      return;
+    }
+    nullPos = Idx.getZExtValue();
+
+    if ((Idx.isSigned() && Idx.isNegative()) || nullPos > 1) {
+      // FIXME: This error message could be improved, it would be nice
+      // to say what the bounds actually are.
+      S.Diag(Attr.getLoc(), diag::err_attribute_sentinel_not_zero_or_one)
+        << E->getSourceRange();
+      return;
+    }
+  }
+
+  if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
+    const FunctionType *FT = FD->getType()->castAs<FunctionType>();
+    if (isa<FunctionNoProtoType>(FT)) {
+      S.Diag(Attr.getLoc(), diag::warn_attribute_sentinel_named_arguments);
+      return;
+    }
+
+    if (!cast<FunctionProtoType>(FT)->isVariadic()) {
+      S.Diag(Attr.getLoc(), diag::warn_attribute_sentinel_not_variadic) << 0;
+      return;
+    }
+  } else if (ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) {
+    if (!MD->isVariadic()) {
+      S.Diag(Attr.getLoc(), diag::warn_attribute_sentinel_not_variadic) << 0;
+      return;
+    }
+  } else if (BlockDecl *BD = dyn_cast<BlockDecl>(D)) {
+    if (!BD->isVariadic()) {
+      S.Diag(Attr.getLoc(), diag::warn_attribute_sentinel_not_variadic) << 1;
+      return;
+    }
+  } else if (const VarDecl *V = dyn_cast<VarDecl>(D)) {
+    QualType Ty = V->getType();
+    if (Ty->isBlockPointerType() || Ty->isFunctionPointerType()) {
+      const FunctionType *FT = Ty->isFunctionPointerType() ? getFunctionType(D)
+       : Ty->getAs<BlockPointerType>()->getPointeeType()->getAs<FunctionType>();
+      if (!cast<FunctionProtoType>(FT)->isVariadic()) {
+        int m = Ty->isFunctionPointerType() ? 0 : 1;
+        S.Diag(Attr.getLoc(), diag::warn_attribute_sentinel_not_variadic) << m;
+        return;
+      }
+    } else {
+      S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
+        << Attr.getName() << ExpectedFunctionMethodOrBlock;
+      return;
+    }
+  } else {
+    S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
+      << Attr.getName() << ExpectedFunctionMethodOrBlock;
+    return;
+  }
+  D->addAttr(::new (S.Context) SentinelAttr(Attr.getRange(), S.Context, sentinel,
+                                            nullPos));
+}
+
+static void handleWarnUnusedResult(Sema &S, Decl *D, const AttributeList &Attr) {
+  // check the attribute arguments.
+  if (!checkAttributeNumArgs(S, Attr, 0))
+    return;
+
+  if (!isFunction(D) && !isa<ObjCMethodDecl>(D)) {
+    S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
+      << Attr.getName() << ExpectedFunctionOrMethod;
+    return;
+  }
+
+  if (isFunction(D) && getFunctionType(D)->getResultType()->isVoidType()) {
+    S.Diag(Attr.getLoc(), diag::warn_attribute_void_function_method)
+      << Attr.getName() << 0;
+    return;
+  }
+  if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D))
+    if (MD->getResultType()->isVoidType()) {
+      S.Diag(Attr.getLoc(), diag::warn_attribute_void_function_method)
+      << Attr.getName() << 1;
+      return;
+    }
+  
+  D->addAttr(::new (S.Context) WarnUnusedResultAttr(Attr.getRange(), S.Context));
+}
+
+static void handleWeakAttr(Sema &S, Decl *D, const AttributeList &Attr) {
+  // check the attribute arguments.
+  if (Attr.hasParameterOrArguments()) {
+    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
+    return;
+  }
+
+  if (!isa<VarDecl>(D) && !isa<FunctionDecl>(D)) {
+    if (isa<CXXRecordDecl>(D)) {
+      D->addAttr(::new (S.Context) WeakAttr(Attr.getRange(), S.Context));
+      return;
+    }
+    S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
+      << Attr.getName() << ExpectedVariableOrFunction;
+    return;
+  }
+
+  NamedDecl *nd = cast<NamedDecl>(D);
+
+  // 'weak' only applies to declarations with external linkage.
+  if (hasEffectivelyInternalLinkage(nd)) {
+    S.Diag(Attr.getLoc(), diag::err_attribute_weak_static);
+    return;
+  }
+
+  nd->addAttr(::new (S.Context) WeakAttr(Attr.getRange(), S.Context));
+}
+
+static void handleWeakImportAttr(Sema &S, Decl *D, const AttributeList &Attr) {
+  // check the attribute arguments.
+  if (!checkAttributeNumArgs(S, Attr, 0))
+    return;
+
+
+  // weak_import only applies to variable & function declarations.
+  bool isDef = false;
+  if (!D->canBeWeakImported(isDef)) {
+    if (isDef)
+      S.Diag(Attr.getLoc(),
+             diag::warn_attribute_weak_import_invalid_on_definition)
+        << "weak_import" << 2 /*variable and function*/;
+    else if (isa<ObjCPropertyDecl>(D) || isa<ObjCMethodDecl>(D) ||
+             (S.Context.getTargetInfo().getTriple().isOSDarwin() &&
+              (isa<ObjCInterfaceDecl>(D) || isa<EnumDecl>(D)))) {
+      // Nothing to warn about here.
+    } else
+      S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
+        << Attr.getName() << ExpectedVariableOrFunction;
+
+    return;
+  }
+
+  D->addAttr(::new (S.Context) WeakImportAttr(Attr.getRange(), S.Context));
+}
+
+static void handleReqdWorkGroupSize(Sema &S, Decl *D,
+                                    const AttributeList &Attr) {
+  // Attribute has 3 arguments.
+  if (!checkAttributeNumArgs(S, Attr, 3))
+    return;
+
+  unsigned WGSize[3];
+  for (unsigned i = 0; i < 3; ++i) {
+    Expr *E = Attr.getArg(i);
+    llvm::APSInt ArgNum(32);
+    if (E->isTypeDependent() || E->isValueDependent() ||
+        !E->isIntegerConstantExpr(ArgNum, S.Context)) {
+      S.Diag(Attr.getLoc(), diag::err_attribute_argument_not_int)
+        << "reqd_work_group_size" << E->getSourceRange();
+      return;
+    }
+    WGSize[i] = (unsigned) ArgNum.getZExtValue();
+  }
+  D->addAttr(::new (S.Context) ReqdWorkGroupSizeAttr(Attr.getRange(), S.Context,
+                                                     WGSize[0], WGSize[1],
+                                                     WGSize[2]));
+}
+
+static void handleSectionAttr(Sema &S, Decl *D, const AttributeList &Attr) {
+  // Attribute has no arguments.
+  if (!checkAttributeNumArgs(S, Attr, 1))
+    return;
+
+  // Make sure that there is a string literal as the sections's single
+  // argument.
+  Expr *ArgExpr = Attr.getArg(0);
+  StringLiteral *SE = dyn_cast<StringLiteral>(ArgExpr);
+  if (!SE) {
+    S.Diag(ArgExpr->getLocStart(), diag::err_attribute_not_string) << "section";
+    return;
+  }
+
+  // If the target wants to validate the section specifier, make it happen.
+  std::string Error = S.Context.getTargetInfo().isValidSectionSpecifier(SE->getString());
+  if (!Error.empty()) {
+    S.Diag(SE->getLocStart(), diag::err_attribute_section_invalid_for_target)
+    << Error;
+    return;
+  }
+
+  // This attribute cannot be applied to local variables.
+  if (isa<VarDecl>(D) && cast<VarDecl>(D)->hasLocalStorage()) {
+    S.Diag(SE->getLocStart(), diag::err_attribute_section_local_variable);
+    return;
+  }
+  
+  D->addAttr(::new (S.Context) SectionAttr(Attr.getRange(), S.Context,
+                                           SE->getString()));
+}
+
+
+static void handleNothrowAttr(Sema &S, Decl *D, const AttributeList &Attr) {
+  // check the attribute arguments.
+  if (Attr.hasParameterOrArguments()) {
+    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
+    return;
+  }
+  
+  if (NoThrowAttr *Existing = D->getAttr<NoThrowAttr>()) {
+    if (Existing->getLocation().isInvalid())
+      Existing->setRange(Attr.getRange());
+  } else {
+    D->addAttr(::new (S.Context) NoThrowAttr(Attr.getRange(), S.Context));
+  }
+}
+
+static void handleConstAttr(Sema &S, Decl *D, const AttributeList &Attr) {
+  // check the attribute arguments.
+  if (Attr.hasParameterOrArguments()) {
+    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
+    return;
+  }
+
+  if (ConstAttr *Existing = D->getAttr<ConstAttr>()) {
+   if (Existing->getLocation().isInvalid())
+     Existing->setRange(Attr.getRange());
+  } else {
+    D->addAttr(::new (S.Context) ConstAttr(Attr.getRange(), S.Context));
+  }
+}
+
+static void handlePureAttr(Sema &S, Decl *D, const AttributeList &Attr) {
+  // check the attribute arguments.
+  if (!checkAttributeNumArgs(S, Attr, 0))
+    return;
+
+  D->addAttr(::new (S.Context) PureAttr(Attr.getRange(), S.Context));
+}
+
+static void handleCleanupAttr(Sema &S, Decl *D, const AttributeList &Attr) {
+  if (!Attr.getParameterName()) {
+    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
+    return;
+  }
+
+  if (Attr.getNumArgs() != 0) {
+    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
+    return;
+  }
+
+  VarDecl *VD = dyn_cast<VarDecl>(D);
+
+  if (!VD || !VD->hasLocalStorage()) {
+    S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "cleanup";
+    return;
+  }
+
+  // Look up the function
+  // FIXME: Lookup probably isn't looking in the right place
+  NamedDecl *CleanupDecl
+    = S.LookupSingleName(S.TUScope, Attr.getParameterName(),
+                         Attr.getParameterLoc(), Sema::LookupOrdinaryName);
+  if (!CleanupDecl) {
+    S.Diag(Attr.getParameterLoc(), diag::err_attribute_cleanup_arg_not_found) <<
+      Attr.getParameterName();
+    return;
+  }
+
+  FunctionDecl *FD = dyn_cast<FunctionDecl>(CleanupDecl);
+  if (!FD) {
+    S.Diag(Attr.getParameterLoc(),
+           diag::err_attribute_cleanup_arg_not_function)
+      << Attr.getParameterName();
+    return;
+  }
+
+  if (FD->getNumParams() != 1) {
+    S.Diag(Attr.getParameterLoc(),
+           diag::err_attribute_cleanup_func_must_take_one_arg)
+      << Attr.getParameterName();
+    return;
+  }
+
+  // We're currently more strict than GCC about what function types we accept.
+  // If this ever proves to be a problem it should be easy to fix.
+  QualType Ty = S.Context.getPointerType(VD->getType());
+  QualType ParamTy = FD->getParamDecl(0)->getType();
+  if (S.CheckAssignmentConstraints(FD->getParamDecl(0)->getLocation(),
+                                   ParamTy, Ty) != Sema::Compatible) {
+    S.Diag(Attr.getParameterLoc(),
+           diag::err_attribute_cleanup_func_arg_incompatible_type) <<
+      Attr.getParameterName() << ParamTy << Ty;
+    return;
+  }
+
+  D->addAttr(::new (S.Context) CleanupAttr(Attr.getRange(), S.Context, FD));
+  S.MarkFunctionReferenced(Attr.getParameterLoc(), FD);
+}
+
+/// Handle __attribute__((format_arg((idx)))) attribute based on
+/// http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html
+static void handleFormatArgAttr(Sema &S, Decl *D, const AttributeList &Attr) {
+  if (!checkAttributeNumArgs(S, Attr, 1))
+    return;
+
+  if (!isFunctionOrMethod(D) || !hasFunctionProto(D)) {
+    S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
+      << Attr.getName() << ExpectedFunction;
+    return;
+  }
+
+  // In C++ the implicit 'this' function parameter also counts, and they are
+  // counted from one.
+  bool HasImplicitThisParam = isInstanceMethod(D);
+  unsigned NumArgs  = getFunctionOrMethodNumArgs(D) + HasImplicitThisParam;
+  unsigned FirstIdx = 1;
+
+  // checks for the 2nd argument
+  Expr *IdxExpr = Attr.getArg(0);
+  llvm::APSInt Idx(32);
+  if (IdxExpr->isTypeDependent() || IdxExpr->isValueDependent() ||
+      !IdxExpr->isIntegerConstantExpr(Idx, S.Context)) {
+    S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_int)
+    << "format" << 2 << IdxExpr->getSourceRange();
+    return;
+  }
+
+  if (Idx.getZExtValue() < FirstIdx || Idx.getZExtValue() > NumArgs) {
+    S.Diag(Attr.getLoc(), diag::err_attribute_argument_out_of_bounds)
+    << "format" << 2 << IdxExpr->getSourceRange();
+    return;
+  }
+
+  unsigned ArgIdx = Idx.getZExtValue() - 1;
+
+  if (HasImplicitThisParam) {
+    if (ArgIdx == 0) {
+      S.Diag(Attr.getLoc(), diag::err_attribute_invalid_implicit_this_argument)
+        << "format_arg" << IdxExpr->getSourceRange();
+      return;
+    }
+    ArgIdx--;
+  }
+
+  // make sure the format string is really a string
+  QualType Ty = getFunctionOrMethodArgType(D, ArgIdx);
+
+  bool not_nsstring_type = !isNSStringType(Ty, S.Context);
+  if (not_nsstring_type &&
+      !isCFStringType(Ty, S.Context) &&
+      (!Ty->isPointerType() ||
+       !Ty->getAs<PointerType>()->getPointeeType()->isCharType())) {
+    // FIXME: Should highlight the actual expression that has the wrong type.
+    S.Diag(Attr.getLoc(), diag::err_format_attribute_not)
+    << (not_nsstring_type ? "a string type" : "an NSString")
+       << IdxExpr->getSourceRange();
+    return;
+  }
+  Ty = getFunctionOrMethodResultType(D);
+  if (!isNSStringType(Ty, S.Context) &&
+      !isCFStringType(Ty, S.Context) &&
+      (!Ty->isPointerType() ||
+       !Ty->getAs<PointerType>()->getPointeeType()->isCharType())) {
+    // FIXME: Should highlight the actual expression that has the wrong type.
+    S.Diag(Attr.getLoc(), diag::err_format_attribute_result_not)
+    << (not_nsstring_type ? "string type" : "NSString")
+       << IdxExpr->getSourceRange();
+    return;
+  }
+
+  D->addAttr(::new (S.Context) FormatArgAttr(Attr.getRange(), S.Context,
+                                             Idx.getZExtValue()));
+}
+
+enum FormatAttrKind {
+  CFStringFormat,
+  NSStringFormat,
+  StrftimeFormat,
+  SupportedFormat,
+  IgnoredFormat,
+  InvalidFormat
+};
+
+/// getFormatAttrKind - Map from format attribute names to supported format
+/// types.
+static FormatAttrKind getFormatAttrKind(StringRef Format) {
+  // Check for formats that get handled specially.
+  if (Format == "NSString")
+    return NSStringFormat;
+  if (Format == "CFString")
+    return CFStringFormat;
+  if (Format == "strftime")
+    return StrftimeFormat;
+
+  // Otherwise, check for supported formats.
+  if (Format == "scanf" || Format == "printf" || Format == "printf0" ||
+      Format == "strfmon" || Format == "cmn_err" || Format == "vcmn_err" ||
+      Format == "zcmn_err" ||
+      Format == "kprintf")  // OpenBSD.
+    return SupportedFormat;
+
+  if (Format == "gcc_diag" || Format == "gcc_cdiag" ||
+      Format == "gcc_cxxdiag" || Format == "gcc_tdiag")
+    return IgnoredFormat;
+  
+  return InvalidFormat;
+}
+
+/// Handle __attribute__((init_priority(priority))) attributes based on
+/// http://gcc.gnu.org/onlinedocs/gcc/C_002b_002b-Attributes.html
+static void handleInitPriorityAttr(Sema &S, Decl *D,
+                                   const AttributeList &Attr) {
+  if (!S.getLangOpts().CPlusPlus) {
+    S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName();
+    return;
+  }
+  
+  if (!isa<VarDecl>(D) || S.getCurFunctionOrMethodDecl()) {
+    S.Diag(Attr.getLoc(), diag::err_init_priority_object_attr);
+    Attr.setInvalid();
+    return;
+  }
+  QualType T = dyn_cast<VarDecl>(D)->getType();
+  if (S.Context.getAsArrayType(T))
+    T = S.Context.getBaseElementType(T);
+  if (!T->getAs<RecordType>()) {
+    S.Diag(Attr.getLoc(), diag::err_init_priority_object_attr);
+    Attr.setInvalid();
+    return;
+  }
+  
+  if (Attr.getNumArgs() != 1) {
+    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
+    Attr.setInvalid();
+    return;
+  }
+  Expr *priorityExpr = Attr.getArg(0);
+  
+  llvm::APSInt priority(32);
+  if (priorityExpr->isTypeDependent() || priorityExpr->isValueDependent() ||
+      !priorityExpr->isIntegerConstantExpr(priority, S.Context)) {
+    S.Diag(Attr.getLoc(), diag::err_attribute_argument_not_int)
+    << "init_priority" << priorityExpr->getSourceRange();
+    Attr.setInvalid();
+    return;
+  }
+  unsigned prioritynum = priority.getZExtValue();
+  if (prioritynum < 101 || prioritynum > 65535) {
+    S.Diag(Attr.getLoc(), diag::err_attribute_argument_outof_range)
+    <<  priorityExpr->getSourceRange();
+    Attr.setInvalid();
+    return;
+  }
+  D->addAttr(::new (S.Context) InitPriorityAttr(Attr.getRange(), S.Context,
+                                                prioritynum));
+}
+
+/// Handle __attribute__((format(type,idx,firstarg))) attributes based on
+/// http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html
+static void handleFormatAttr(Sema &S, Decl *D, const AttributeList &Attr) {
+
+  if (!Attr.getParameterName()) {
+    S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_string)
+      << "format" << 1;
+    return;
+  }
+
+  if (Attr.getNumArgs() != 2) {
+    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 3;
+    return;
+  }
+
+  if (!isFunctionOrMethodOrBlock(D) || !hasFunctionProto(D)) {
+    S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
+      << Attr.getName() << ExpectedFunction;
+    return;
+  }
+
+  // In C++ the implicit 'this' function parameter also counts, and they are
+  // counted from one.
+  bool HasImplicitThisParam = isInstanceMethod(D);
+  unsigned NumArgs  = getFunctionOrMethodNumArgs(D) + HasImplicitThisParam;
+  unsigned FirstIdx = 1;
+
+  StringRef Format = Attr.getParameterName()->getName();
+
+  // Normalize the argument, __foo__ becomes foo.
+  if (Format.startswith("__") && Format.endswith("__"))
+    Format = Format.substr(2, Format.size() - 4);
+
+  // Check for supported formats.
+  FormatAttrKind Kind = getFormatAttrKind(Format);
+  
+  if (Kind == IgnoredFormat)
+    return;
+  
+  if (Kind == InvalidFormat) {
+    S.Diag(Attr.getLoc(), diag::warn_attribute_type_not_supported)
+      << "format" << Attr.getParameterName()->getName();
+    return;
+  }
+
+  // checks for the 2nd argument
+  Expr *IdxExpr = Attr.getArg(0);
+  llvm::APSInt Idx(32);
+  if (IdxExpr->isTypeDependent() || IdxExpr->isValueDependent() ||
+      !IdxExpr->isIntegerConstantExpr(Idx, S.Context)) {
+    S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_int)
+      << "format" << 2 << IdxExpr->getSourceRange();
+    return;
+  }
+
+  if (Idx.getZExtValue() < FirstIdx || Idx.getZExtValue() > NumArgs) {
+    S.Diag(Attr.getLoc(), diag::err_attribute_argument_out_of_bounds)
+      << "format" << 2 << IdxExpr->getSourceRange();
+    return;
+  }
+
+  // FIXME: Do we need to bounds check?
+  unsigned ArgIdx = Idx.getZExtValue() - 1;
+
+  if (HasImplicitThisParam) {
+    if (ArgIdx == 0) {
+      S.Diag(Attr.getLoc(),
+             diag::err_format_attribute_implicit_this_format_string)
+        << IdxExpr->getSourceRange();
+      return;
+    }
+    ArgIdx--;
+  }
+
+  // make sure the format string is really a string
+  QualType Ty = getFunctionOrMethodArgType(D, ArgIdx);
+
+  if (Kind == CFStringFormat) {
+    if (!isCFStringType(Ty, S.Context)) {
+      S.Diag(Attr.getLoc(), diag::err_format_attribute_not)
+        << "a CFString" << IdxExpr->getSourceRange();
+      return;
+    }
+  } else if (Kind == NSStringFormat) {
+    // FIXME: do we need to check if the type is NSString*?  What are the
+    // semantics?
+    if (!isNSStringType(Ty, S.Context)) {
+      // FIXME: Should highlight the actual expression that has the wrong type.
+      S.Diag(Attr.getLoc(), diag::err_format_attribute_not)
+        << "an NSString" << IdxExpr->getSourceRange();
+      return;
+    }
+  } else if (!Ty->isPointerType() ||
+             !Ty->getAs<PointerType>()->getPointeeType()->isCharType()) {
+    // FIXME: Should highlight the actual expression that has the wrong type.
+    S.Diag(Attr.getLoc(), diag::err_format_attribute_not)
+      << "a string type" << IdxExpr->getSourceRange();
+    return;
+  }
+
+  // check the 3rd argument
+  Expr *FirstArgExpr = Attr.getArg(1);
+  llvm::APSInt FirstArg(32);
+  if (FirstArgExpr->isTypeDependent() || FirstArgExpr->isValueDependent() ||
+      !FirstArgExpr->isIntegerConstantExpr(FirstArg, S.Context)) {
+    S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_int)
+      << "format" << 3 << FirstArgExpr->getSourceRange();
+    return;
+  }
+
+  // check if the function is variadic if the 3rd argument non-zero
+  if (FirstArg != 0) {
+    if (isFunctionOrMethodVariadic(D)) {
+      ++NumArgs; // +1 for ...
+    } else {
+      S.Diag(D->getLocation(), diag::err_format_attribute_requires_variadic);
+      return;
+    }
+  }
+
+  // strftime requires FirstArg to be 0 because it doesn't read from any
+  // variable the input is just the current time + the format string.
+  if (Kind == StrftimeFormat) {
+    if (FirstArg != 0) {
+      S.Diag(Attr.getLoc(), diag::err_format_strftime_third_parameter)
+        << FirstArgExpr->getSourceRange();
+      return;
+    }
+  // if 0 it disables parameter checking (to use with e.g. va_list)
+  } else if (FirstArg != 0 && FirstArg != NumArgs) {
+    S.Diag(Attr.getLoc(), diag::err_attribute_argument_out_of_bounds)
+      << "format" << 3 << FirstArgExpr->getSourceRange();
+    return;
+  }
+
+  // Check whether we already have an equivalent format attribute.
+  for (specific_attr_iterator<FormatAttr>
+         i = D->specific_attr_begin<FormatAttr>(),
+         e = D->specific_attr_end<FormatAttr>();
+       i != e ; ++i) {
+    FormatAttr *f = *i;
+    if (f->getType() == Format &&
+        f->getFormatIdx() == (int)Idx.getZExtValue() &&
+        f->getFirstArg() == (int)FirstArg.getZExtValue()) {
+      // If we don't have a valid location for this attribute, adopt the
+      // location.
+      if (f->getLocation().isInvalid())
+        f->setRange(Attr.getRange());
+      return;
+    }
+  }
+  
+  D->addAttr(::new (S.Context) FormatAttr(Attr.getRange(), S.Context, Format,
+                                          Idx.getZExtValue(),
+                                          FirstArg.getZExtValue()));
+}
+
+static void handleTransparentUnionAttr(Sema &S, Decl *D,
+                                       const AttributeList &Attr) {
+  // check the attribute arguments.
+  if (!checkAttributeNumArgs(S, Attr, 0))
+    return;
+
+
+  // Try to find the underlying union declaration.
+  RecordDecl *RD = 0;
+  TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(D);
+  if (TD && TD->getUnderlyingType()->isUnionType())
+    RD = TD->getUnderlyingType()->getAsUnionType()->getDecl();
+  else
+    RD = dyn_cast<RecordDecl>(D);
+
+  if (!RD || !RD->isUnion()) {
+    S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
+      << Attr.getName() << ExpectedUnion;
+    return;
+  }
+
+  if (!RD->isCompleteDefinition()) {
+    S.Diag(Attr.getLoc(),
+        diag::warn_transparent_union_attribute_not_definition);
+    return;
+  }
+
+  RecordDecl::field_iterator Field = RD->field_begin(),
+                          FieldEnd = RD->field_end();
+  if (Field == FieldEnd) {
+    S.Diag(Attr.getLoc(), diag::warn_transparent_union_attribute_zero_fields);
+    return;
+  }
+
+  FieldDecl *FirstField = *Field;
+  QualType FirstType = FirstField->getType();
+  if (FirstType->hasFloatingRepresentation() || FirstType->isVectorType()) {
+    S.Diag(FirstField->getLocation(),
+           diag::warn_transparent_union_attribute_floating)
+      << FirstType->isVectorType() << FirstType;
+    return;
+  }
+
+  uint64_t FirstSize = S.Context.getTypeSize(FirstType);
+  uint64_t FirstAlign = S.Context.getTypeAlign(FirstType);
+  for (; Field != FieldEnd; ++Field) {
+    QualType FieldType = Field->getType();
+    if (S.Context.getTypeSize(FieldType) != FirstSize ||
+        S.Context.getTypeAlign(FieldType) != FirstAlign) {
+      // Warn if we drop the attribute.
+      bool isSize = S.Context.getTypeSize(FieldType) != FirstSize;
+      unsigned FieldBits = isSize? S.Context.getTypeSize(FieldType)
+                                 : S.Context.getTypeAlign(FieldType);
+      S.Diag(Field->getLocation(),
+          diag::warn_transparent_union_attribute_field_size_align)
+        << isSize << Field->getDeclName() << FieldBits;
+      unsigned FirstBits = isSize? FirstSize : FirstAlign;
+      S.Diag(FirstField->getLocation(),
+             diag::note_transparent_union_first_field_size_align)
+        << isSize << FirstBits;
+      return;
+    }
+  }
+
+  RD->addAttr(::new (S.Context) TransparentUnionAttr(Attr.getRange(), S.Context));
+}
+
+static void handleAnnotateAttr(Sema &S, Decl *D, const AttributeList &Attr) {
+  // check the attribute arguments.
+  if (!checkAttributeNumArgs(S, Attr, 1))
+    return;
+
+  Expr *ArgExpr = Attr.getArg(0);
+  StringLiteral *SE = dyn_cast<StringLiteral>(ArgExpr);
+
+  // Make sure that there is a string literal as the annotation's single
+  // argument.
+  if (!SE) {
+    S.Diag(ArgExpr->getLocStart(), diag::err_attribute_not_string) <<"annotate";
+    return;
+  }
+
+  // Don't duplicate annotations that are already set.
+  for (specific_attr_iterator<AnnotateAttr>
+       i = D->specific_attr_begin<AnnotateAttr>(),
+       e = D->specific_attr_end<AnnotateAttr>(); i != e; ++i) {
+      if ((*i)->getAnnotation() == SE->getString())
+          return;
+  }
+  D->addAttr(::new (S.Context) AnnotateAttr(Attr.getRange(), S.Context,
+                                            SE->getString()));
+}
+
+static void handleAlignedAttr(Sema &S, Decl *D, const AttributeList &Attr) {
+  // check the attribute arguments.
+  if (Attr.getNumArgs() > 1) {
+    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
+    return;
+  }
+  
+  //FIXME: The C++0x version of this attribute has more limited applicabilty
+  //       than GNU's, and should error out when it is used to specify a
+  //       weaker alignment, rather than being silently ignored.
+
+  if (Attr.getNumArgs() == 0) {
+    D->addAttr(::new (S.Context) AlignedAttr(Attr.getRange(), S.Context, true, 0));
+    return;
+  }
+
+  S.AddAlignedAttr(Attr.getRange(), D, Attr.getArg(0));
+}
+
+void Sema::AddAlignedAttr(SourceRange AttrRange, Decl *D, Expr *E) {
+  // FIXME: Handle pack-expansions here.
+  if (DiagnoseUnexpandedParameterPack(E))
+    return;
+
+  if (E->isTypeDependent() || E->isValueDependent()) {
+    // Save dependent expressions in the AST to be instantiated.
+    D->addAttr(::new (Context) AlignedAttr(AttrRange, Context, true, E));
+    return;
+  }
+
+  SourceLocation AttrLoc = AttrRange.getBegin();
+  // FIXME: Cache the number on the Attr object?
+  llvm::APSInt Alignment(32);
+  ExprResult ICE =
+    VerifyIntegerConstantExpression(E, &Alignment,
+      PDiag(diag::err_attribute_argument_not_int) << "aligned",
+      /*AllowFold*/ false);
+  if (ICE.isInvalid())
+    return;
+  if (!llvm::isPowerOf2_64(Alignment.getZExtValue())) {
+    Diag(AttrLoc, diag::err_attribute_aligned_not_power_of_two)
+      << E->getSourceRange();
+    return;
+  }
+
+  D->addAttr(::new (Context) AlignedAttr(AttrRange, Context, true, ICE.take()));
+}
+
+void Sema::AddAlignedAttr(SourceRange AttrRange, Decl *D, TypeSourceInfo *TS) {
+  // FIXME: Cache the number on the Attr object if non-dependent?
+  // FIXME: Perform checking of type validity
+  D->addAttr(::new (Context) AlignedAttr(AttrRange, Context, false, TS));
+  return;
+}
+
+/// handleModeAttr - This attribute modifies the width of a decl with primitive
+/// type.
+///
+/// Despite what would be logical, the mode attribute is a decl attribute, not a
+/// type attribute: 'int ** __attribute((mode(HI))) *G;' tries to make 'G' be
+/// HImode, not an intermediate pointer.
+static void handleModeAttr(Sema &S, Decl *D, const AttributeList &Attr) {
+  // This attribute isn't documented, but glibc uses it.  It changes
+  // the width of an int or unsigned int to the specified size.
+
+  // Check that there aren't any arguments
+  if (!checkAttributeNumArgs(S, Attr, 0))
+    return;
+
+
+  IdentifierInfo *Name = Attr.getParameterName();
+  if (!Name) {
+    S.Diag(Attr.getLoc(), diag::err_attribute_missing_parameter_name);
+    return;
+  }
+
+  StringRef Str = Attr.getParameterName()->getName();
+
+  // Normalize the attribute name, __foo__ becomes foo.
+  if (Str.startswith("__") && Str.endswith("__"))
+    Str = Str.substr(2, Str.size() - 4);
+
+  unsigned DestWidth = 0;
+  bool IntegerMode = true;
+  bool ComplexMode = false;
+  switch (Str.size()) {
+  case 2:
+    switch (Str[0]) {
+    case 'Q': DestWidth = 8; break;
+    case 'H': DestWidth = 16; break;
+    case 'S': DestWidth = 32; break;
+    case 'D': DestWidth = 64; break;
+    case 'X': DestWidth = 96; break;
+    case 'T': DestWidth = 128; break;
+    }
+    if (Str[1] == 'F') {
+      IntegerMode = false;
+    } else if (Str[1] == 'C') {
+      IntegerMode = false;
+      ComplexMode = true;
+    } else if (Str[1] != 'I') {
+      DestWidth = 0;
+    }
+    break;
+  case 4:
+    // FIXME: glibc uses 'word' to define register_t; this is narrower than a
+    // pointer on PIC16 and other embedded platforms.
+    if (Str == "word")
+      DestWidth = S.Context.getTargetInfo().getPointerWidth(0);
+    else if (Str == "byte")
+      DestWidth = S.Context.getTargetInfo().getCharWidth();
+    break;
+  case 7:
+    if (Str == "pointer")
+      DestWidth = S.Context.getTargetInfo().getPointerWidth(0);
+    break;
+  }
+
+  QualType OldTy;
+  if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(D))
+    OldTy = TD->getUnderlyingType();
+  else if (ValueDecl *VD = dyn_cast<ValueDecl>(D))
+    OldTy = VD->getType();
+  else {
+    S.Diag(D->getLocation(), diag::err_attr_wrong_decl)
+      << "mode" << Attr.getRange();
+    return;
+  }
+
+  if (!OldTy->getAs<BuiltinType>() && !OldTy->isComplexType())
+    S.Diag(Attr.getLoc(), diag::err_mode_not_primitive);
+  else if (IntegerMode) {
+    if (!OldTy->isIntegralOrEnumerationType())
+      S.Diag(Attr.getLoc(), diag::err_mode_wrong_type);
+  } else if (ComplexMode) {
+    if (!OldTy->isComplexType())
+      S.Diag(Attr.getLoc(), diag::err_mode_wrong_type);
+  } else {
+    if (!OldTy->isFloatingType())
+      S.Diag(Attr.getLoc(), diag::err_mode_wrong_type);
+  }
+
+  // FIXME: Sync this with InitializePredefinedMacros; we need to match int8_t
+  // and friends, at least with glibc.
+  // FIXME: Make sure 32/64-bit integers don't get defined to types of the wrong
+  // width on unusual platforms.
+  // FIXME: Make sure floating-point mappings are accurate
+  // FIXME: Support XF and TF types
+  QualType NewTy;
+  switch (DestWidth) {
+  case 0:
+    S.Diag(Attr.getLoc(), diag::err_unknown_machine_mode) << Name;
+    return;
+  default:
+    S.Diag(Attr.getLoc(), diag::err_unsupported_machine_mode) << Name;
+    return;
+  case 8:
+    if (!IntegerMode) {
+      S.Diag(Attr.getLoc(), diag::err_unsupported_machine_mode) << Name;
+      return;
+    }
+    if (OldTy->isSignedIntegerType())
+      NewTy = S.Context.SignedCharTy;
+    else
+      NewTy = S.Context.UnsignedCharTy;
+    break;
+  case 16:
+    if (!IntegerMode) {
+      S.Diag(Attr.getLoc(), diag::err_unsupported_machine_mode) << Name;
+      return;
+    }
+    if (OldTy->isSignedIntegerType())
+      NewTy = S.Context.ShortTy;
+    else
+      NewTy = S.Context.UnsignedShortTy;
+    break;
+  case 32:
+    if (!IntegerMode)
+      NewTy = S.Context.FloatTy;
+    else if (OldTy->isSignedIntegerType())
+      NewTy = S.Context.IntTy;
+    else
+      NewTy = S.Context.UnsignedIntTy;
+    break;
+  case 64:
+    if (!IntegerMode)
+      NewTy = S.Context.DoubleTy;
+    else if (OldTy->isSignedIntegerType())
+      if (S.Context.getTargetInfo().getLongWidth() == 64)
+        NewTy = S.Context.LongTy;
+      else
+        NewTy = S.Context.LongLongTy;
+    else
+      if (S.Context.getTargetInfo().getLongWidth() == 64)
+        NewTy = S.Context.UnsignedLongTy;
+      else
+        NewTy = S.Context.UnsignedLongLongTy;
+    break;
+  case 96:
+    NewTy = S.Context.LongDoubleTy;
+    break;
+  case 128:
+    if (!IntegerMode) {
+      S.Diag(Attr.getLoc(), diag::err_unsupported_machine_mode) << Name;
+      return;
+    }
+    if (OldTy->isSignedIntegerType())
+      NewTy = S.Context.Int128Ty;
+    else
+      NewTy = S.Context.UnsignedInt128Ty;
+    break;
+  }
+
+  if (ComplexMode) {
+    NewTy = S.Context.getComplexType(NewTy);
+  }
+
+  // Install the new type.
+  if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(D)) {
+    // FIXME: preserve existing source info.
+    TD->setTypeSourceInfo(S.Context.getTrivialTypeSourceInfo(NewTy));
+  } else
+    cast<ValueDecl>(D)->setType(NewTy);
+}
+
+static void handleNoDebugAttr(Sema &S, Decl *D, const AttributeList &Attr) {
+  // check the attribute arguments.
+  if (!checkAttributeNumArgs(S, Attr, 0))
+    return;
+
+  if (!isFunctionOrMethod(D)) {
+    S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
+      << Attr.getName() << ExpectedFunction;
+    return;
+  }
+
+  D->addAttr(::new (S.Context) NoDebugAttr(Attr.getRange(), S.Context));
+}
+
+static void handleNoInlineAttr(Sema &S, Decl *D, const AttributeList &Attr) {
+  // check the attribute arguments.
+  if (!checkAttributeNumArgs(S, Attr, 0))
+    return;
+
+
+  if (!isa<FunctionDecl>(D)) {
+    S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
+      << Attr.getName() << ExpectedFunction;
+    return;
+  }
+
+  D->addAttr(::new (S.Context) NoInlineAttr(Attr.getRange(), S.Context));
+}
+
+static void handleNoInstrumentFunctionAttr(Sema &S, Decl *D,
+                                           const AttributeList &Attr) {
+  // check the attribute arguments.
+  if (!checkAttributeNumArgs(S, Attr, 0))
+    return;
+
+
+  if (!isa<FunctionDecl>(D)) {
+    S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
+      << Attr.getName() << ExpectedFunction;
+    return;
+  }
+
+  D->addAttr(::new (S.Context) NoInstrumentFunctionAttr(Attr.getRange(),
+                                                        S.Context));
+}
+
+static void handleConstantAttr(Sema &S, Decl *D, const AttributeList &Attr) {
+  if (S.LangOpts.CUDA) {
+    // check the attribute arguments.
+    if (Attr.hasParameterOrArguments()) {
+      S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
+      return;
+    }
+
+    if (!isa<VarDecl>(D)) {
+      S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
+        << Attr.getName() << ExpectedVariable;
+      return;
+    }
+
+    D->addAttr(::new (S.Context) CUDAConstantAttr(Attr.getRange(), S.Context));
+  } else {
+    S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "constant";
+  }
+}
+
+static void handleDeviceAttr(Sema &S, Decl *D, const AttributeList &Attr) {
+  if (S.LangOpts.CUDA) {
+    // check the attribute arguments.
+    if (Attr.getNumArgs() != 0) {
+      S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
+      return;
+    }
+
+    if (!isa<FunctionDecl>(D) && !isa<VarDecl>(D)) {
+      S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
+        << Attr.getName() << ExpectedVariableOrFunction;
+      return;
+    }
+
+    D->addAttr(::new (S.Context) CUDADeviceAttr(Attr.getRange(), S.Context));
+  } else {
+    S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "device";
+  }
+}
+
+static void handleGlobalAttr(Sema &S, Decl *D, const AttributeList &Attr) {
+  if (S.LangOpts.CUDA) {
+    // check the attribute arguments.
+    if (!checkAttributeNumArgs(S, Attr, 0))
+      return;
+
+    if (!isa<FunctionDecl>(D)) {
+      S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
+        << Attr.getName() << ExpectedFunction;
+      return;
+    }
+
+    FunctionDecl *FD = cast<FunctionDecl>(D);
+    if (!FD->getResultType()->isVoidType()) {
+      TypeLoc TL = FD->getTypeSourceInfo()->getTypeLoc().IgnoreParens();
+      if (FunctionTypeLoc* FTL = dyn_cast<FunctionTypeLoc>(&TL)) {
+        S.Diag(FD->getTypeSpecStartLoc(), diag::err_kern_type_not_void_return)
+          << FD->getType()
+          << FixItHint::CreateReplacement(FTL->getResultLoc().getSourceRange(),
+                                          "void");
+      } else {
+        S.Diag(FD->getTypeSpecStartLoc(), diag::err_kern_type_not_void_return)
+          << FD->getType();
+      }
+      return;
+    }
+
+    D->addAttr(::new (S.Context) CUDAGlobalAttr(Attr.getRange(), S.Context));
+  } else {
+    S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "global";
+  }
+}
+
+static void handleHostAttr(Sema &S, Decl *D, const AttributeList &Attr) {
+  if (S.LangOpts.CUDA) {
+    // check the attribute arguments.
+    if (!checkAttributeNumArgs(S, Attr, 0))
+      return;
+
+
+    if (!isa<FunctionDecl>(D)) {
+      S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
+        << Attr.getName() << ExpectedFunction;
+      return;
+    }
+
+    D->addAttr(::new (S.Context) CUDAHostAttr(Attr.getRange(), S.Context));
+  } else {
+    S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "host";
+  }
+}
+
+static void handleSharedAttr(Sema &S, Decl *D, const AttributeList &Attr) {
+  if (S.LangOpts.CUDA) {
+    // check the attribute arguments.
+    if (!checkAttributeNumArgs(S, Attr, 0))
+      return;
+
+
+    if (!isa<VarDecl>(D)) {
+      S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
+        << Attr.getName() << ExpectedVariable;
+      return;
+    }
+
+    D->addAttr(::new (S.Context) CUDASharedAttr(Attr.getRange(), S.Context));
+  } else {
+    S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "shared";
+  }
+}
+
+static void handleGNUInlineAttr(Sema &S, Decl *D, const AttributeList &Attr) {
+  // check the attribute arguments.
+  if (!checkAttributeNumArgs(S, Attr, 0))
+    return;
+
+  FunctionDecl *Fn = dyn_cast<FunctionDecl>(D);
+  if (Fn == 0) {
+    S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
+      << Attr.getName() << ExpectedFunction;
+    return;
+  }
+
+  if (!Fn->isInlineSpecified()) {
+    S.Diag(Attr.getLoc(), diag::warn_gnu_inline_attribute_requires_inline);
+    return;
+  }
+
+  D->addAttr(::new (S.Context) GNUInlineAttr(Attr.getRange(), S.Context));
+}
+
+static void handleCallConvAttr(Sema &S, Decl *D, const AttributeList &Attr) {
+  if (hasDeclarator(D)) return;
+
+  // Diagnostic is emitted elsewhere: here we store the (valid) Attr
+  // in the Decl node for syntactic reasoning, e.g., pretty-printing.
+  CallingConv CC;
+  if (S.CheckCallingConvAttr(Attr, CC))
+    return;
+
+  if (!isa<ObjCMethodDecl>(D)) {
+    S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
+      << Attr.getName() << ExpectedFunctionOrMethod;
+    return;
+  }
+
+  switch (Attr.getKind()) {
+  case AttributeList::AT_fastcall:
+    D->addAttr(::new (S.Context) FastCallAttr(Attr.getRange(), S.Context));
+    return;
+  case AttributeList::AT_stdcall:
+    D->addAttr(::new (S.Context) StdCallAttr(Attr.getRange(), S.Context));
+    return;
+  case AttributeList::AT_thiscall:
+    D->addAttr(::new (S.Context) ThisCallAttr(Attr.getRange(), S.Context));
+    return;
+  case AttributeList::AT_cdecl:
+    D->addAttr(::new (S.Context) CDeclAttr(Attr.getRange(), S.Context));
+    return;
+  case AttributeList::AT_pascal:
+    D->addAttr(::new (S.Context) PascalAttr(Attr.getRange(), S.Context));
+    return;
+  case AttributeList::AT_pcs: {
+    Expr *Arg = Attr.getArg(0);
+    StringLiteral *Str = dyn_cast<StringLiteral>(Arg);
+    if (!Str || !Str->isAscii()) {
+      S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_string)
+        << "pcs" << 1;
+      Attr.setInvalid();
+      return;
+    }
+
+    StringRef StrRef = Str->getString();
+    PcsAttr::PCSType PCS;
+    if (StrRef == "aapcs")
+      PCS = PcsAttr::AAPCS;
+    else if (StrRef == "aapcs-vfp")
+      PCS = PcsAttr::AAPCS_VFP;
+    else {
+      S.Diag(Attr.getLoc(), diag::err_invalid_pcs);
+      Attr.setInvalid();
+      return;
+    }
+
+    D->addAttr(::new (S.Context) PcsAttr(Attr.getRange(), S.Context, PCS));
+  }
+  default:
+    llvm_unreachable("unexpected attribute kind");
+  }
+}
+
+static void handleOpenCLKernelAttr(Sema &S, Decl *D, const AttributeList &Attr){
+  assert(!Attr.isInvalid());
+  D->addAttr(::new (S.Context) OpenCLKernelAttr(Attr.getRange(), S.Context));
+}
+
+bool Sema::CheckCallingConvAttr(const AttributeList &attr, CallingConv &CC) {
+  if (attr.isInvalid())
+    return true;
+
+  if ((attr.getNumArgs() != 0 &&
+      !(attr.getKind() == AttributeList::AT_pcs && attr.getNumArgs() == 1)) ||
+      attr.getParameterName()) {
+    Diag(attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
+    attr.setInvalid();
+    return true;
+  }
+
+  // TODO: diagnose uses of these conventions on the wrong target. Or, better
+  // move to TargetAttributesSema one day.
+  switch (attr.getKind()) {
+  case AttributeList::AT_cdecl: CC = CC_C; break;
+  case AttributeList::AT_fastcall: CC = CC_X86FastCall; break;
+  case AttributeList::AT_stdcall: CC = CC_X86StdCall; break;
+  case AttributeList::AT_thiscall: CC = CC_X86ThisCall; break;
+  case AttributeList::AT_pascal: CC = CC_X86Pascal; break;
+  case AttributeList::AT_pcs: {
+    Expr *Arg = attr.getArg(0);
+    StringLiteral *Str = dyn_cast<StringLiteral>(Arg);
+    if (!Str || !Str->isAscii()) {
+      Diag(attr.getLoc(), diag::err_attribute_argument_n_not_string)
+        << "pcs" << 1;
+      attr.setInvalid();
+      return true;
+    }
+
+    StringRef StrRef = Str->getString();
+    if (StrRef == "aapcs") {
+      CC = CC_AAPCS;
+      break;
+    } else if (StrRef == "aapcs-vfp") {
+      CC = CC_AAPCS_VFP;
+      break;
+    }
+    // FALLS THROUGH
+  }
+  default: llvm_unreachable("unexpected attribute kind");
+  }
+
+  return false;
+}
+
+static void handleRegparmAttr(Sema &S, Decl *D, const AttributeList &Attr) {
+  if (hasDeclarator(D)) return;
+
+  unsigned numParams;
+  if (S.CheckRegparmAttr(Attr, numParams))
+    return;
+
+  if (!isa<ObjCMethodDecl>(D)) {
+    S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
+      << Attr.getName() << ExpectedFunctionOrMethod;
+    return;
+  }
+
+  D->addAttr(::new (S.Context) RegparmAttr(Attr.getRange(), S.Context, numParams));
+}
+
+/// Checks a regparm attribute, returning true if it is ill-formed and
+/// otherwise setting numParams to the appropriate value.
+bool Sema::CheckRegparmAttr(const AttributeList &Attr, unsigned &numParams) {
+  if (Attr.isInvalid())
+    return true;
+
+  if (Attr.getNumArgs() != 1) {
+    Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
+    Attr.setInvalid();
+    return true;
+  }
+
+  Expr *NumParamsExpr = Attr.getArg(0);
+  llvm::APSInt NumParams(32);
+  if (NumParamsExpr->isTypeDependent() || NumParamsExpr->isValueDependent() ||
+      !NumParamsExpr->isIntegerConstantExpr(NumParams, Context)) {
+    Diag(Attr.getLoc(), diag::err_attribute_argument_not_int)
+      << "regparm" << NumParamsExpr->getSourceRange();
+    Attr.setInvalid();
+    return true;
+  }
+
+  if (Context.getTargetInfo().getRegParmMax() == 0) {
+    Diag(Attr.getLoc(), diag::err_attribute_regparm_wrong_platform)
+      << NumParamsExpr->getSourceRange();
+    Attr.setInvalid();
+    return true;
+  }
+
+  numParams = NumParams.getZExtValue();
+  if (numParams > Context.getTargetInfo().getRegParmMax()) {
+    Diag(Attr.getLoc(), diag::err_attribute_regparm_invalid_number)
+      << Context.getTargetInfo().getRegParmMax() << NumParamsExpr->getSourceRange();
+    Attr.setInvalid();
+    return true;
+  }
+
+  return false;
+}
+
+static void handleLaunchBoundsAttr(Sema &S, Decl *D, const AttributeList &Attr){
+  if (S.LangOpts.CUDA) {
+    // check the attribute arguments.
+    if (Attr.getNumArgs() != 1 && Attr.getNumArgs() != 2) {
+      // FIXME: 0 is not okay.
+      S.Diag(Attr.getLoc(), diag::err_attribute_too_many_arguments) << 2;
+      return;
+    }
+
+    if (!isFunctionOrMethod(D)) {
+      S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
+        << Attr.getName() << ExpectedFunctionOrMethod;
+      return;
+    }
+
+    Expr *MaxThreadsExpr = Attr.getArg(0);
+    llvm::APSInt MaxThreads(32);
+    if (MaxThreadsExpr->isTypeDependent() ||
+        MaxThreadsExpr->isValueDependent() ||
+        !MaxThreadsExpr->isIntegerConstantExpr(MaxThreads, S.Context)) {
+      S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_int)
+        << "launch_bounds" << 1 << MaxThreadsExpr->getSourceRange();
+      return;
+    }
+
+    llvm::APSInt MinBlocks(32);
+    if (Attr.getNumArgs() > 1) {
+      Expr *MinBlocksExpr = Attr.getArg(1);
+      if (MinBlocksExpr->isTypeDependent() ||
+          MinBlocksExpr->isValueDependent() ||
+          !MinBlocksExpr->isIntegerConstantExpr(MinBlocks, S.Context)) {
+        S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_int)
+          << "launch_bounds" << 2 << MinBlocksExpr->getSourceRange();
+        return;
+      }
+    }
+
+    D->addAttr(::new (S.Context) CUDALaunchBoundsAttr(Attr.getRange(), S.Context,
+                                                      MaxThreads.getZExtValue(),
+                                                     MinBlocks.getZExtValue()));
+  } else {
+    S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "launch_bounds";
+  }
+}
+
+//===----------------------------------------------------------------------===//
+// Checker-specific attribute handlers.
+//===----------------------------------------------------------------------===//
+
+static bool isValidSubjectOfNSAttribute(Sema &S, QualType type) {
+  return type->isDependentType() || 
+         type->isObjCObjectPointerType() || 
+         S.Context.isObjCNSObjectType(type);
+}
+static bool isValidSubjectOfCFAttribute(Sema &S, QualType type) {
+  return type->isDependentType() || 
+         type->isPointerType() || 
+         isValidSubjectOfNSAttribute(S, type);
+}
+
+static void handleNSConsumedAttr(Sema &S, Decl *D, const AttributeList &Attr) {
+  ParmVarDecl *param = dyn_cast<ParmVarDecl>(D);
+  if (!param) {
+    S.Diag(D->getLocStart(), diag::warn_attribute_wrong_decl_type)
+      << Attr.getRange() << Attr.getName() << ExpectedParameter;
+    return;
+  }
+
+  bool typeOK, cf;
+  if (Attr.getKind() == AttributeList::AT_ns_consumed) {
+    typeOK = isValidSubjectOfNSAttribute(S, param->getType());
+    cf = false;
+  } else {
+    typeOK = isValidSubjectOfCFAttribute(S, param->getType());
+    cf = true;
+  }
+
+  if (!typeOK) {
+    S.Diag(D->getLocStart(), diag::warn_ns_attribute_wrong_parameter_type)
+      << Attr.getRange() << Attr.getName() << cf;
+    return;
+  }
+
+  if (cf)
+    param->addAttr(::new (S.Context) CFConsumedAttr(Attr.getRange(), S.Context));
+  else
+    param->addAttr(::new (S.Context) NSConsumedAttr(Attr.getRange(), S.Context));
+}
+
+static void handleNSConsumesSelfAttr(Sema &S, Decl *D,
+                                     const AttributeList &Attr) {
+  if (!isa<ObjCMethodDecl>(D)) {
+    S.Diag(D->getLocStart(), diag::warn_attribute_wrong_decl_type)
+      << Attr.getRange() << Attr.getName() << ExpectedMethod;
+    return;
+  }
+
+  D->addAttr(::new (S.Context) NSConsumesSelfAttr(Attr.getRange(), S.Context));
+}
+
+static void handleNSReturnsRetainedAttr(Sema &S, Decl *D,
+                                        const AttributeList &Attr) {
+
+  QualType returnType;
+
+  if (ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D))
+    returnType = MD->getResultType();
+  else if (ObjCPropertyDecl *PD = dyn_cast<ObjCPropertyDecl>(D))
+    returnType = PD->getType();
+  else if (S.getLangOpts().ObjCAutoRefCount && hasDeclarator(D) &&
+           (Attr.getKind() == AttributeList::AT_ns_returns_retained))
+    return; // ignore: was handled as a type attribute
+  else if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
+    returnType = FD->getResultType();
+  else {
+    S.Diag(D->getLocStart(), diag::warn_attribute_wrong_decl_type)
+        << Attr.getRange() << Attr.getName()
+        << ExpectedFunctionOrMethod;
+    return;
+  }
+
+  bool typeOK;
+  bool cf;
+  switch (Attr.getKind()) {
+  default: llvm_unreachable("invalid ownership attribute");
+  case AttributeList::AT_ns_returns_autoreleased:
+  case AttributeList::AT_ns_returns_retained:
+  case AttributeList::AT_ns_returns_not_retained:
+    typeOK = isValidSubjectOfNSAttribute(S, returnType);
+    cf = false;
+    break;
+
+  case AttributeList::AT_cf_returns_retained:
+  case AttributeList::AT_cf_returns_not_retained:
+    typeOK = isValidSubjectOfCFAttribute(S, returnType);
+    cf = true;
+    break;
+  }
+
+  if (!typeOK) {
+    S.Diag(D->getLocStart(), diag::warn_ns_attribute_wrong_return_type)
+      << Attr.getRange() << Attr.getName() << isa<ObjCMethodDecl>(D) << cf;
+    return;
+  }
+
+  switch (Attr.getKind()) {
+    default:
+      llvm_unreachable("invalid ownership attribute");
+    case AttributeList::AT_ns_returns_autoreleased:
+      D->addAttr(::new (S.Context) NSReturnsAutoreleasedAttr(Attr.getRange(),
+                                                             S.Context));
+      return;
+    case AttributeList::AT_cf_returns_not_retained:
+      D->addAttr(::new (S.Context) CFReturnsNotRetainedAttr(Attr.getRange(),
+                                                            S.Context));
+      return;
+    case AttributeList::AT_ns_returns_not_retained:
+      D->addAttr(::new (S.Context) NSReturnsNotRetainedAttr(Attr.getRange(),
+                                                            S.Context));
+      return;
+    case AttributeList::AT_cf_returns_retained:
+      D->addAttr(::new (S.Context) CFReturnsRetainedAttr(Attr.getRange(),
+                                                         S.Context));
+      return;
+    case AttributeList::AT_ns_returns_retained:
+      D->addAttr(::new (S.Context) NSReturnsRetainedAttr(Attr.getRange(),
+                                                         S.Context));
+      return;
+  };
+}
+
+static void handleObjCReturnsInnerPointerAttr(Sema &S, Decl *D,
+                                              const AttributeList &attr) {
+  SourceLocation loc = attr.getLoc();
+
+  ObjCMethodDecl *method = dyn_cast<ObjCMethodDecl>(D);
+
+  if (!isa<ObjCMethodDecl>(method)) {
+    S.Diag(method->getLocStart(), diag::err_attribute_wrong_decl_type)
+      << SourceRange(loc, loc) << attr.getName() << ExpectedMethod;
+    return;
+  }
+
+  // Check that the method returns a normal pointer.
+  QualType resultType = method->getResultType();
+    
+  if (!resultType->isReferenceType() &&
+      (!resultType->isPointerType() || resultType->isObjCRetainableType())) {
+    S.Diag(method->getLocStart(), diag::warn_ns_attribute_wrong_return_type)
+      << SourceRange(loc)
+      << attr.getName() << /*method*/ 1 << /*non-retainable pointer*/ 2;
+
+    // Drop the attribute.
+    return;
+  }
+
+  method->addAttr(
+    ::new (S.Context) ObjCReturnsInnerPointerAttr(attr.getRange(), S.Context));
+}
+
+/// Handle cf_audited_transfer and cf_unknown_transfer.
+static void handleCFTransferAttr(Sema &S, Decl *D, const AttributeList &A) {
+  if (!isa<FunctionDecl>(D)) {
+    S.Diag(D->getLocStart(), diag::err_attribute_wrong_decl_type)
+      << A.getRange() << A.getName() << ExpectedFunction;
+    return;
+  }
+
+  bool IsAudited = (A.getKind() == AttributeList::AT_cf_audited_transfer);
+
+  // Check whether there's a conflicting attribute already present.
+  Attr *Existing;
+  if (IsAudited) {
+    Existing = D->getAttr<CFUnknownTransferAttr>();
+  } else {
+    Existing = D->getAttr<CFAuditedTransferAttr>();
+  }
+  if (Existing) {
+    S.Diag(D->getLocStart(), diag::err_attributes_are_not_compatible)
+      << A.getName()
+      << (IsAudited ? "cf_unknown_transfer" : "cf_audited_transfer")
+      << A.getRange() << Existing->getRange();
+    return;
+  }
+
+  // All clear;  add the attribute.
+  if (IsAudited) {
+    D->addAttr(
+      ::new (S.Context) CFAuditedTransferAttr(A.getRange(), S.Context));
+  } else {
+    D->addAttr(
+      ::new (S.Context) CFUnknownTransferAttr(A.getRange(), S.Context));
+  }
+}
+
+static void handleNSBridgedAttr(Sema &S, Scope *Sc, Decl *D,
+                                const AttributeList &Attr) {
+  RecordDecl *RD = dyn_cast<RecordDecl>(D);
+  if (!RD || RD->isUnion()) {
+    S.Diag(D->getLocStart(), diag::err_attribute_wrong_decl_type)
+      << Attr.getRange() << Attr.getName() << ExpectedStruct;
+  }
+
+  IdentifierInfo *ParmName = Attr.getParameterName();
+
+  // In Objective-C, verify that the type names an Objective-C type.
+  // We don't want to check this outside of ObjC because people sometimes
+  // do crazy C declarations of Objective-C types.
+  if (ParmName && S.getLangOpts().ObjC1) {
+    // Check for an existing type with this name.
+    LookupResult R(S, DeclarationName(ParmName), Attr.getParameterLoc(),
+                   Sema::LookupOrdinaryName);
+    if (S.LookupName(R, Sc)) {
+      NamedDecl *Target = R.getFoundDecl();
+      if (Target && !isa<ObjCInterfaceDecl>(Target)) {
+        S.Diag(D->getLocStart(), diag::err_ns_bridged_not_interface);
+        S.Diag(Target->getLocStart(), diag::note_declared_at);
+      }
+    }
+  }
+
+  D->addAttr(::new (S.Context) NSBridgedAttr(Attr.getRange(), S.Context,
+                                             ParmName));
+}
+
+static void handleObjCOwnershipAttr(Sema &S, Decl *D,
+                                    const AttributeList &Attr) {
+  if (hasDeclarator(D)) return;
+
+  S.Diag(D->getLocStart(), diag::err_attribute_wrong_decl_type)
+    << Attr.getRange() << Attr.getName() << ExpectedVariable;
+}
+
+static void handleObjCPreciseLifetimeAttr(Sema &S, Decl *D,
+                                          const AttributeList &Attr) {
+  if (!isa<VarDecl>(D) && !isa<FieldDecl>(D)) {
+    S.Diag(D->getLocStart(), diag::err_attribute_wrong_decl_type)
+      << Attr.getRange() << Attr.getName() << ExpectedVariable;
+    return;
+  }
+
+  ValueDecl *vd = cast<ValueDecl>(D);
+  QualType type = vd->getType();
+
+  if (!type->isDependentType() &&
+      !type->isObjCLifetimeType()) {
+    S.Diag(Attr.getLoc(), diag::err_objc_precise_lifetime_bad_type)
+      << type;
+    return;
+  }
+
+  Qualifiers::ObjCLifetime lifetime = type.getObjCLifetime();
+
+  // If we have no lifetime yet, check the lifetime we're presumably
+  // going to infer.
+  if (lifetime == Qualifiers::OCL_None && !type->isDependentType())
+    lifetime = type->getObjCARCImplicitLifetime();
+
+  switch (lifetime) {
+  case Qualifiers::OCL_None:
+    assert(type->isDependentType() &&
+           "didn't infer lifetime for non-dependent type?");
+    break;
+
+  case Qualifiers::OCL_Weak:   // meaningful
+  case Qualifiers::OCL_Strong: // meaningful
+    break;
+
+  case Qualifiers::OCL_ExplicitNone:
+  case Qualifiers::OCL_Autoreleasing:
+    S.Diag(Attr.getLoc(), diag::warn_objc_precise_lifetime_meaningless)
+      << (lifetime == Qualifiers::OCL_Autoreleasing);
+    break;
+  }
+
+  D->addAttr(::new (S.Context)
+                 ObjCPreciseLifetimeAttr(Attr.getRange(), S.Context));
+}
+
+static bool isKnownDeclSpecAttr(const AttributeList &Attr) {
+  switch (Attr.getKind()) {
+  default:
+    return false;
+  case AttributeList::AT_dllimport:
+  case AttributeList::AT_dllexport:
+  case AttributeList::AT_uuid:
+  case AttributeList::AT_deprecated:
+  case AttributeList::AT_noreturn:
+  case AttributeList::AT_nothrow:
+  case AttributeList::AT_naked:
+  case AttributeList::AT_noinline:
+    return true;
+  }
+}
+
+//===----------------------------------------------------------------------===//
+// Microsoft specific attribute handlers.
+//===----------------------------------------------------------------------===//
+
+static void handleUuidAttr(Sema &S, Decl *D, const AttributeList &Attr) {
+  if (S.LangOpts.MicrosoftExt || S.LangOpts.Borland) {
+    // check the attribute arguments.
+    if (!checkAttributeNumArgs(S, Attr, 1))
+      return;
+
+    Expr *Arg = Attr.getArg(0);
+    StringLiteral *Str = dyn_cast<StringLiteral>(Arg);
+    if (!Str || !Str->isAscii()) {
+      S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_string)
+        << "uuid" << 1;
+      return;
+    }
+
+    StringRef StrRef = Str->getString();
+
+    bool IsCurly = StrRef.size() > 1 && StrRef.front() == '{' &&
+                   StrRef.back() == '}';
+
+    // Validate GUID length.
+    if (IsCurly && StrRef.size() != 38) {
+      S.Diag(Attr.getLoc(), diag::err_attribute_uuid_malformed_guid);
+      return;
+    }
+    if (!IsCurly && StrRef.size() != 36) {
+      S.Diag(Attr.getLoc(), diag::err_attribute_uuid_malformed_guid);
+      return;
+    }
+
+    // GUID format is "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX" or
+    // "{XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}"
+    StringRef::iterator I = StrRef.begin();
+    if (IsCurly) // Skip the optional '{'
+       ++I;
+
+    for (int i = 0; i < 36; ++i) {
+      if (i == 8 || i == 13 || i == 18 || i == 23) {
+        if (*I != '-') {
+          S.Diag(Attr.getLoc(), diag::err_attribute_uuid_malformed_guid);
+          return;
+        }
+      } else if (!isxdigit(*I)) {
+        S.Diag(Attr.getLoc(), diag::err_attribute_uuid_malformed_guid);
+        return;
+      }
+      I++;
+    }
+
+    D->addAttr(::new (S.Context) UuidAttr(Attr.getRange(), S.Context,
+                                          Str->getString()));
+  } else
+    S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "uuid";
+}
+
+//===----------------------------------------------------------------------===//
+// Top Level Sema Entry Points
+//===----------------------------------------------------------------------===//
+
+static void ProcessNonInheritableDeclAttr(Sema &S, Scope *scope, Decl *D,
+                                          const AttributeList &Attr) {
+  switch (Attr.getKind()) {
+  case AttributeList::AT_device:      handleDeviceAttr      (S, D, Attr); break;
+  case AttributeList::AT_host:        handleHostAttr        (S, D, Attr); break;
+  case AttributeList::AT_overloadable:handleOverloadableAttr(S, D, Attr); break;
+  default:
+    break;
+  }
+}
+
+static void ProcessInheritableDeclAttr(Sema &S, Scope *scope, Decl *D,
+                                       const AttributeList &Attr) {
+  switch (Attr.getKind()) {
+    case AttributeList::AT_ibaction:            handleIBAction(S, D, Attr); break;
+    case AttributeList::AT_iboutlet:          handleIBOutlet(S, D, Attr); break;
+    case AttributeList::AT_iboutletcollection:
+      handleIBOutletCollection(S, D, Attr); break;
+  case AttributeList::AT_address_space:
+  case AttributeList::AT_opencl_image_access:
+  case AttributeList::AT_objc_gc:
+  case AttributeList::AT_vector_size:
+  case AttributeList::AT_neon_vector_type:
+  case AttributeList::AT_neon_polyvector_type:
+    // Ignore these, these are type attributes, handled by
+    // ProcessTypeAttributes.
+    break;
+  case AttributeList::AT_device:
+  case AttributeList::AT_host:
+  case AttributeList::AT_overloadable:
+    // Ignore, this is a non-inheritable attribute, handled
+    // by ProcessNonInheritableDeclAttr.
+    break;
+  case AttributeList::AT_alias:       handleAliasAttr       (S, D, Attr); break;
+  case AttributeList::AT_aligned:     handleAlignedAttr     (S, D, Attr); break;
+  case AttributeList::AT_always_inline:
+    handleAlwaysInlineAttr  (S, D, Attr); break;
+  case AttributeList::AT_analyzer_noreturn:
+    handleAnalyzerNoReturnAttr  (S, D, Attr); break;
+  case AttributeList::AT_annotate:    handleAnnotateAttr    (S, D, Attr); break;
+  case AttributeList::AT_availability:handleAvailabilityAttr(S, D, Attr); break;
+  case AttributeList::AT_carries_dependency:
+                                      handleDependencyAttr  (S, D, Attr); break;
+  case AttributeList::AT_common:      handleCommonAttr      (S, D, Attr); break;
+  case AttributeList::AT_constant:    handleConstantAttr    (S, D, Attr); break;
+  case AttributeList::AT_constructor: handleConstructorAttr (S, D, Attr); break;
+  case AttributeList::AT_deprecated:  handleDeprecatedAttr  (S, D, Attr); break;
+  case AttributeList::AT_destructor:  handleDestructorAttr  (S, D, Attr); break;
+  case AttributeList::AT_ext_vector_type:
+    handleExtVectorTypeAttr(S, scope, D, Attr);
+    break;
+  case AttributeList::AT_format:      handleFormatAttr      (S, D, Attr); break;
+  case AttributeList::AT_format_arg:  handleFormatArgAttr   (S, D, Attr); break;
+  case AttributeList::AT_global:      handleGlobalAttr      (S, D, Attr); break;
+  case AttributeList::AT_gnu_inline:  handleGNUInlineAttr   (S, D, Attr); break;
+  case AttributeList::AT_launch_bounds:
+    handleLaunchBoundsAttr(S, D, Attr);
+    break;
+  case AttributeList::AT_mode:        handleModeAttr        (S, D, Attr); break;
+  case AttributeList::AT_malloc:      handleMallocAttr      (S, D, Attr); break;
+  case AttributeList::AT_may_alias:   handleMayAliasAttr    (S, D, Attr); break;
+  case AttributeList::AT_nocommon:    handleNoCommonAttr    (S, D, Attr); break;
+  case AttributeList::AT_nonnull:     handleNonNullAttr     (S, D, Attr); break;
+  case AttributeList::AT_ownership_returns:
+  case AttributeList::AT_ownership_takes:
+  case AttributeList::AT_ownership_holds:
+      handleOwnershipAttr     (S, D, Attr); break;
+  case AttributeList::AT_naked:       handleNakedAttr       (S, D, Attr); break;
+  case AttributeList::AT_noreturn:    handleNoReturnAttr    (S, D, Attr); break;
+  case AttributeList::AT_nothrow:     handleNothrowAttr     (S, D, Attr); break;
+  case AttributeList::AT_shared:      handleSharedAttr      (S, D, Attr); break;
+  case AttributeList::AT_vecreturn:   handleVecReturnAttr   (S, D, Attr); break;
+
+  case AttributeList::AT_objc_ownership:
+    handleObjCOwnershipAttr(S, D, Attr); break;
+  case AttributeList::AT_objc_precise_lifetime:
+    handleObjCPreciseLifetimeAttr(S, D, Attr); break;
+
+  case AttributeList::AT_objc_returns_inner_pointer:
+    handleObjCReturnsInnerPointerAttr(S, D, Attr); break;
+
+  case AttributeList::AT_ns_bridged:
+    handleNSBridgedAttr(S, scope, D, Attr); break;
+
+  case AttributeList::AT_cf_audited_transfer:
+  case AttributeList::AT_cf_unknown_transfer:
+    handleCFTransferAttr(S, D, Attr); break;
+
+  // Checker-specific.
+  case AttributeList::AT_cf_consumed:
+  case AttributeList::AT_ns_consumed: handleNSConsumedAttr  (S, D, Attr); break;
+  case AttributeList::AT_ns_consumes_self:
+    handleNSConsumesSelfAttr(S, D, Attr); break;
+
+  case AttributeList::AT_ns_returns_autoreleased:
+  case AttributeList::AT_ns_returns_not_retained:
+  case AttributeList::AT_cf_returns_not_retained:
+  case AttributeList::AT_ns_returns_retained:
+  case AttributeList::AT_cf_returns_retained:
+    handleNSReturnsRetainedAttr(S, D, Attr); break;
+
+  case AttributeList::AT_reqd_work_group_size:
+    handleReqdWorkGroupSize(S, D, Attr); break;
+
+  case AttributeList::AT_init_priority: 
+      handleInitPriorityAttr(S, D, Attr); break;
+      
+  case AttributeList::AT_packed:      handlePackedAttr      (S, D, Attr); break;
+  case AttributeList::AT_ms_struct:    handleMsStructAttr    (S, D, Attr); break;
+  case AttributeList::AT_section:     handleSectionAttr     (S, D, Attr); break;
+  case AttributeList::AT_unavailable: handleUnavailableAttr (S, D, Attr); break;
+  case AttributeList::AT_objc_arc_weak_reference_unavailable: 
+    handleArcWeakrefUnavailableAttr (S, D, Attr); 
+    break;
+  case AttributeList::AT_objc_root_class:
+    handleObjCRootClassAttr(S, D, Attr);
+    break;
+  case AttributeList::AT_objc_requires_property_definitions: 
+    handleObjCRequiresPropertyDefsAttr (S, D, Attr); 
+    break;
+  case AttributeList::AT_unused:      handleUnusedAttr      (S, D, Attr); break;
+  case AttributeList::AT_returns_twice:
+    handleReturnsTwiceAttr(S, D, Attr);
+    break;
+  case AttributeList::AT_used:        handleUsedAttr        (S, D, Attr); break;
+  case AttributeList::AT_visibility:  handleVisibilityAttr  (S, D, Attr); break;
+  case AttributeList::AT_warn_unused_result: handleWarnUnusedResult(S, D, Attr);
+    break;
+  case AttributeList::AT_weak:        handleWeakAttr        (S, D, Attr); break;
+  case AttributeList::AT_weakref:     handleWeakRefAttr     (S, D, Attr); break;
+  case AttributeList::AT_weak_import: handleWeakImportAttr  (S, D, Attr); break;
+  case AttributeList::AT_transparent_union:
+    handleTransparentUnionAttr(S, D, Attr);
+    break;
+  case AttributeList::AT_objc_exception:
+    handleObjCExceptionAttr(S, D, Attr);
+    break;
+  case AttributeList::AT_objc_method_family:
+    handleObjCMethodFamilyAttr(S, D, Attr);
+    break;
+  case AttributeList::AT_NSObject:    handleObjCNSObject    (S, D, Attr); break;
+  case AttributeList::AT_blocks:      handleBlocksAttr      (S, D, Attr); break;
+  case AttributeList::AT_sentinel:    handleSentinelAttr    (S, D, Attr); break;
+  case AttributeList::AT_const:       handleConstAttr       (S, D, Attr); break;
+  case AttributeList::AT_pure:        handlePureAttr        (S, D, Attr); break;
+  case AttributeList::AT_cleanup:     handleCleanupAttr     (S, D, Attr); break;
+  case AttributeList::AT_nodebug:     handleNoDebugAttr     (S, D, Attr); break;
+  case AttributeList::AT_noinline:    handleNoInlineAttr    (S, D, Attr); break;
+  case AttributeList::AT_regparm:     handleRegparmAttr     (S, D, Attr); break;
+  case AttributeList::IgnoredAttribute:
+    // Just ignore
+    break;
+  case AttributeList::AT_no_instrument_function:  // Interacts with -pg.
+    handleNoInstrumentFunctionAttr(S, D, Attr);
+    break;
+  case AttributeList::AT_stdcall:
+  case AttributeList::AT_cdecl:
+  case AttributeList::AT_fastcall:
+  case AttributeList::AT_thiscall:
+  case AttributeList::AT_pascal:
+  case AttributeList::AT_pcs:
+    handleCallConvAttr(S, D, Attr);
+    break;
+  case AttributeList::AT_opencl_kernel_function:
+    handleOpenCLKernelAttr(S, D, Attr);
+    break;
+  case AttributeList::AT_uuid:
+    handleUuidAttr(S, D, Attr);
+    break;
+
+  // Thread safety attributes:
+  case AttributeList::AT_guarded_var:
+    handleGuardedVarAttr(S, D, Attr);
+    break;
+  case AttributeList::AT_pt_guarded_var:
+    handleGuardedVarAttr(S, D, Attr, /*pointer = */true);
+    break;
+  case AttributeList::AT_scoped_lockable:
+    handleLockableAttr(S, D, Attr, /*scoped = */true);
+    break;
+  case AttributeList::AT_no_address_safety_analysis:
+    handleNoAddressSafetyAttr(S, D, Attr);
+    break;
+  case AttributeList::AT_no_thread_safety_analysis:
+    handleNoThreadSafetyAttr(S, D, Attr);
+    break;
+  case AttributeList::AT_lockable:
+    handleLockableAttr(S, D, Attr);
+    break;
+  case AttributeList::AT_guarded_by:
+    handleGuardedByAttr(S, D, Attr);
+    break;
+  case AttributeList::AT_pt_guarded_by:
+    handleGuardedByAttr(S, D, Attr, /*pointer = */true);
+    break;
+  case AttributeList::AT_exclusive_lock_function:
+    handleLockFunAttr(S, D, Attr, /*exclusive = */true);
+    break;
+  case AttributeList::AT_exclusive_locks_required:
+    handleLocksRequiredAttr(S, D, Attr, /*exclusive = */true);
+    break;
+  case AttributeList::AT_exclusive_trylock_function:
+    handleTrylockFunAttr(S, D, Attr, /*exclusive = */true);
+    break;
+  case AttributeList::AT_lock_returned:
+    handleLockReturnedAttr(S, D, Attr);
+    break;
+  case AttributeList::AT_locks_excluded:
+    handleLocksExcludedAttr(S, D, Attr);
+    break;
+  case AttributeList::AT_shared_lock_function:
+    handleLockFunAttr(S, D, Attr);
+    break;
+  case AttributeList::AT_shared_locks_required:
+    handleLocksRequiredAttr(S, D, Attr);
+    break;
+  case AttributeList::AT_shared_trylock_function:
+    handleTrylockFunAttr(S, D, Attr);
+    break;
+  case AttributeList::AT_unlock_function:
+    handleUnlockFunAttr(S, D, Attr);
+    break;
+  case AttributeList::AT_acquired_before:
+    handleAcquireOrderAttr(S, D, Attr, /*before = */true);
+    break;
+  case AttributeList::AT_acquired_after:
+    handleAcquireOrderAttr(S, D, Attr, /*before = */false);
+    break;
+
+  default:
+    // Ask target about the attribute.
+    const TargetAttributesSema &TargetAttrs = S.getTargetAttributesSema();
+    if (!TargetAttrs.ProcessDeclAttribute(scope, D, Attr, S))
+      S.Diag(Attr.getLoc(), diag::warn_unknown_attribute_ignored)
+        << Attr.getName();
+    break;
+  }
+}
+
+/// ProcessDeclAttribute - Apply the specific attribute to the specified decl if
+/// the attribute applies to decls.  If the attribute is a type attribute, just
+/// silently ignore it if a GNU attribute. FIXME: Applying a C++0x attribute to
+/// the wrong thing is illegal (C++0x [dcl.attr.grammar]/4).
+static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D,
+                                 const AttributeList &Attr,
+                                 bool NonInheritable, bool Inheritable) {
+  if (Attr.isInvalid())
+    return;
+
+  if (Attr.isDeclspecAttribute() && !isKnownDeclSpecAttr(Attr))
+    // FIXME: Try to deal with other __declspec attributes!
+    return;
+
+  if (NonInheritable)
+    ProcessNonInheritableDeclAttr(S, scope, D, Attr);
+
+  if (Inheritable)
+    ProcessInheritableDeclAttr(S, scope, D, Attr);
+}
+
+/// ProcessDeclAttributeList - Apply all the decl attributes in the specified
+/// attribute list to the specified decl, ignoring any type attributes.
+void Sema::ProcessDeclAttributeList(Scope *S, Decl *D,
+                                    const AttributeList *AttrList,
+                                    bool NonInheritable, bool Inheritable) {
+  for (const AttributeList* l = AttrList; l; l = l->getNext()) {
+    ProcessDeclAttribute(*this, S, D, *l, NonInheritable, Inheritable);
+  }
+
+  // GCC accepts
+  // static int a9 __attribute__((weakref));
+  // but that looks really pointless. We reject it.
+  if (Inheritable && D->hasAttr<WeakRefAttr>() && !D->hasAttr<AliasAttr>()) {
+    Diag(AttrList->getLoc(), diag::err_attribute_weakref_without_alias) <<
+    dyn_cast<NamedDecl>(D)->getNameAsString();
+    return;
+  }
+}
+
+// Annotation attributes are the only attributes allowed after an access
+// specifier.
+bool Sema::ProcessAccessDeclAttributeList(AccessSpecDecl *ASDecl,
+                                          const AttributeList *AttrList) {
+  for (const AttributeList* l = AttrList; l; l = l->getNext()) {
+    if (l->getKind() == AttributeList::AT_annotate) {
+      handleAnnotateAttr(*this, ASDecl, *l);
+    } else {
+      Diag(l->getLoc(), diag::err_only_annotate_after_access_spec);
+      return true;
+    }
+  }
+
+  return false;
+}
+
+/// checkUnusedDeclAttributes - Check a list of attributes to see if it
+/// contains any decl attributes that we should warn about.
+static void checkUnusedDeclAttributes(Sema &S, const AttributeList *A) {
+  for ( ; A; A = A->getNext()) {
+    // Only warn if the attribute is an unignored, non-type attribute.
+    if (A->isUsedAsTypeAttr()) continue;
+    if (A->getKind() == AttributeList::IgnoredAttribute) continue;
+
+    if (A->getKind() == AttributeList::UnknownAttribute) {
+      S.Diag(A->getLoc(), diag::warn_unknown_attribute_ignored)
+        << A->getName() << A->getRange();
+    } else {
+      S.Diag(A->getLoc(), diag::warn_attribute_not_on_decl)
+        << A->getName() << A->getRange();
+    }
+  }
+}
+
+/// checkUnusedDeclAttributes - Given a declarator which is not being
+/// used to build a declaration, complain about any decl attributes
+/// which might be lying around on it.
+void Sema::checkUnusedDeclAttributes(Declarator &D) {
+  ::checkUnusedDeclAttributes(*this, D.getDeclSpec().getAttributes().getList());
+  ::checkUnusedDeclAttributes(*this, D.getAttributes());
+  for (unsigned i = 0, e = D.getNumTypeObjects(); i != e; ++i)
+    ::checkUnusedDeclAttributes(*this, D.getTypeObject(i).getAttrs());
+}
+
+/// DeclClonePragmaWeak - clone existing decl (maybe definition),
+/// #pragma weak needs a non-definition decl and source may not have one
+NamedDecl * Sema::DeclClonePragmaWeak(NamedDecl *ND, IdentifierInfo *II,
+                                      SourceLocation Loc) {
+  assert(isa<FunctionDecl>(ND) || isa<VarDecl>(ND));
+  NamedDecl *NewD = 0;
+  if (FunctionDecl *FD = dyn_cast<FunctionDecl>(ND)) {
+    FunctionDecl *NewFD;
+    // FIXME: Missing call to CheckFunctionDeclaration().
+    // FIXME: Mangling?
+    // FIXME: Is the qualifier info correct?
+    // FIXME: Is the DeclContext correct?
+    NewFD = FunctionDecl::Create(FD->getASTContext(), FD->getDeclContext(),
+                                 Loc, Loc, DeclarationName(II),
+                                 FD->getType(), FD->getTypeSourceInfo(),
+                                 SC_None, SC_None,
+                                 false/*isInlineSpecified*/,
+                                 FD->hasPrototype(),
+                                 false/*isConstexprSpecified*/);
+    NewD = NewFD;
+
+    if (FD->getQualifier())
+      NewFD->setQualifierInfo(FD->getQualifierLoc());
+
+    // Fake up parameter variables; they are declared as if this were
+    // a typedef.
+    QualType FDTy = FD->getType();
+    if (const FunctionProtoType *FT = FDTy->getAs<FunctionProtoType>()) {
+      SmallVector<ParmVarDecl*, 16> Params;
+      for (FunctionProtoType::arg_type_iterator AI = FT->arg_type_begin(),
+           AE = FT->arg_type_end(); AI != AE; ++AI) {
+        ParmVarDecl *Param = BuildParmVarDeclForTypedef(NewFD, Loc, *AI);
+        Param->setScopeInfo(0, Params.size());
+        Params.push_back(Param);
+      }
+      NewFD->setParams(Params);
+    }
+  } else if (VarDecl *VD = dyn_cast<VarDecl>(ND)) {
+    NewD = VarDecl::Create(VD->getASTContext(), VD->getDeclContext(),
+                           VD->getInnerLocStart(), VD->getLocation(), II,
+                           VD->getType(), VD->getTypeSourceInfo(),
+                           VD->getStorageClass(),
+                           VD->getStorageClassAsWritten());
+    if (VD->getQualifier()) {
+      VarDecl *NewVD = cast<VarDecl>(NewD);
+      NewVD->setQualifierInfo(VD->getQualifierLoc());
+    }
+  }
+  return NewD;
+}
+
+/// DeclApplyPragmaWeak - A declaration (maybe definition) needs #pragma weak
+/// applied to it, possibly with an alias.
+void Sema::DeclApplyPragmaWeak(Scope *S, NamedDecl *ND, WeakInfo &W) {
+  if (W.getUsed()) return; // only do this once
+  W.setUsed(true);
+  if (W.getAlias()) { // clone decl, impersonate __attribute(weak,alias(...))
+    IdentifierInfo *NDId = ND->getIdentifier();
+    NamedDecl *NewD = DeclClonePragmaWeak(ND, W.getAlias(), W.getLocation());
+    NewD->addAttr(::new (Context) AliasAttr(W.getLocation(), Context,
+                                            NDId->getName()));
+    NewD->addAttr(::new (Context) WeakAttr(W.getLocation(), Context));
+    WeakTopLevelDecl.push_back(NewD);
+    // FIXME: "hideous" code from Sema::LazilyCreateBuiltin
+    // to insert Decl at TU scope, sorry.
+    DeclContext *SavedContext = CurContext;
+    CurContext = Context.getTranslationUnitDecl();
+    PushOnScopeChains(NewD, S);
+    CurContext = SavedContext;
+  } else { // just add weak to existing
+    ND->addAttr(::new (Context) WeakAttr(W.getLocation(), Context));
+  }
+}
+
+/// ProcessDeclAttributes - Given a declarator (PD) with attributes indicated in
+/// it, apply them to D.  This is a bit tricky because PD can have attributes
+/// specified in many different places, and we need to find and apply them all.
+void Sema::ProcessDeclAttributes(Scope *S, Decl *D, const Declarator &PD,
+                                 bool NonInheritable, bool Inheritable) {
+  // It's valid to "forward-declare" #pragma weak, in which case we
+  // have to do this.
+  if (Inheritable) {
+    LoadExternalWeakUndeclaredIdentifiers();
+    if (!WeakUndeclaredIdentifiers.empty()) {
+      if (NamedDecl *ND = dyn_cast<NamedDecl>(D)) {
+        if (IdentifierInfo *Id = ND->getIdentifier()) {
+          llvm::DenseMap<IdentifierInfo*,WeakInfo>::iterator I
+            = WeakUndeclaredIdentifiers.find(Id);
+          if (I != WeakUndeclaredIdentifiers.end() && ND->hasLinkage()) {
+            WeakInfo W = I->second;
+            DeclApplyPragmaWeak(S, ND, W);
+            WeakUndeclaredIdentifiers[Id] = W;
+          }
+        }
+      }
+    }
+  }
+
+  // Apply decl attributes from the DeclSpec if present.
+  if (const AttributeList *Attrs = PD.getDeclSpec().getAttributes().getList())
+    ProcessDeclAttributeList(S, D, Attrs, NonInheritable, Inheritable);
+
+  // Walk the declarator structure, applying decl attributes that were in a type
+  // position to the decl itself.  This handles cases like:
+  //   int *__attr__(x)** D;
+  // when X is a decl attribute.
+  for (unsigned i = 0, e = PD.getNumTypeObjects(); i != e; ++i)
+    if (const AttributeList *Attrs = PD.getTypeObject(i).getAttrs())
+      ProcessDeclAttributeList(S, D, Attrs, NonInheritable, Inheritable);
+
+  // Finally, apply any attributes on the decl itself.
+  if (const AttributeList *Attrs = PD.getAttributes())
+    ProcessDeclAttributeList(S, D, Attrs, NonInheritable, Inheritable);
+}
+
+/// Is the given declaration allowed to use a forbidden type?
+static bool isForbiddenTypeAllowed(Sema &S, Decl *decl) {
+  // Private ivars are always okay.  Unfortunately, people don't
+  // always properly make their ivars private, even in system headers.
+  // Plus we need to make fields okay, too.
+  // Function declarations in sys headers will be marked unavailable.
+  if (!isa<FieldDecl>(decl) && !isa<ObjCPropertyDecl>(decl) &&
+      !isa<FunctionDecl>(decl))
+    return false;
+
+  // Require it to be declared in a system header.
+  return S.Context.getSourceManager().isInSystemHeader(decl->getLocation());
+}
+
+/// Handle a delayed forbidden-type diagnostic.
+static void handleDelayedForbiddenType(Sema &S, DelayedDiagnostic &diag,
+                                       Decl *decl) {
+  if (decl && isForbiddenTypeAllowed(S, decl)) {
+    decl->addAttr(new (S.Context) UnavailableAttr(diag.Loc, S.Context,
+                        "this system declaration uses an unsupported type"));
+    return;
+  }
+  if (S.getLangOpts().ObjCAutoRefCount)
+    if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(decl)) {
+      // FIXME. we may want to supress diagnostics for all
+      // kind of forbidden type messages on unavailable functions. 
+      if (FD->hasAttr<UnavailableAttr>() &&
+          diag.getForbiddenTypeDiagnostic() == 
+          diag::err_arc_array_param_no_ownership) {
+        diag.Triggered = true;
+        return;
+      }
+    }
+
+  S.Diag(diag.Loc, diag.getForbiddenTypeDiagnostic())
+    << diag.getForbiddenTypeOperand() << diag.getForbiddenTypeArgument();
+  diag.Triggered = true;
+}
+
+// This duplicates a vector push_back but hides the need to know the
+// size of the type.
+void Sema::DelayedDiagnostics::add(const DelayedDiagnostic &diag) {
+  assert(StackSize <= StackCapacity);
+
+  // Grow the stack if necessary.
+  if (StackSize == StackCapacity) {
+    unsigned newCapacity = 2 * StackCapacity + 2;
+    char *newBuffer = new char[newCapacity * sizeof(DelayedDiagnostic)];
+    const char *oldBuffer = (const char*) Stack;
+
+    if (StackCapacity)
+      memcpy(newBuffer, oldBuffer, StackCapacity * sizeof(DelayedDiagnostic));
+    
+    delete[] oldBuffer;
+    Stack = reinterpret_cast<sema::DelayedDiagnostic*>(newBuffer);
+    StackCapacity = newCapacity;
+  }
+
+  assert(StackSize < StackCapacity);
+  new (&Stack[StackSize++]) DelayedDiagnostic(diag);
+}
+
+void Sema::DelayedDiagnostics::popParsingDecl(Sema &S, ParsingDeclState state,
+                                              Decl *decl) {
+  DelayedDiagnostics &DD = S.DelayedDiagnostics;
+
+  // Check the invariants.
+  assert(DD.StackSize >= state.SavedStackSize);
+  assert(state.SavedStackSize >= DD.ActiveStackBase);
+  assert(DD.ParsingDepth > 0);
+
+  // Drop the parsing depth.
+  DD.ParsingDepth--;
+
+  // If there are no active diagnostics, we're done.
+  if (DD.StackSize == DD.ActiveStackBase)
+    return;
+
+  // We only want to actually emit delayed diagnostics when we
+  // successfully parsed a decl.
+  if (decl) {
+    // We emit all the active diagnostics, not just those starting
+    // from the saved state.  The idea is this:  we get one push for a
+    // decl spec and another for each declarator;  in a decl group like:
+    //   deprecated_typedef foo, *bar, baz();
+    // only the declarator pops will be passed decls.  This is correct;
+    // we really do need to consider delayed diagnostics from the decl spec
+    // for each of the different declarations.
+    for (unsigned i = DD.ActiveStackBase, e = DD.StackSize; i != e; ++i) {
+      DelayedDiagnostic &diag = DD.Stack[i];
+      if (diag.Triggered)
+        continue;
+
+      switch (diag.Kind) {
+      case DelayedDiagnostic::Deprecation:
+        // Don't bother giving deprecation diagnostics if the decl is invalid.
+        if (!decl->isInvalidDecl())
+          S.HandleDelayedDeprecationCheck(diag, decl);
+        break;
+
+      case DelayedDiagnostic::Access:
+        S.HandleDelayedAccessCheck(diag, decl);
+        break;
+
+      case DelayedDiagnostic::ForbiddenType:
+        handleDelayedForbiddenType(S, diag, decl);
+        break;
+      }
+    }
+  }
+
+  // Destroy all the delayed diagnostics we're about to pop off.
+  for (unsigned i = state.SavedStackSize, e = DD.StackSize; i != e; ++i)
+    DD.Stack[i].Destroy();
+
+  DD.StackSize = state.SavedStackSize;
+}
+
+static bool isDeclDeprecated(Decl *D) {
+  do {
+    if (D->isDeprecated())
+      return true;
+    // A category implicitly has the availability of the interface.
+    if (const ObjCCategoryDecl *CatD = dyn_cast<ObjCCategoryDecl>(D))
+      return CatD->getClassInterface()->isDeprecated();
+  } while ((D = cast_or_null<Decl>(D->getDeclContext())));
+  return false;
+}
+
+void Sema::HandleDelayedDeprecationCheck(DelayedDiagnostic &DD,
+                                         Decl *Ctx) {
+  if (isDeclDeprecated(Ctx))
+    return;
+
+  DD.Triggered = true;
+  if (!DD.getDeprecationMessage().empty())
+    Diag(DD.Loc, diag::warn_deprecated_message)
+      << DD.getDeprecationDecl()->getDeclName()
+      << DD.getDeprecationMessage();
+  else if (DD.getUnknownObjCClass()) {
+    Diag(DD.Loc, diag::warn_deprecated_fwdclass_message) 
+      << DD.getDeprecationDecl()->getDeclName();
+    Diag(DD.getUnknownObjCClass()->getLocation(), diag::note_forward_class);
+  }
+  else
+    Diag(DD.Loc, diag::warn_deprecated)
+      << DD.getDeprecationDecl()->getDeclName();
+}
+
+void Sema::EmitDeprecationWarning(NamedDecl *D, StringRef Message,
+                                  SourceLocation Loc,
+                                  const ObjCInterfaceDecl *UnknownObjCClass) {
+  // Delay if we're currently parsing a declaration.
+  if (DelayedDiagnostics.shouldDelayDiagnostics()) {
+    DelayedDiagnostics.add(DelayedDiagnostic::makeDeprecation(Loc, D, 
+                                                              UnknownObjCClass,
+                                                              Message));
+    return;
+  }
+
+  // Otherwise, don't warn if our current context is deprecated.
+  if (isDeclDeprecated(cast<Decl>(getCurLexicalContext())))
+    return;
+  if (!Message.empty())
+    Diag(Loc, diag::warn_deprecated_message) << D->getDeclName() 
+                                             << Message;
+  else {
+    if (!UnknownObjCClass)
+      Diag(Loc, diag::warn_deprecated) << D->getDeclName();
+    else {
+      Diag(Loc, diag::warn_deprecated_fwdclass_message) << D->getDeclName();
+      Diag(UnknownObjCClass->getLocation(), diag::note_forward_class);
+    }
+  }
+}
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
new file mode 100644
index 0000000..c861072
--- /dev/null
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -0,0 +1,11340 @@
+//===------ SemaDeclCXX.cpp - Semantic Analysis for C++ Declarations ------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+//  This file implements semantic analysis for C++ declarations.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Sema/SemaInternal.h"
+#include "clang/Sema/CXXFieldCollector.h"
+#include "clang/Sema/Scope.h"
+#include "clang/Sema/Initialization.h"
+#include "clang/Sema/Lookup.h"
+#include "clang/Sema/ScopeInfo.h"
+#include "clang/AST/ASTConsumer.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/ASTMutationListener.h"
+#include "clang/AST/CharUnits.h"
+#include "clang/AST/CXXInheritance.h"
+#include "clang/AST/DeclVisitor.h"
+#include "clang/AST/ExprCXX.h"
+#include "clang/AST/RecordLayout.h"
+#include "clang/AST/RecursiveASTVisitor.h"
+#include "clang/AST/StmtVisitor.h"
+#include "clang/AST/TypeLoc.h"
+#include "clang/AST/TypeOrdering.h"
+#include "clang/Sema/DeclSpec.h"
+#include "clang/Sema/ParsedTemplate.h"
+#include "clang/Basic/PartialDiagnostic.h"
+#include "clang/Lex/Preprocessor.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/STLExtras.h"
+#include <map>
+#include <set>
+
+using namespace clang;
+
+//===----------------------------------------------------------------------===//
+// CheckDefaultArgumentVisitor
+//===----------------------------------------------------------------------===//
+
+namespace {
+  /// CheckDefaultArgumentVisitor - C++ [dcl.fct.default] Traverses
+  /// the default argument of a parameter to determine whether it
+  /// contains any ill-formed subexpressions. For example, this will
+  /// diagnose the use of local variables or parameters within the
+  /// default argument expression.
+  class CheckDefaultArgumentVisitor
+    : public StmtVisitor<CheckDefaultArgumentVisitor, bool> {
+    Expr *DefaultArg;
+    Sema *S;
+
+  public:
+    CheckDefaultArgumentVisitor(Expr *defarg, Sema *s)
+      : DefaultArg(defarg), S(s) {}
+
+    bool VisitExpr(Expr *Node);
+    bool VisitDeclRefExpr(DeclRefExpr *DRE);
+    bool VisitCXXThisExpr(CXXThisExpr *ThisE);
+    bool VisitLambdaExpr(LambdaExpr *Lambda);
+  };
+
+  /// VisitExpr - Visit all of the children of this expression.
+  bool CheckDefaultArgumentVisitor::VisitExpr(Expr *Node) {
+    bool IsInvalid = false;
+    for (Stmt::child_range I = Node->children(); I; ++I)
+      IsInvalid |= Visit(*I);
+    return IsInvalid;
+  }
+
+  /// VisitDeclRefExpr - Visit a reference to a declaration, to
+  /// determine whether this declaration can be used in the default
+  /// argument expression.
+  bool CheckDefaultArgumentVisitor::VisitDeclRefExpr(DeclRefExpr *DRE) {
+    NamedDecl *Decl = DRE->getDecl();
+    if (ParmVarDecl *Param = dyn_cast<ParmVarDecl>(Decl)) {
+      // C++ [dcl.fct.default]p9
+      //   Default arguments are evaluated each time the function is
+      //   called. The order of evaluation of function arguments is
+      //   unspecified. Consequently, parameters of a function shall not
+      //   be used in default argument expressions, even if they are not
+      //   evaluated. Parameters of a function declared before a default
+      //   argument expression are in scope and can hide namespace and
+      //   class member names.
+      return S->Diag(DRE->getLocStart(),
+                     diag::err_param_default_argument_references_param)
+         << Param->getDeclName() << DefaultArg->getSourceRange();
+    } else if (VarDecl *VDecl = dyn_cast<VarDecl>(Decl)) {
+      // C++ [dcl.fct.default]p7
+      //   Local variables shall not be used in default argument
+      //   expressions.
+      if (VDecl->isLocalVarDecl())
+        return S->Diag(DRE->getLocStart(),
+                       diag::err_param_default_argument_references_local)
+          << VDecl->getDeclName() << DefaultArg->getSourceRange();
+    }
+
+    return false;
+  }
+
+  /// VisitCXXThisExpr - Visit a C++ "this" expression.
+  bool CheckDefaultArgumentVisitor::VisitCXXThisExpr(CXXThisExpr *ThisE) {
+    // C++ [dcl.fct.default]p8:
+    //   The keyword this shall not be used in a default argument of a
+    //   member function.
+    return S->Diag(ThisE->getLocStart(),
+                   diag::err_param_default_argument_references_this)
+               << ThisE->getSourceRange();
+  }
+
+  bool CheckDefaultArgumentVisitor::VisitLambdaExpr(LambdaExpr *Lambda) {
+    // C++11 [expr.lambda.prim]p13:
+    //   A lambda-expression appearing in a default argument shall not
+    //   implicitly or explicitly capture any entity.
+    if (Lambda->capture_begin() == Lambda->capture_end())
+      return false;
+
+    return S->Diag(Lambda->getLocStart(), 
+                   diag::err_lambda_capture_default_arg);
+  }
+}
+
+void Sema::ImplicitExceptionSpecification::CalledDecl(SourceLocation CallLoc,
+                                                      CXXMethodDecl *Method) {
+  // If we have an MSAny or unknown spec already, don't bother.
+  if (!Method || ComputedEST == EST_MSAny || ComputedEST == EST_Delayed)
+    return;
+
+  const FunctionProtoType *Proto
+    = Method->getType()->getAs<FunctionProtoType>();
+  Proto = Self->ResolveExceptionSpec(CallLoc, Proto);
+  if (!Proto)
+    return;
+
+  ExceptionSpecificationType EST = Proto->getExceptionSpecType();
+
+  // If this function can throw any exceptions, make a note of that.
+  if (EST == EST_Delayed || EST == EST_MSAny || EST == EST_None) {
+    ClearExceptions();
+    ComputedEST = EST;
+    return;
+  }
+
+  // FIXME: If the call to this decl is using any of its default arguments, we
+  // need to search them for potentially-throwing calls.
+
+  // If this function has a basic noexcept, it doesn't affect the outcome.
+  if (EST == EST_BasicNoexcept)
+    return;
+
+  // If we have a throw-all spec at this point, ignore the function.
+  if (ComputedEST == EST_None)
+    return;
+
+  // If we're still at noexcept(true) and there's a nothrow() callee,
+  // change to that specification.
+  if (EST == EST_DynamicNone) {
+    if (ComputedEST == EST_BasicNoexcept)
+      ComputedEST = EST_DynamicNone;
+    return;
+  }
+
+  // Check out noexcept specs.
+  if (EST == EST_ComputedNoexcept) {
+    FunctionProtoType::NoexceptResult NR =
+        Proto->getNoexceptSpec(Self->Context);
+    assert(NR != FunctionProtoType::NR_NoNoexcept &&
+           "Must have noexcept result for EST_ComputedNoexcept.");
+    assert(NR != FunctionProtoType::NR_Dependent &&
+           "Should not generate implicit declarations for dependent cases, "
+           "and don't know how to handle them anyway.");
+
+    // noexcept(false) -> no spec on the new function
+    if (NR == FunctionProtoType::NR_Throw) {
+      ClearExceptions();
+      ComputedEST = EST_None;
+    }
+    // noexcept(true) won't change anything either.
+    return;
+  }
+
+  assert(EST == EST_Dynamic && "EST case not considered earlier.");
+  assert(ComputedEST != EST_None &&
+         "Shouldn't collect exceptions when throw-all is guaranteed.");
+  ComputedEST = EST_Dynamic;
+  // Record the exceptions in this function's exception specification.
+  for (FunctionProtoType::exception_iterator E = Proto->exception_begin(),
+                                          EEnd = Proto->exception_end();
+       E != EEnd; ++E)
+    if (ExceptionsSeen.insert(Self->Context.getCanonicalType(*E)))
+      Exceptions.push_back(*E);
+}
+
+void Sema::ImplicitExceptionSpecification::CalledExpr(Expr *E) {
+  if (!E || ComputedEST == EST_MSAny || ComputedEST == EST_Delayed)
+    return;
+
+  // FIXME:
+  //
+  // C++0x [except.spec]p14:
+  //   [An] implicit exception-specification specifies the type-id T if and
+  // only if T is allowed by the exception-specification of a function directly
+  // invoked by f's implicit definition; f shall allow all exceptions if any
+  // function it directly invokes allows all exceptions, and f shall allow no
+  // exceptions if every function it directly invokes allows no exceptions.
+  //
+  // Note in particular that if an implicit exception-specification is generated
+  // for a function containing a throw-expression, that specification can still
+  // be noexcept(true).
+  //
+  // Note also that 'directly invoked' is not defined in the standard, and there
+  // is no indication that we should only consider potentially-evaluated calls.
+  //
+  // Ultimately we should implement the intent of the standard: the exception
+  // specification should be the set of exceptions which can be thrown by the
+  // implicit definition. For now, we assume that any non-nothrow expression can
+  // throw any exception.
+
+  if (Self->canThrow(E))
+    ComputedEST = EST_None;
+}
+
+bool
+Sema::SetParamDefaultArgument(ParmVarDecl *Param, Expr *Arg,
+                              SourceLocation EqualLoc) {
+  if (RequireCompleteType(Param->getLocation(), Param->getType(),
+                          diag::err_typecheck_decl_incomplete_type)) {
+    Param->setInvalidDecl();
+    return true;
+  }
+
+  // C++ [dcl.fct.default]p5
+  //   A default argument expression is implicitly converted (clause
+  //   4) to the parameter type. The default argument expression has
+  //   the same semantic constraints as the initializer expression in
+  //   a declaration of a variable of the parameter type, using the
+  //   copy-initialization semantics (8.5).
+  InitializedEntity Entity = InitializedEntity::InitializeParameter(Context,
+                                                                    Param);
+  InitializationKind Kind = InitializationKind::CreateCopy(Param->getLocation(),
+                                                           EqualLoc);
+  InitializationSequence InitSeq(*this, Entity, Kind, &Arg, 1);
+  ExprResult Result = InitSeq.Perform(*this, Entity, Kind,
+                                      MultiExprArg(*this, &Arg, 1));
+  if (Result.isInvalid())
+    return true;
+  Arg = Result.takeAs<Expr>();
+
+  CheckImplicitConversions(Arg, EqualLoc);
+  Arg = MaybeCreateExprWithCleanups(Arg);
+
+  // Okay: add the default argument to the parameter
+  Param->setDefaultArg(Arg);
+
+  // We have already instantiated this parameter; provide each of the 
+  // instantiations with the uninstantiated default argument.
+  UnparsedDefaultArgInstantiationsMap::iterator InstPos
+    = UnparsedDefaultArgInstantiations.find(Param);
+  if (InstPos != UnparsedDefaultArgInstantiations.end()) {
+    for (unsigned I = 0, N = InstPos->second.size(); I != N; ++I)
+      InstPos->second[I]->setUninstantiatedDefaultArg(Arg);
+    
+    // We're done tracking this parameter's instantiations.
+    UnparsedDefaultArgInstantiations.erase(InstPos);
+  }
+  
+  return false;
+}
+
+/// ActOnParamDefaultArgument - Check whether the default argument
+/// provided for a function parameter is well-formed. If so, attach it
+/// to the parameter declaration.
+void
+Sema::ActOnParamDefaultArgument(Decl *param, SourceLocation EqualLoc,
+                                Expr *DefaultArg) {
+  if (!param || !DefaultArg)
+    return;
+
+  ParmVarDecl *Param = cast<ParmVarDecl>(param);
+  UnparsedDefaultArgLocs.erase(Param);
+
+  // Default arguments are only permitted in C++
+  if (!getLangOpts().CPlusPlus) {
+    Diag(EqualLoc, diag::err_param_default_argument)
+      << DefaultArg->getSourceRange();
+    Param->setInvalidDecl();
+    return;
+  }
+
+  // Check for unexpanded parameter packs.
+  if (DiagnoseUnexpandedParameterPack(DefaultArg, UPPC_DefaultArgument)) {
+    Param->setInvalidDecl();
+    return;
+  }    
+      
+  // Check that the default argument is well-formed
+  CheckDefaultArgumentVisitor DefaultArgChecker(DefaultArg, this);
+  if (DefaultArgChecker.Visit(DefaultArg)) {
+    Param->setInvalidDecl();
+    return;
+  }
+
+  SetParamDefaultArgument(Param, DefaultArg, EqualLoc);
+}
+
+/// ActOnParamUnparsedDefaultArgument - We've seen a default
+/// argument for a function parameter, but we can't parse it yet
+/// because we're inside a class definition. Note that this default
+/// argument will be parsed later.
+void Sema::ActOnParamUnparsedDefaultArgument(Decl *param,
+                                             SourceLocation EqualLoc,
+                                             SourceLocation ArgLoc) {
+  if (!param)
+    return;
+
+  ParmVarDecl *Param = cast<ParmVarDecl>(param);
+  if (Param)
+    Param->setUnparsedDefaultArg();
+
+  UnparsedDefaultArgLocs[Param] = ArgLoc;
+}
+
+/// ActOnParamDefaultArgumentError - Parsing or semantic analysis of
+/// the default argument for the parameter param failed.
+void Sema::ActOnParamDefaultArgumentError(Decl *param) {
+  if (!param)
+    return;
+
+  ParmVarDecl *Param = cast<ParmVarDecl>(param);
+
+  Param->setInvalidDecl();
+
+  UnparsedDefaultArgLocs.erase(Param);
+}
+
+/// CheckExtraCXXDefaultArguments - Check for any extra default
+/// arguments in the declarator, which is not a function declaration
+/// or definition and therefore is not permitted to have default
+/// arguments. This routine should be invoked for every declarator
+/// that is not a function declaration or definition.
+void Sema::CheckExtraCXXDefaultArguments(Declarator &D) {
+  // C++ [dcl.fct.default]p3
+  //   A default argument expression shall be specified only in the
+  //   parameter-declaration-clause of a function declaration or in a
+  //   template-parameter (14.1). It shall not be specified for a
+  //   parameter pack. If it is specified in a
+  //   parameter-declaration-clause, it shall not occur within a
+  //   declarator or abstract-declarator of a parameter-declaration.
+  for (unsigned i = 0, e = D.getNumTypeObjects(); i != e; ++i) {
+    DeclaratorChunk &chunk = D.getTypeObject(i);
+    if (chunk.Kind == DeclaratorChunk::Function) {
+      for (unsigned argIdx = 0, e = chunk.Fun.NumArgs; argIdx != e; ++argIdx) {
+        ParmVarDecl *Param =
+          cast<ParmVarDecl>(chunk.Fun.ArgInfo[argIdx].Param);
+        if (Param->hasUnparsedDefaultArg()) {
+          CachedTokens *Toks = chunk.Fun.ArgInfo[argIdx].DefaultArgTokens;
+          Diag(Param->getLocation(), diag::err_param_default_argument_nonfunc)
+            << SourceRange((*Toks)[1].getLocation(), Toks->back().getLocation());
+          delete Toks;
+          chunk.Fun.ArgInfo[argIdx].DefaultArgTokens = 0;
+        } else if (Param->getDefaultArg()) {
+          Diag(Param->getLocation(), diag::err_param_default_argument_nonfunc)
+            << Param->getDefaultArg()->getSourceRange();
+          Param->setDefaultArg(0);
+        }
+      }
+    }
+  }
+}
+
+// MergeCXXFunctionDecl - Merge two declarations of the same C++
+// function, once we already know that they have the same
+// type. Subroutine of MergeFunctionDecl. Returns true if there was an
+// error, false otherwise.
+bool Sema::MergeCXXFunctionDecl(FunctionDecl *New, FunctionDecl *Old,
+                                Scope *S) {
+  bool Invalid = false;
+
+  // C++ [dcl.fct.default]p4:
+  //   For non-template functions, default arguments can be added in
+  //   later declarations of a function in the same
+  //   scope. Declarations in different scopes have completely
+  //   distinct sets of default arguments. That is, declarations in
+  //   inner scopes do not acquire default arguments from
+  //   declarations in outer scopes, and vice versa. In a given
+  //   function declaration, all parameters subsequent to a
+  //   parameter with a default argument shall have default
+  //   arguments supplied in this or previous declarations. A
+  //   default argument shall not be redefined by a later
+  //   declaration (not even to the same value).
+  //
+  // C++ [dcl.fct.default]p6:
+  //   Except for member functions of class templates, the default arguments 
+  //   in a member function definition that appears outside of the class 
+  //   definition are added to the set of default arguments provided by the 
+  //   member function declaration in the class definition.
+  for (unsigned p = 0, NumParams = Old->getNumParams(); p < NumParams; ++p) {
+    ParmVarDecl *OldParam = Old->getParamDecl(p);
+    ParmVarDecl *NewParam = New->getParamDecl(p);
+
+    bool OldParamHasDfl = OldParam->hasDefaultArg();
+    bool NewParamHasDfl = NewParam->hasDefaultArg();
+
+    NamedDecl *ND = Old;
+    if (S && !isDeclInScope(ND, New->getDeclContext(), S))
+      // Ignore default parameters of old decl if they are not in
+      // the same scope.
+      OldParamHasDfl = false;
+
+    if (OldParamHasDfl && NewParamHasDfl) {
+
+      unsigned DiagDefaultParamID =
+        diag::err_param_default_argument_redefinition;
+
+      // MSVC accepts that default parameters be redefined for member functions
+      // of template class. The new default parameter's value is ignored.
+      Invalid = true;
+      if (getLangOpts().MicrosoftExt) {
+        CXXMethodDecl* MD = dyn_cast<CXXMethodDecl>(New);
+        if (MD && MD->getParent()->getDescribedClassTemplate()) {
+          // Merge the old default argument into the new parameter.
+          NewParam->setHasInheritedDefaultArg();
+          if (OldParam->hasUninstantiatedDefaultArg())
+            NewParam->setUninstantiatedDefaultArg(
+                                      OldParam->getUninstantiatedDefaultArg());
+          else
+            NewParam->setDefaultArg(OldParam->getInit());
+          DiagDefaultParamID = diag::warn_param_default_argument_redefinition;
+          Invalid = false;
+        }
+      }
+      
+      // FIXME: If we knew where the '=' was, we could easily provide a fix-it 
+      // hint here. Alternatively, we could walk the type-source information
+      // for NewParam to find the last source location in the type... but it
+      // isn't worth the effort right now. This is the kind of test case that
+      // is hard to get right:
+      //   int f(int);
+      //   void g(int (*fp)(int) = f);
+      //   void g(int (*fp)(int) = &f);
+      Diag(NewParam->getLocation(), DiagDefaultParamID)
+        << NewParam->getDefaultArgRange();
+      
+      // Look for the function declaration where the default argument was
+      // actually written, which may be a declaration prior to Old.
+      for (FunctionDecl *Older = Old->getPreviousDecl();
+           Older; Older = Older->getPreviousDecl()) {
+        if (!Older->getParamDecl(p)->hasDefaultArg())
+          break;
+        
+        OldParam = Older->getParamDecl(p);
+      }        
+      
+      Diag(OldParam->getLocation(), diag::note_previous_definition)
+        << OldParam->getDefaultArgRange();
+    } else if (OldParamHasDfl) {
+      // Merge the old default argument into the new parameter.
+      // It's important to use getInit() here;  getDefaultArg()
+      // strips off any top-level ExprWithCleanups.
+      NewParam->setHasInheritedDefaultArg();
+      if (OldParam->hasUninstantiatedDefaultArg())
+        NewParam->setUninstantiatedDefaultArg(
+                                      OldParam->getUninstantiatedDefaultArg());
+      else
+        NewParam->setDefaultArg(OldParam->getInit());
+    } else if (NewParamHasDfl) {
+      if (New->getDescribedFunctionTemplate()) {
+        // Paragraph 4, quoted above, only applies to non-template functions.
+        Diag(NewParam->getLocation(),
+             diag::err_param_default_argument_template_redecl)
+          << NewParam->getDefaultArgRange();
+        Diag(Old->getLocation(), diag::note_template_prev_declaration)
+          << false;
+      } else if (New->getTemplateSpecializationKind()
+                   != TSK_ImplicitInstantiation &&
+                 New->getTemplateSpecializationKind() != TSK_Undeclared) {
+        // C++ [temp.expr.spec]p21:
+        //   Default function arguments shall not be specified in a declaration
+        //   or a definition for one of the following explicit specializations:
+        //     - the explicit specialization of a function template;
+        //     - the explicit specialization of a member function template;
+        //     - the explicit specialization of a member function of a class 
+        //       template where the class template specialization to which the
+        //       member function specialization belongs is implicitly 
+        //       instantiated.
+        Diag(NewParam->getLocation(), diag::err_template_spec_default_arg)
+          << (New->getTemplateSpecializationKind() ==TSK_ExplicitSpecialization)
+          << New->getDeclName()
+          << NewParam->getDefaultArgRange();
+      } else if (New->getDeclContext()->isDependentContext()) {
+        // C++ [dcl.fct.default]p6 (DR217):
+        //   Default arguments for a member function of a class template shall 
+        //   be specified on the initial declaration of the member function 
+        //   within the class template.
+        //
+        // Reading the tea leaves a bit in DR217 and its reference to DR205 
+        // leads me to the conclusion that one cannot add default function 
+        // arguments for an out-of-line definition of a member function of a 
+        // dependent type.
+        int WhichKind = 2;
+        if (CXXRecordDecl *Record 
+              = dyn_cast<CXXRecordDecl>(New->getDeclContext())) {
+          if (Record->getDescribedClassTemplate())
+            WhichKind = 0;
+          else if (isa<ClassTemplatePartialSpecializationDecl>(Record))
+            WhichKind = 1;
+          else
+            WhichKind = 2;
+        }
+        
+        Diag(NewParam->getLocation(), 
+             diag::err_param_default_argument_member_template_redecl)
+          << WhichKind
+          << NewParam->getDefaultArgRange();
+      } else if (CXXConstructorDecl *Ctor = dyn_cast<CXXConstructorDecl>(New)) {
+        CXXSpecialMember NewSM = getSpecialMember(Ctor),
+                         OldSM = getSpecialMember(cast<CXXConstructorDecl>(Old));
+        if (NewSM != OldSM) {
+          Diag(NewParam->getLocation(),diag::warn_default_arg_makes_ctor_special)
+            << NewParam->getDefaultArgRange() << NewSM;
+          Diag(Old->getLocation(), diag::note_previous_declaration_special)
+            << OldSM;
+        }
+      }
+    }
+  }
+
+  // C++11 [dcl.constexpr]p1: If any declaration of a function or function
+  // template has a constexpr specifier then all its declarations shall
+  // contain the constexpr specifier.
+  if (New->isConstexpr() != Old->isConstexpr()) {
+    Diag(New->getLocation(), diag::err_constexpr_redecl_mismatch)
+      << New << New->isConstexpr();
+    Diag(Old->getLocation(), diag::note_previous_declaration);
+    Invalid = true;
+  }
+
+  if (CheckEquivalentExceptionSpec(Old, New))
+    Invalid = true;
+
+  return Invalid;
+}
+
+/// \brief Merge the exception specifications of two variable declarations.
+///
+/// This is called when there's a redeclaration of a VarDecl. The function
+/// checks if the redeclaration might have an exception specification and
+/// validates compatibility and merges the specs if necessary.
+void Sema::MergeVarDeclExceptionSpecs(VarDecl *New, VarDecl *Old) {
+  // Shortcut if exceptions are disabled.
+  if (!getLangOpts().CXXExceptions)
+    return;
+
+  assert(Context.hasSameType(New->getType(), Old->getType()) &&
+         "Should only be called if types are otherwise the same.");
+
+  QualType NewType = New->getType();
+  QualType OldType = Old->getType();
+
+  // We're only interested in pointers and references to functions, as well
+  // as pointers to member functions.
+  if (const ReferenceType *R = NewType->getAs<ReferenceType>()) {
+    NewType = R->getPointeeType();
+    OldType = OldType->getAs<ReferenceType>()->getPointeeType();
+  } else if (const PointerType *P = NewType->getAs<PointerType>()) {
+    NewType = P->getPointeeType();
+    OldType = OldType->getAs<PointerType>()->getPointeeType();
+  } else if (const MemberPointerType *M = NewType->getAs<MemberPointerType>()) {
+    NewType = M->getPointeeType();
+    OldType = OldType->getAs<MemberPointerType>()->getPointeeType();
+  }
+
+  if (!NewType->isFunctionProtoType())
+    return;
+
+  // There's lots of special cases for functions. For function pointers, system
+  // libraries are hopefully not as broken so that we don't need these
+  // workarounds.
+  if (CheckEquivalentExceptionSpec(
+        OldType->getAs<FunctionProtoType>(), Old->getLocation(),
+        NewType->getAs<FunctionProtoType>(), New->getLocation())) {
+    New->setInvalidDecl();
+  }
+}
+
+/// CheckCXXDefaultArguments - Verify that the default arguments for a
+/// function declaration are well-formed according to C++
+/// [dcl.fct.default].
+void Sema::CheckCXXDefaultArguments(FunctionDecl *FD) {
+  unsigned NumParams = FD->getNumParams();
+  unsigned p;
+
+  bool IsLambda = FD->getOverloadedOperator() == OO_Call &&
+                  isa<CXXMethodDecl>(FD) &&
+                  cast<CXXMethodDecl>(FD)->getParent()->isLambda();
+              
+  // Find first parameter with a default argument
+  for (p = 0; p < NumParams; ++p) {
+    ParmVarDecl *Param = FD->getParamDecl(p);
+    if (Param->hasDefaultArg()) {
+      // C++11 [expr.prim.lambda]p5:
+      //   [...] Default arguments (8.3.6) shall not be specified in the 
+      //   parameter-declaration-clause of a lambda-declarator.
+      //
+      // FIXME: Core issue 974 strikes this sentence, we only provide an
+      // extension warning.
+      if (IsLambda)
+        Diag(Param->getLocation(), diag::ext_lambda_default_arguments)
+          << Param->getDefaultArgRange();
+      break;
+    }
+  }
+
+  // C++ [dcl.fct.default]p4:
+  //   In a given function declaration, all parameters
+  //   subsequent to a parameter with a default argument shall
+  //   have default arguments supplied in this or previous
+  //   declarations. A default argument shall not be redefined
+  //   by a later declaration (not even to the same value).
+  unsigned LastMissingDefaultArg = 0;
+  for (; p < NumParams; ++p) {
+    ParmVarDecl *Param = FD->getParamDecl(p);
+    if (!Param->hasDefaultArg()) {
+      if (Param->isInvalidDecl())
+        /* We already complained about this parameter. */;
+      else if (Param->getIdentifier())
+        Diag(Param->getLocation(),
+             diag::err_param_default_argument_missing_name)
+          << Param->getIdentifier();
+      else
+        Diag(Param->getLocation(),
+             diag::err_param_default_argument_missing);
+
+      LastMissingDefaultArg = p;
+    }
+  }
+
+  if (LastMissingDefaultArg > 0) {
+    // Some default arguments were missing. Clear out all of the
+    // default arguments up to (and including) the last missing
+    // default argument, so that we leave the function parameters
+    // in a semantically valid state.
+    for (p = 0; p <= LastMissingDefaultArg; ++p) {
+      ParmVarDecl *Param = FD->getParamDecl(p);
+      if (Param->hasDefaultArg()) {
+        Param->setDefaultArg(0);
+      }
+    }
+  }
+}
+
+// CheckConstexprParameterTypes - Check whether a function's parameter types
+// are all literal types. If so, return true. If not, produce a suitable
+// diagnostic and return false.
+static bool CheckConstexprParameterTypes(Sema &SemaRef,
+                                         const FunctionDecl *FD) {
+  unsigned ArgIndex = 0;
+  const FunctionProtoType *FT = FD->getType()->getAs<FunctionProtoType>();
+  for (FunctionProtoType::arg_type_iterator i = FT->arg_type_begin(),
+       e = FT->arg_type_end(); i != e; ++i, ++ArgIndex) {
+    const ParmVarDecl *PD = FD->getParamDecl(ArgIndex);
+    SourceLocation ParamLoc = PD->getLocation();
+    if (!(*i)->isDependentType() &&
+        SemaRef.RequireLiteralType(ParamLoc, *i,
+                            SemaRef.PDiag(diag::err_constexpr_non_literal_param)
+                                     << ArgIndex+1 << PD->getSourceRange()
+                                     << isa<CXXConstructorDecl>(FD)))
+      return false;
+  }
+  return true;
+}
+
+// CheckConstexprFunctionDecl - Check whether a function declaration satisfies
+// the requirements of a constexpr function definition or a constexpr
+// constructor definition. If so, return true. If not, produce appropriate
+// diagnostics and return false.
+//
+// This implements C++11 [dcl.constexpr]p3,4, as amended by DR1360.
+bool Sema::CheckConstexprFunctionDecl(const FunctionDecl *NewFD) {
+  const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(NewFD);
+  if (MD && MD->isInstance()) {
+    // C++11 [dcl.constexpr]p4:
+    //  The definition of a constexpr constructor shall satisfy the following
+    //  constraints:
+    //  - the class shall not have any virtual base classes;
+    const CXXRecordDecl *RD = MD->getParent();
+    if (RD->getNumVBases()) {
+      Diag(NewFD->getLocation(), diag::err_constexpr_virtual_base)
+        << isa<CXXConstructorDecl>(NewFD) << RD->isStruct()
+        << RD->getNumVBases();
+      for (CXXRecordDecl::base_class_const_iterator I = RD->vbases_begin(),
+             E = RD->vbases_end(); I != E; ++I)
+        Diag(I->getLocStart(),
+             diag::note_constexpr_virtual_base_here) << I->getSourceRange();
+      return false;
+    }
+  }
+
+  if (!isa<CXXConstructorDecl>(NewFD)) {
+    // C++11 [dcl.constexpr]p3:
+    //  The definition of a constexpr function shall satisfy the following
+    //  constraints:
+    // - it shall not be virtual;
+    const CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(NewFD);
+    if (Method && Method->isVirtual()) {
+      Diag(NewFD->getLocation(), diag::err_constexpr_virtual);
+
+      // If it's not obvious why this function is virtual, find an overridden
+      // function which uses the 'virtual' keyword.
+      const CXXMethodDecl *WrittenVirtual = Method;
+      while (!WrittenVirtual->isVirtualAsWritten())
+        WrittenVirtual = *WrittenVirtual->begin_overridden_methods();
+      if (WrittenVirtual != Method)
+        Diag(WrittenVirtual->getLocation(),
+             diag::note_overridden_virtual_function);
+      return false;
+    }
+
+    // - its return type shall be a literal type;
+    QualType RT = NewFD->getResultType();
+    if (!RT->isDependentType() &&
+        RequireLiteralType(NewFD->getLocation(), RT,
+                           PDiag(diag::err_constexpr_non_literal_return)))
+      return false;
+  }
+
+  // - each of its parameter types shall be a literal type;
+  if (!CheckConstexprParameterTypes(*this, NewFD))
+    return false;
+
+  return true;
+}
+
+/// Check the given declaration statement is legal within a constexpr function
+/// body. C++0x [dcl.constexpr]p3,p4.
+///
+/// \return true if the body is OK, false if we have diagnosed a problem.
+static bool CheckConstexprDeclStmt(Sema &SemaRef, const FunctionDecl *Dcl,
+                                   DeclStmt *DS) {
+  // C++0x [dcl.constexpr]p3 and p4:
+  //  The definition of a constexpr function(p3) or constructor(p4) [...] shall
+  //  contain only
+  for (DeclStmt::decl_iterator DclIt = DS->decl_begin(),
+         DclEnd = DS->decl_end(); DclIt != DclEnd; ++DclIt) {
+    switch ((*DclIt)->getKind()) {
+    case Decl::StaticAssert:
+    case Decl::Using:
+    case Decl::UsingShadow:
+    case Decl::UsingDirective:
+    case Decl::UnresolvedUsingTypename:
+      //   - static_assert-declarations
+      //   - using-declarations,
+      //   - using-directives,
+      continue;
+
+    case Decl::Typedef:
+    case Decl::TypeAlias: {
+      //   - typedef declarations and alias-declarations that do not define
+      //     classes or enumerations,
+      TypedefNameDecl *TN = cast<TypedefNameDecl>(*DclIt);
+      if (TN->getUnderlyingType()->isVariablyModifiedType()) {
+        // Don't allow variably-modified types in constexpr functions.
+        TypeLoc TL = TN->getTypeSourceInfo()->getTypeLoc();
+        SemaRef.Diag(TL.getBeginLoc(), diag::err_constexpr_vla)
+          << TL.getSourceRange() << TL.getType()
+          << isa<CXXConstructorDecl>(Dcl);
+        return false;
+      }
+      continue;
+    }
+
+    case Decl::Enum:
+    case Decl::CXXRecord:
+      // As an extension, we allow the declaration (but not the definition) of
+      // classes and enumerations in all declarations, not just in typedef and
+      // alias declarations.
+      if (cast<TagDecl>(*DclIt)->isThisDeclarationADefinition()) {
+        SemaRef.Diag(DS->getLocStart(), diag::err_constexpr_type_definition)
+          << isa<CXXConstructorDecl>(Dcl);
+        return false;
+      }
+      continue;
+
+    case Decl::Var:
+      SemaRef.Diag(DS->getLocStart(), diag::err_constexpr_var_declaration)
+        << isa<CXXConstructorDecl>(Dcl);
+      return false;
+
+    default:
+      SemaRef.Diag(DS->getLocStart(), diag::err_constexpr_body_invalid_stmt)
+        << isa<CXXConstructorDecl>(Dcl);
+      return false;
+    }
+  }
+
+  return true;
+}
+
+/// Check that the given field is initialized within a constexpr constructor.
+///
+/// \param Dcl The constexpr constructor being checked.
+/// \param Field The field being checked. This may be a member of an anonymous
+///        struct or union nested within the class being checked.
+/// \param Inits All declarations, including anonymous struct/union members and
+///        indirect members, for which any initialization was provided.
+/// \param Diagnosed Set to true if an error is produced.
+static void CheckConstexprCtorInitializer(Sema &SemaRef,
+                                          const FunctionDecl *Dcl,
+                                          FieldDecl *Field,
+                                          llvm::SmallSet<Decl*, 16> &Inits,
+                                          bool &Diagnosed) {
+  if (Field->isUnnamedBitfield())
+    return;
+
+  if (Field->isAnonymousStructOrUnion() &&
+      Field->getType()->getAsCXXRecordDecl()->isEmpty())
+    return;
+
+  if (!Inits.count(Field)) {
+    if (!Diagnosed) {
+      SemaRef.Diag(Dcl->getLocation(), diag::err_constexpr_ctor_missing_init);
+      Diagnosed = true;
+    }
+    SemaRef.Diag(Field->getLocation(), diag::note_constexpr_ctor_missing_init);
+  } else if (Field->isAnonymousStructOrUnion()) {
+    const RecordDecl *RD = Field->getType()->castAs<RecordType>()->getDecl();
+    for (RecordDecl::field_iterator I = RD->field_begin(), E = RD->field_end();
+         I != E; ++I)
+      // If an anonymous union contains an anonymous struct of which any member
+      // is initialized, all members must be initialized.
+      if (!RD->isUnion() || Inits.count(*I))
+        CheckConstexprCtorInitializer(SemaRef, Dcl, *I, Inits, Diagnosed);
+  }
+}
+
+/// Check the body for the given constexpr function declaration only contains
+/// the permitted types of statement. C++11 [dcl.constexpr]p3,p4.
+///
+/// \return true if the body is OK, false if we have diagnosed a problem.
+bool Sema::CheckConstexprFunctionBody(const FunctionDecl *Dcl, Stmt *Body) {
+  if (isa<CXXTryStmt>(Body)) {
+    // C++11 [dcl.constexpr]p3:
+    //  The definition of a constexpr function shall satisfy the following
+    //  constraints: [...]
+    // - its function-body shall be = delete, = default, or a
+    //   compound-statement
+    //
+    // C++11 [dcl.constexpr]p4:
+    //  In the definition of a constexpr constructor, [...]
+    // - its function-body shall not be a function-try-block;
+    Diag(Body->getLocStart(), diag::err_constexpr_function_try_block)
+      << isa<CXXConstructorDecl>(Dcl);
+    return false;
+  }
+
+  // - its function-body shall be [...] a compound-statement that contains only
+  CompoundStmt *CompBody = cast<CompoundStmt>(Body);
+
+  llvm::SmallVector<SourceLocation, 4> ReturnStmts;
+  for (CompoundStmt::body_iterator BodyIt = CompBody->body_begin(),
+         BodyEnd = CompBody->body_end(); BodyIt != BodyEnd; ++BodyIt) {
+    switch ((*BodyIt)->getStmtClass()) {
+    case Stmt::NullStmtClass:
+      //   - null statements,
+      continue;
+
+    case Stmt::DeclStmtClass:
+      //   - static_assert-declarations
+      //   - using-declarations,
+      //   - using-directives,
+      //   - typedef declarations and alias-declarations that do not define
+      //     classes or enumerations,
+      if (!CheckConstexprDeclStmt(*this, Dcl, cast<DeclStmt>(*BodyIt)))
+        return false;
+      continue;
+
+    case Stmt::ReturnStmtClass:
+      //   - and exactly one return statement;
+      if (isa<CXXConstructorDecl>(Dcl))
+        break;
+
+      ReturnStmts.push_back((*BodyIt)->getLocStart());
+      continue;
+
+    default:
+      break;
+    }
+
+    Diag((*BodyIt)->getLocStart(), diag::err_constexpr_body_invalid_stmt)
+      << isa<CXXConstructorDecl>(Dcl);
+    return false;
+  }
+
+  if (const CXXConstructorDecl *Constructor
+        = dyn_cast<CXXConstructorDecl>(Dcl)) {
+    const CXXRecordDecl *RD = Constructor->getParent();
+    // DR1359:
+    // - every non-variant non-static data member and base class sub-object
+    //   shall be initialized;
+    // - if the class is a non-empty union, or for each non-empty anonymous
+    //   union member of a non-union class, exactly one non-static data member
+    //   shall be initialized;
+    if (RD->isUnion()) {
+      if (Constructor->getNumCtorInitializers() == 0 && !RD->isEmpty()) {
+        Diag(Dcl->getLocation(), diag::err_constexpr_union_ctor_no_init);
+        return false;
+      }
+    } else if (!Constructor->isDependentContext() &&
+               !Constructor->isDelegatingConstructor()) {
+      assert(RD->getNumVBases() == 0 && "constexpr ctor with virtual bases");
+
+      // Skip detailed checking if we have enough initializers, and we would
+      // allow at most one initializer per member.
+      bool AnyAnonStructUnionMembers = false;
+      unsigned Fields = 0;
+      for (CXXRecordDecl::field_iterator I = RD->field_begin(),
+           E = RD->field_end(); I != E; ++I, ++Fields) {
+        if ((*I)->isAnonymousStructOrUnion()) {
+          AnyAnonStructUnionMembers = true;
+          break;
+        }
+      }
+      if (AnyAnonStructUnionMembers ||
+          Constructor->getNumCtorInitializers() != RD->getNumBases() + Fields) {
+        // Check initialization of non-static data members. Base classes are
+        // always initialized so do not need to be checked. Dependent bases
+        // might not have initializers in the member initializer list.
+        llvm::SmallSet<Decl*, 16> Inits;
+        for (CXXConstructorDecl::init_const_iterator
+               I = Constructor->init_begin(), E = Constructor->init_end();
+             I != E; ++I) {
+          if (FieldDecl *FD = (*I)->getMember())
+            Inits.insert(FD);
+          else if (IndirectFieldDecl *ID = (*I)->getIndirectMember())
+            Inits.insert(ID->chain_begin(), ID->chain_end());
+        }
+
+        bool Diagnosed = false;
+        for (CXXRecordDecl::field_iterator I = RD->field_begin(),
+             E = RD->field_end(); I != E; ++I)
+          CheckConstexprCtorInitializer(*this, Dcl, *I, Inits, Diagnosed);
+        if (Diagnosed)
+          return false;
+      }
+    }
+  } else {
+    if (ReturnStmts.empty()) {
+      Diag(Dcl->getLocation(), diag::err_constexpr_body_no_return);
+      return false;
+    }
+    if (ReturnStmts.size() > 1) {
+      Diag(ReturnStmts.back(), diag::err_constexpr_body_multiple_return);
+      for (unsigned I = 0; I < ReturnStmts.size() - 1; ++I)
+        Diag(ReturnStmts[I], diag::note_constexpr_body_previous_return);
+      return false;
+    }
+  }
+
+  // C++11 [dcl.constexpr]p5:
+  //   if no function argument values exist such that the function invocation
+  //   substitution would produce a constant expression, the program is
+  //   ill-formed; no diagnostic required.
+  // C++11 [dcl.constexpr]p3:
+  //   - every constructor call and implicit conversion used in initializing the
+  //     return value shall be one of those allowed in a constant expression.
+  // C++11 [dcl.constexpr]p4:
+  //   - every constructor involved in initializing non-static data members and
+  //     base class sub-objects shall be a constexpr constructor.
+  llvm::SmallVector<PartialDiagnosticAt, 8> Diags;
+  if (!Expr::isPotentialConstantExpr(Dcl, Diags)) {
+    Diag(Dcl->getLocation(), diag::err_constexpr_function_never_constant_expr)
+      << isa<CXXConstructorDecl>(Dcl);
+    for (size_t I = 0, N = Diags.size(); I != N; ++I)
+      Diag(Diags[I].first, Diags[I].second);
+    return false;
+  }
+
+  return true;
+}
+
+/// isCurrentClassName - Determine whether the identifier II is the
+/// name of the class type currently being defined. In the case of
+/// nested classes, this will only return true if II is the name of
+/// the innermost class.
+bool Sema::isCurrentClassName(const IdentifierInfo &II, Scope *,
+                              const CXXScopeSpec *SS) {
+  assert(getLangOpts().CPlusPlus && "No class names in C!");
+
+  CXXRecordDecl *CurDecl;
+  if (SS && SS->isSet() && !SS->isInvalid()) {
+    DeclContext *DC = computeDeclContext(*SS, true);
+    CurDecl = dyn_cast_or_null<CXXRecordDecl>(DC);
+  } else
+    CurDecl = dyn_cast_or_null<CXXRecordDecl>(CurContext);
+
+  if (CurDecl && CurDecl->getIdentifier())
+    return &II == CurDecl->getIdentifier();
+  else
+    return false;
+}
+
+/// \brief Check the validity of a C++ base class specifier.
+///
+/// \returns a new CXXBaseSpecifier if well-formed, emits diagnostics
+/// and returns NULL otherwise.
+CXXBaseSpecifier *
+Sema::CheckBaseSpecifier(CXXRecordDecl *Class,
+                         SourceRange SpecifierRange,
+                         bool Virtual, AccessSpecifier Access,
+                         TypeSourceInfo *TInfo,
+                         SourceLocation EllipsisLoc) {
+  QualType BaseType = TInfo->getType();
+
+  // C++ [class.union]p1:
+  //   A union shall not have base classes.
+  if (Class->isUnion()) {
+    Diag(Class->getLocation(), diag::err_base_clause_on_union)
+      << SpecifierRange;
+    return 0;
+  }
+
+  if (EllipsisLoc.isValid() && 
+      !TInfo->getType()->containsUnexpandedParameterPack()) {
+    Diag(EllipsisLoc, diag::err_pack_expansion_without_parameter_packs)
+      << TInfo->getTypeLoc().getSourceRange();
+    EllipsisLoc = SourceLocation();
+  }
+  
+  if (BaseType->isDependentType())
+    return new (Context) CXXBaseSpecifier(SpecifierRange, Virtual,
+                                          Class->getTagKind() == TTK_Class,
+                                          Access, TInfo, EllipsisLoc);
+
+  SourceLocation BaseLoc = TInfo->getTypeLoc().getBeginLoc();
+
+  // Base specifiers must be record types.
+  if (!BaseType->isRecordType()) {
+    Diag(BaseLoc, diag::err_base_must_be_class) << SpecifierRange;
+    return 0;
+  }
+
+  // C++ [class.union]p1:
+  //   A union shall not be used as a base class.
+  if (BaseType->isUnionType()) {
+    Diag(BaseLoc, diag::err_union_as_base_class) << SpecifierRange;
+    return 0;
+  }
+
+  // C++ [class.derived]p2:
+  //   The class-name in a base-specifier shall not be an incompletely
+  //   defined class.
+  if (RequireCompleteType(BaseLoc, BaseType,
+                          PDiag(diag::err_incomplete_base_class)
+                            << SpecifierRange)) {
+    Class->setInvalidDecl();
+    return 0;
+  }
+
+  // If the base class is polymorphic or isn't empty, the new one is/isn't, too.
+  RecordDecl *BaseDecl = BaseType->getAs<RecordType>()->getDecl();
+  assert(BaseDecl && "Record type has no declaration");
+  BaseDecl = BaseDecl->getDefinition();
+  assert(BaseDecl && "Base type is not incomplete, but has no definition");
+  CXXRecordDecl * CXXBaseDecl = cast<CXXRecordDecl>(BaseDecl);
+  assert(CXXBaseDecl && "Base type is not a C++ type");
+
+  // C++ [class]p3:
+  //   If a class is marked final and it appears as a base-type-specifier in 
+  //   base-clause, the program is ill-formed.
+  if (CXXBaseDecl->hasAttr<FinalAttr>()) {
+    Diag(BaseLoc, diag::err_class_marked_final_used_as_base) 
+      << CXXBaseDecl->getDeclName();
+    Diag(CXXBaseDecl->getLocation(), diag::note_previous_decl)
+      << CXXBaseDecl->getDeclName();
+    return 0;
+  }
+
+  if (BaseDecl->isInvalidDecl())
+    Class->setInvalidDecl();
+  
+  // Create the base specifier.
+  return new (Context) CXXBaseSpecifier(SpecifierRange, Virtual,
+                                        Class->getTagKind() == TTK_Class,
+                                        Access, TInfo, EllipsisLoc);
+}
+
+/// ActOnBaseSpecifier - Parsed a base specifier. A base specifier is
+/// one entry in the base class list of a class specifier, for
+/// example:
+///    class foo : public bar, virtual private baz {
+/// 'public bar' and 'virtual private baz' are each base-specifiers.
+BaseResult
+Sema::ActOnBaseSpecifier(Decl *classdecl, SourceRange SpecifierRange,
+                         bool Virtual, AccessSpecifier Access,
+                         ParsedType basetype, SourceLocation BaseLoc,
+                         SourceLocation EllipsisLoc) {
+  if (!classdecl)
+    return true;
+
+  AdjustDeclIfTemplate(classdecl);
+  CXXRecordDecl *Class = dyn_cast<CXXRecordDecl>(classdecl);
+  if (!Class)
+    return true;
+
+  TypeSourceInfo *TInfo = 0;
+  GetTypeFromParser(basetype, &TInfo);
+
+  if (EllipsisLoc.isInvalid() &&
+      DiagnoseUnexpandedParameterPack(SpecifierRange.getBegin(), TInfo, 
+                                      UPPC_BaseType))
+    return true;
+  
+  if (CXXBaseSpecifier *BaseSpec = CheckBaseSpecifier(Class, SpecifierRange,
+                                                      Virtual, Access, TInfo,
+                                                      EllipsisLoc))
+    return BaseSpec;
+
+  return true;
+}
+
+/// \brief Performs the actual work of attaching the given base class
+/// specifiers to a C++ class.
+bool Sema::AttachBaseSpecifiers(CXXRecordDecl *Class, CXXBaseSpecifier **Bases,
+                                unsigned NumBases) {
+ if (NumBases == 0)
+    return false;
+
+  // Used to keep track of which base types we have already seen, so
+  // that we can properly diagnose redundant direct base types. Note
+  // that the key is always the unqualified canonical type of the base
+  // class.
+  std::map<QualType, CXXBaseSpecifier*, QualTypeOrdering> KnownBaseTypes;
+
+  // Copy non-redundant base specifiers into permanent storage.
+  unsigned NumGoodBases = 0;
+  bool Invalid = false;
+  for (unsigned idx = 0; idx < NumBases; ++idx) {
+    QualType NewBaseType
+      = Context.getCanonicalType(Bases[idx]->getType());
+    NewBaseType = NewBaseType.getLocalUnqualifiedType();
+
+    CXXBaseSpecifier *&KnownBase = KnownBaseTypes[NewBaseType];
+    if (KnownBase) {
+      // C++ [class.mi]p3:
+      //   A class shall not be specified as a direct base class of a
+      //   derived class more than once.
+      Diag(Bases[idx]->getLocStart(),
+           diag::err_duplicate_base_class)
+        << KnownBase->getType()
+        << Bases[idx]->getSourceRange();
+
+      // Delete the duplicate base class specifier; we're going to
+      // overwrite its pointer later.
+      Context.Deallocate(Bases[idx]);
+
+      Invalid = true;
+    } else {
+      // Okay, add this new base class.
+      KnownBase = Bases[idx];
+      Bases[NumGoodBases++] = Bases[idx];
+      if (const RecordType *Record = NewBaseType->getAs<RecordType>())
+        if (const CXXRecordDecl *RD = cast<CXXRecordDecl>(Record->getDecl()))
+          if (RD->hasAttr<WeakAttr>())
+            Class->addAttr(::new (Context) WeakAttr(SourceRange(), Context));
+    }
+  }
+
+  // Attach the remaining base class specifiers to the derived class.
+  Class->setBases(Bases, NumGoodBases);
+
+  // Delete the remaining (good) base class specifiers, since their
+  // data has been copied into the CXXRecordDecl.
+  for (unsigned idx = 0; idx < NumGoodBases; ++idx)
+    Context.Deallocate(Bases[idx]);
+
+  return Invalid;
+}
+
+/// ActOnBaseSpecifiers - Attach the given base specifiers to the
+/// class, after checking whether there are any duplicate base
+/// classes.
+void Sema::ActOnBaseSpecifiers(Decl *ClassDecl, CXXBaseSpecifier **Bases,
+                               unsigned NumBases) {
+  if (!ClassDecl || !Bases || !NumBases)
+    return;
+
+  AdjustDeclIfTemplate(ClassDecl);
+  AttachBaseSpecifiers(cast<CXXRecordDecl>(ClassDecl),
+                       (CXXBaseSpecifier**)(Bases), NumBases);
+}
+
+static CXXRecordDecl *GetClassForType(QualType T) {
+  if (const RecordType *RT = T->getAs<RecordType>())
+    return cast<CXXRecordDecl>(RT->getDecl());
+  else if (const InjectedClassNameType *ICT = T->getAs<InjectedClassNameType>())
+    return ICT->getDecl();
+  else
+    return 0;
+}
+
+/// \brief Determine whether the type \p Derived is a C++ class that is
+/// derived from the type \p Base.
+bool Sema::IsDerivedFrom(QualType Derived, QualType Base) {
+  if (!getLangOpts().CPlusPlus)
+    return false;
+  
+  CXXRecordDecl *DerivedRD = GetClassForType(Derived);
+  if (!DerivedRD)
+    return false;
+  
+  CXXRecordDecl *BaseRD = GetClassForType(Base);
+  if (!BaseRD)
+    return false;
+  
+  // FIXME: instantiate DerivedRD if necessary.  We need a PoI for this.
+  return DerivedRD->hasDefinition() && DerivedRD->isDerivedFrom(BaseRD);
+}
+
+/// \brief Determine whether the type \p Derived is a C++ class that is
+/// derived from the type \p Base.
+bool Sema::IsDerivedFrom(QualType Derived, QualType Base, CXXBasePaths &Paths) {
+  if (!getLangOpts().CPlusPlus)
+    return false;
+  
+  CXXRecordDecl *DerivedRD = GetClassForType(Derived);
+  if (!DerivedRD)
+    return false;
+  
+  CXXRecordDecl *BaseRD = GetClassForType(Base);
+  if (!BaseRD)
+    return false;
+  
+  return DerivedRD->isDerivedFrom(BaseRD, Paths);
+}
+
+void Sema::BuildBasePathArray(const CXXBasePaths &Paths, 
+                              CXXCastPath &BasePathArray) {
+  assert(BasePathArray.empty() && "Base path array must be empty!");
+  assert(Paths.isRecordingPaths() && "Must record paths!");
+  
+  const CXXBasePath &Path = Paths.front();
+       
+  // We first go backward and check if we have a virtual base.
+  // FIXME: It would be better if CXXBasePath had the base specifier for
+  // the nearest virtual base.
+  unsigned Start = 0;
+  for (unsigned I = Path.size(); I != 0; --I) {
+    if (Path[I - 1].Base->isVirtual()) {
+      Start = I - 1;
+      break;
+    }
+  }
+
+  // Now add all bases.
+  for (unsigned I = Start, E = Path.size(); I != E; ++I)
+    BasePathArray.push_back(const_cast<CXXBaseSpecifier*>(Path[I].Base));
+}
+
+/// \brief Determine whether the given base path includes a virtual
+/// base class.
+bool Sema::BasePathInvolvesVirtualBase(const CXXCastPath &BasePath) {
+  for (CXXCastPath::const_iterator B = BasePath.begin(), 
+                                BEnd = BasePath.end();
+       B != BEnd; ++B)
+    if ((*B)->isVirtual())
+      return true;
+
+  return false;
+}
+
+/// CheckDerivedToBaseConversion - Check whether the Derived-to-Base
+/// conversion (where Derived and Base are class types) is
+/// well-formed, meaning that the conversion is unambiguous (and
+/// that all of the base classes are accessible). Returns true
+/// and emits a diagnostic if the code is ill-formed, returns false
+/// otherwise. Loc is the location where this routine should point to
+/// if there is an error, and Range is the source range to highlight
+/// if there is an error.
+bool
+Sema::CheckDerivedToBaseConversion(QualType Derived, QualType Base,
+                                   unsigned InaccessibleBaseID,
+                                   unsigned AmbigiousBaseConvID,
+                                   SourceLocation Loc, SourceRange Range,
+                                   DeclarationName Name,
+                                   CXXCastPath *BasePath) {
+  // First, determine whether the path from Derived to Base is
+  // ambiguous. This is slightly more expensive than checking whether
+  // the Derived to Base conversion exists, because here we need to
+  // explore multiple paths to determine if there is an ambiguity.
+  CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
+                     /*DetectVirtual=*/false);
+  bool DerivationOkay = IsDerivedFrom(Derived, Base, Paths);
+  assert(DerivationOkay &&
+         "Can only be used with a derived-to-base conversion");
+  (void)DerivationOkay;
+  
+  if (!Paths.isAmbiguous(Context.getCanonicalType(Base).getUnqualifiedType())) {
+    if (InaccessibleBaseID) {
+      // Check that the base class can be accessed.
+      switch (CheckBaseClassAccess(Loc, Base, Derived, Paths.front(),
+                                   InaccessibleBaseID)) {
+        case AR_inaccessible: 
+          return true;
+        case AR_accessible: 
+        case AR_dependent:
+        case AR_delayed:
+          break;
+      }
+    }
+    
+    // Build a base path if necessary.
+    if (BasePath)
+      BuildBasePathArray(Paths, *BasePath);
+    return false;
+  }
+  
+  // We know that the derived-to-base conversion is ambiguous, and
+  // we're going to produce a diagnostic. Perform the derived-to-base
+  // search just one more time to compute all of the possible paths so
+  // that we can print them out. This is more expensive than any of
+  // the previous derived-to-base checks we've done, but at this point
+  // performance isn't as much of an issue.
+  Paths.clear();
+  Paths.setRecordingPaths(true);
+  bool StillOkay = IsDerivedFrom(Derived, Base, Paths);
+  assert(StillOkay && "Can only be used with a derived-to-base conversion");
+  (void)StillOkay;
+  
+  // Build up a textual representation of the ambiguous paths, e.g.,
+  // D -> B -> A, that will be used to illustrate the ambiguous
+  // conversions in the diagnostic. We only print one of the paths
+  // to each base class subobject.
+  std::string PathDisplayStr = getAmbiguousPathsDisplayString(Paths);
+  
+  Diag(Loc, AmbigiousBaseConvID)
+  << Derived << Base << PathDisplayStr << Range << Name;
+  return true;
+}
+
+bool
+Sema::CheckDerivedToBaseConversion(QualType Derived, QualType Base,
+                                   SourceLocation Loc, SourceRange Range,
+                                   CXXCastPath *BasePath,
+                                   bool IgnoreAccess) {
+  return CheckDerivedToBaseConversion(Derived, Base,
+                                      IgnoreAccess ? 0
+                                       : diag::err_upcast_to_inaccessible_base,
+                                      diag::err_ambiguous_derived_to_base_conv,
+                                      Loc, Range, DeclarationName(), 
+                                      BasePath);
+}
+
+
+/// @brief Builds a string representing ambiguous paths from a
+/// specific derived class to different subobjects of the same base
+/// class.
+///
+/// This function builds a string that can be used in error messages
+/// to show the different paths that one can take through the
+/// inheritance hierarchy to go from the derived class to different
+/// subobjects of a base class. The result looks something like this:
+/// @code
+/// struct D -> struct B -> struct A
+/// struct D -> struct C -> struct A
+/// @endcode
+std::string Sema::getAmbiguousPathsDisplayString(CXXBasePaths &Paths) {
+  std::string PathDisplayStr;
+  std::set<unsigned> DisplayedPaths;
+  for (CXXBasePaths::paths_iterator Path = Paths.begin();
+       Path != Paths.end(); ++Path) {
+    if (DisplayedPaths.insert(Path->back().SubobjectNumber).second) {
+      // We haven't displayed a path to this particular base
+      // class subobject yet.
+      PathDisplayStr += "\n    ";
+      PathDisplayStr += Context.getTypeDeclType(Paths.getOrigin()).getAsString();
+      for (CXXBasePath::const_iterator Element = Path->begin();
+           Element != Path->end(); ++Element)
+        PathDisplayStr += " -> " + Element->Base->getType().getAsString();
+    }
+  }
+  
+  return PathDisplayStr;
+}
+
+//===----------------------------------------------------------------------===//
+// C++ class member Handling
+//===----------------------------------------------------------------------===//
+
+/// ActOnAccessSpecifier - Parsed an access specifier followed by a colon.
+bool Sema::ActOnAccessSpecifier(AccessSpecifier Access,
+                                SourceLocation ASLoc,
+                                SourceLocation ColonLoc,
+                                AttributeList *Attrs) {
+  assert(Access != AS_none && "Invalid kind for syntactic access specifier!");
+  AccessSpecDecl *ASDecl = AccessSpecDecl::Create(Context, Access, CurContext,
+                                                  ASLoc, ColonLoc);
+  CurContext->addHiddenDecl(ASDecl);
+  return ProcessAccessDeclAttributeList(ASDecl, Attrs);
+}
+
+/// CheckOverrideControl - Check C++0x override control semantics.
+void Sema::CheckOverrideControl(const Decl *D) {
+  const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(D);
+  if (!MD || !MD->isVirtual())
+    return;
+
+  if (MD->isDependentContext())
+    return;
+
+  // C++0x [class.virtual]p3:
+  //   If a virtual function is marked with the virt-specifier override and does
+  //   not override a member function of a base class, 
+  //   the program is ill-formed.
+  bool HasOverriddenMethods = 
+    MD->begin_overridden_methods() != MD->end_overridden_methods();
+  if (MD->hasAttr<OverrideAttr>() && !HasOverriddenMethods) {
+    Diag(MD->getLocation(), 
+                 diag::err_function_marked_override_not_overriding)
+      << MD->getDeclName();
+    return;
+  }
+}
+
+/// CheckIfOverriddenFunctionIsMarkedFinal - Checks whether a virtual member 
+/// function overrides a virtual member function marked 'final', according to
+/// C++0x [class.virtual]p3.
+bool Sema::CheckIfOverriddenFunctionIsMarkedFinal(const CXXMethodDecl *New,
+                                                  const CXXMethodDecl *Old) {
+  if (!Old->hasAttr<FinalAttr>())
+    return false;
+
+  Diag(New->getLocation(), diag::err_final_function_overridden)
+    << New->getDeclName();
+  Diag(Old->getLocation(), diag::note_overridden_virtual_function);
+  return true;
+}
+
+/// ActOnCXXMemberDeclarator - This is invoked when a C++ class member
+/// declarator is parsed. 'AS' is the access specifier, 'BW' specifies the
+/// bitfield width if there is one, 'InitExpr' specifies the initializer if
+/// one has been parsed, and 'HasDeferredInit' is true if an initializer is
+/// present but parsing it has been deferred.
+Decl *
+Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D,
+                               MultiTemplateParamsArg TemplateParameterLists,
+                               Expr *BW, const VirtSpecifiers &VS,
+                               bool HasDeferredInit) {
+  const DeclSpec &DS = D.getDeclSpec();
+  DeclarationNameInfo NameInfo = GetNameForDeclarator(D);
+  DeclarationName Name = NameInfo.getName();
+  SourceLocation Loc = NameInfo.getLoc();
+
+  // For anonymous bitfields, the location should point to the type.
+  if (Loc.isInvalid())
+    Loc = D.getLocStart();
+
+  Expr *BitWidth = static_cast<Expr*>(BW);
+
+  assert(isa<CXXRecordDecl>(CurContext));
+  assert(!DS.isFriendSpecified());
+
+  bool isFunc = D.isDeclarationOfFunction();
+
+  // C++ 9.2p6: A member shall not be declared to have automatic storage
+  // duration (auto, register) or with the extern storage-class-specifier.
+  // C++ 7.1.1p8: The mutable specifier can be applied only to names of class
+  // data members and cannot be applied to names declared const or static,
+  // and cannot be applied to reference members.
+  switch (DS.getStorageClassSpec()) {
+    case DeclSpec::SCS_unspecified:
+    case DeclSpec::SCS_typedef:
+    case DeclSpec::SCS_static:
+      // FALL THROUGH.
+      break;
+    case DeclSpec::SCS_mutable:
+      if (isFunc) {
+        if (DS.getStorageClassSpecLoc().isValid())
+          Diag(DS.getStorageClassSpecLoc(), diag::err_mutable_function);
+        else
+          Diag(DS.getThreadSpecLoc(), diag::err_mutable_function);
+
+        // FIXME: It would be nicer if the keyword was ignored only for this
+        // declarator. Otherwise we could get follow-up errors.
+        D.getMutableDeclSpec().ClearStorageClassSpecs();
+      }
+      break;
+    default:
+      if (DS.getStorageClassSpecLoc().isValid())
+        Diag(DS.getStorageClassSpecLoc(),
+             diag::err_storageclass_invalid_for_member);
+      else
+        Diag(DS.getThreadSpecLoc(), diag::err_storageclass_invalid_for_member);
+      D.getMutableDeclSpec().ClearStorageClassSpecs();
+  }
+
+  bool isInstField = ((DS.getStorageClassSpec() == DeclSpec::SCS_unspecified ||
+                       DS.getStorageClassSpec() == DeclSpec::SCS_mutable) &&
+                      !isFunc);
+
+  Decl *Member;
+  if (isInstField) {
+    CXXScopeSpec &SS = D.getCXXScopeSpec();
+
+    // Data members must have identifiers for names.
+    if (Name.getNameKind() != DeclarationName::Identifier) {
+      Diag(Loc, diag::err_bad_variable_name)
+        << Name;
+      return 0;
+    }
+    
+    IdentifierInfo *II = Name.getAsIdentifierInfo();
+
+    // Member field could not be with "template" keyword.
+    // So TemplateParameterLists should be empty in this case.
+    if (TemplateParameterLists.size()) {
+      TemplateParameterList* TemplateParams = TemplateParameterLists.get()[0];
+      if (TemplateParams->size()) {
+        // There is no such thing as a member field template.
+        Diag(D.getIdentifierLoc(), diag::err_template_member)
+            << II
+            << SourceRange(TemplateParams->getTemplateLoc(),
+                TemplateParams->getRAngleLoc());
+      } else {
+        // There is an extraneous 'template<>' for this member.
+        Diag(TemplateParams->getTemplateLoc(),
+            diag::err_template_member_noparams)
+            << II
+            << SourceRange(TemplateParams->getTemplateLoc(),
+                TemplateParams->getRAngleLoc());
+      }
+      return 0;
+    }
+
+    if (SS.isSet() && !SS.isInvalid()) {
+      // The user provided a superfluous scope specifier inside a class
+      // definition:
+      //
+      // class X {
+      //   int X::member;
+      // };
+      if (DeclContext *DC = computeDeclContext(SS, false))
+        diagnoseQualifiedDeclaration(SS, DC, Name, D.getIdentifierLoc());
+      else
+        Diag(D.getIdentifierLoc(), diag::err_member_qualification)
+          << Name << SS.getRange();
+      
+      SS.clear();
+    }
+
+    Member = HandleField(S, cast<CXXRecordDecl>(CurContext), Loc, D, BitWidth,
+                         HasDeferredInit, AS);
+    assert(Member && "HandleField never returns null");
+  } else {
+    assert(!HasDeferredInit);
+
+    Member = HandleDeclarator(S, D, move(TemplateParameterLists));
+    if (!Member) {
+      return 0;
+    }
+
+    // Non-instance-fields can't have a bitfield.
+    if (BitWidth) {
+      if (Member->isInvalidDecl()) {
+        // don't emit another diagnostic.
+      } else if (isa<VarDecl>(Member)) {
+        // C++ 9.6p3: A bit-field shall not be a static member.
+        // "static member 'A' cannot be a bit-field"
+        Diag(Loc, diag::err_static_not_bitfield)
+          << Name << BitWidth->getSourceRange();
+      } else if (isa<TypedefDecl>(Member)) {
+        // "typedef member 'x' cannot be a bit-field"
+        Diag(Loc, diag::err_typedef_not_bitfield)
+          << Name << BitWidth->getSourceRange();
+      } else {
+        // A function typedef ("typedef int f(); f a;").
+        // C++ 9.6p3: A bit-field shall have integral or enumeration type.
+        Diag(Loc, diag::err_not_integral_type_bitfield)
+          << Name << cast<ValueDecl>(Member)->getType()
+          << BitWidth->getSourceRange();
+      }
+
+      BitWidth = 0;
+      Member->setInvalidDecl();
+    }
+
+    Member->setAccess(AS);
+
+    // If we have declared a member function template, set the access of the
+    // templated declaration as well.
+    if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(Member))
+      FunTmpl->getTemplatedDecl()->setAccess(AS);
+  }
+
+  if (VS.isOverrideSpecified()) {
+    CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(Member);
+    if (!MD || !MD->isVirtual()) {
+      Diag(Member->getLocStart(), 
+           diag::override_keyword_only_allowed_on_virtual_member_functions)
+        << "override" << FixItHint::CreateRemoval(VS.getOverrideLoc());
+    } else
+      MD->addAttr(new (Context) OverrideAttr(VS.getOverrideLoc(), Context));
+  }
+  if (VS.isFinalSpecified()) {
+    CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(Member);
+    if (!MD || !MD->isVirtual()) {
+      Diag(Member->getLocStart(), 
+           diag::override_keyword_only_allowed_on_virtual_member_functions)
+      << "final" << FixItHint::CreateRemoval(VS.getFinalLoc());
+    } else
+      MD->addAttr(new (Context) FinalAttr(VS.getFinalLoc(), Context));
+  }
+
+  if (VS.getLastLocation().isValid()) {
+    // Update the end location of a method that has a virt-specifiers.
+    if (CXXMethodDecl *MD = dyn_cast_or_null<CXXMethodDecl>(Member))
+      MD->setRangeEnd(VS.getLastLocation());
+  }
+      
+  CheckOverrideControl(Member);
+
+  assert((Name || isInstField) && "No identifier for non-field ?");
+
+  if (isInstField)
+    FieldCollector->Add(cast<FieldDecl>(Member));
+  return Member;
+}
+
+/// ActOnCXXInClassMemberInitializer - This is invoked after parsing an
+/// in-class initializer for a non-static C++ class member, and after
+/// instantiating an in-class initializer in a class template. Such actions
+/// are deferred until the class is complete.
+void
+Sema::ActOnCXXInClassMemberInitializer(Decl *D, SourceLocation EqualLoc,
+                                       Expr *InitExpr) {
+  FieldDecl *FD = cast<FieldDecl>(D);
+
+  if (!InitExpr) {
+    FD->setInvalidDecl();
+    FD->removeInClassInitializer();
+    return;
+  }
+
+  if (DiagnoseUnexpandedParameterPack(InitExpr, UPPC_Initializer)) {
+    FD->setInvalidDecl();
+    FD->removeInClassInitializer();
+    return;
+  }
+
+  ExprResult Init = InitExpr;
+  if (!FD->getType()->isDependentType() && !InitExpr->isTypeDependent()) {
+    if (isa<InitListExpr>(InitExpr) && isStdInitializerList(FD->getType(), 0)) {
+      Diag(FD->getLocation(), diag::warn_dangling_std_initializer_list)
+        << /*at end of ctor*/1 << InitExpr->getSourceRange();
+    }
+    Expr **Inits = &InitExpr;
+    unsigned NumInits = 1;
+    InitializedEntity Entity = InitializedEntity::InitializeMember(FD);
+    InitializationKind Kind = EqualLoc.isInvalid()
+        ? InitializationKind::CreateDirectList(InitExpr->getLocStart())
+        : InitializationKind::CreateCopy(InitExpr->getLocStart(), EqualLoc);
+    InitializationSequence Seq(*this, Entity, Kind, Inits, NumInits);
+    Init = Seq.Perform(*this, Entity, Kind, MultiExprArg(Inits, NumInits));
+    if (Init.isInvalid()) {
+      FD->setInvalidDecl();
+      return;
+    }
+
+    CheckImplicitConversions(Init.get(), EqualLoc);
+  }
+
+  // C++0x [class.base.init]p7:
+  //   The initialization of each base and member constitutes a
+  //   full-expression.
+  Init = MaybeCreateExprWithCleanups(Init);
+  if (Init.isInvalid()) {
+    FD->setInvalidDecl();
+    return;
+  }
+
+  InitExpr = Init.release();
+
+  FD->setInClassInitializer(InitExpr);
+}
+
+/// \brief Find the direct and/or virtual base specifiers that
+/// correspond to the given base type, for use in base initialization
+/// within a constructor.
+static bool FindBaseInitializer(Sema &SemaRef, 
+                                CXXRecordDecl *ClassDecl,
+                                QualType BaseType,
+                                const CXXBaseSpecifier *&DirectBaseSpec,
+                                const CXXBaseSpecifier *&VirtualBaseSpec) {
+  // First, check for a direct base class.
+  DirectBaseSpec = 0;
+  for (CXXRecordDecl::base_class_const_iterator Base
+         = ClassDecl->bases_begin(); 
+       Base != ClassDecl->bases_end(); ++Base) {
+    if (SemaRef.Context.hasSameUnqualifiedType(BaseType, Base->getType())) {
+      // We found a direct base of this type. That's what we're
+      // initializing.
+      DirectBaseSpec = &*Base;
+      break;
+    }
+  }
+
+  // Check for a virtual base class.
+  // FIXME: We might be able to short-circuit this if we know in advance that
+  // there are no virtual bases.
+  VirtualBaseSpec = 0;
+  if (!DirectBaseSpec || !DirectBaseSpec->isVirtual()) {
+    // We haven't found a base yet; search the class hierarchy for a
+    // virtual base class.
+    CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
+                       /*DetectVirtual=*/false);
+    if (SemaRef.IsDerivedFrom(SemaRef.Context.getTypeDeclType(ClassDecl), 
+                              BaseType, Paths)) {
+      for (CXXBasePaths::paths_iterator Path = Paths.begin();
+           Path != Paths.end(); ++Path) {
+        if (Path->back().Base->isVirtual()) {
+          VirtualBaseSpec = Path->back().Base;
+          break;
+        }
+      }
+    }
+  }
+
+  return DirectBaseSpec || VirtualBaseSpec;
+}
+
+/// \brief Handle a C++ member initializer using braced-init-list syntax.
+MemInitResult
+Sema::ActOnMemInitializer(Decl *ConstructorD,
+                          Scope *S,
+                          CXXScopeSpec &SS,
+                          IdentifierInfo *MemberOrBase,
+                          ParsedType TemplateTypeTy,
+                          const DeclSpec &DS,
+                          SourceLocation IdLoc,
+                          Expr *InitList,
+                          SourceLocation EllipsisLoc) {
+  return BuildMemInitializer(ConstructorD, S, SS, MemberOrBase, TemplateTypeTy,
+                             DS, IdLoc, InitList,
+                             EllipsisLoc);
+}
+
+/// \brief Handle a C++ member initializer using parentheses syntax.
+MemInitResult
+Sema::ActOnMemInitializer(Decl *ConstructorD,
+                          Scope *S,
+                          CXXScopeSpec &SS,
+                          IdentifierInfo *MemberOrBase,
+                          ParsedType TemplateTypeTy,
+                          const DeclSpec &DS,
+                          SourceLocation IdLoc,
+                          SourceLocation LParenLoc,
+                          Expr **Args, unsigned NumArgs,
+                          SourceLocation RParenLoc,
+                          SourceLocation EllipsisLoc) {
+  Expr *List = new (Context) ParenListExpr(Context, LParenLoc, Args, NumArgs,
+                                           RParenLoc);
+  return BuildMemInitializer(ConstructorD, S, SS, MemberOrBase, TemplateTypeTy,
+                             DS, IdLoc, List, EllipsisLoc);
+}
+
+namespace {
+
+// Callback to only accept typo corrections that can be a valid C++ member
+// intializer: either a non-static field member or a base class.
+class MemInitializerValidatorCCC : public CorrectionCandidateCallback {
+ public:
+  explicit MemInitializerValidatorCCC(CXXRecordDecl *ClassDecl)
+      : ClassDecl(ClassDecl) {}
+
+  virtual bool ValidateCandidate(const TypoCorrection &candidate) {
+    if (NamedDecl *ND = candidate.getCorrectionDecl()) {
+      if (FieldDecl *Member = dyn_cast<FieldDecl>(ND))
+        return Member->getDeclContext()->getRedeclContext()->Equals(ClassDecl);
+      else
+        return isa<TypeDecl>(ND);
+    }
+    return false;
+  }
+
+ private:
+  CXXRecordDecl *ClassDecl;
+};
+
+}
+
+/// \brief Handle a C++ member initializer.
+MemInitResult
+Sema::BuildMemInitializer(Decl *ConstructorD,
+                          Scope *S,
+                          CXXScopeSpec &SS,
+                          IdentifierInfo *MemberOrBase,
+                          ParsedType TemplateTypeTy,
+                          const DeclSpec &DS,
+                          SourceLocation IdLoc,
+                          Expr *Init,
+                          SourceLocation EllipsisLoc) {
+  if (!ConstructorD)
+    return true;
+
+  AdjustDeclIfTemplate(ConstructorD);
+
+  CXXConstructorDecl *Constructor
+    = dyn_cast<CXXConstructorDecl>(ConstructorD);
+  if (!Constructor) {
+    // The user wrote a constructor initializer on a function that is
+    // not a C++ constructor. Ignore the error for now, because we may
+    // have more member initializers coming; we'll diagnose it just
+    // once in ActOnMemInitializers.
+    return true;
+  }
+
+  CXXRecordDecl *ClassDecl = Constructor->getParent();
+
+  // C++ [class.base.init]p2:
+  //   Names in a mem-initializer-id are looked up in the scope of the
+  //   constructor's class and, if not found in that scope, are looked
+  //   up in the scope containing the constructor's definition.
+  //   [Note: if the constructor's class contains a member with the
+  //   same name as a direct or virtual base class of the class, a
+  //   mem-initializer-id naming the member or base class and composed
+  //   of a single identifier refers to the class member. A
+  //   mem-initializer-id for the hidden base class may be specified
+  //   using a qualified name. ]
+  if (!SS.getScopeRep() && !TemplateTypeTy) {
+    // Look for a member, first.
+    DeclContext::lookup_result Result
+      = ClassDecl->lookup(MemberOrBase);
+    if (Result.first != Result.second) {
+      ValueDecl *Member;
+      if ((Member = dyn_cast<FieldDecl>(*Result.first)) ||
+          (Member = dyn_cast<IndirectFieldDecl>(*Result.first))) {
+        if (EllipsisLoc.isValid())
+          Diag(EllipsisLoc, diag::err_pack_expansion_member_init)
+            << MemberOrBase
+            << SourceRange(IdLoc, Init->getSourceRange().getEnd());
+
+        return BuildMemberInitializer(Member, Init, IdLoc);
+      }
+    }
+  }
+  // It didn't name a member, so see if it names a class.
+  QualType BaseType;
+  TypeSourceInfo *TInfo = 0;
+
+  if (TemplateTypeTy) {
+    BaseType = GetTypeFromParser(TemplateTypeTy, &TInfo);
+  } else if (DS.getTypeSpecType() == TST_decltype) {
+    BaseType = BuildDecltypeType(DS.getRepAsExpr(), DS.getTypeSpecTypeLoc());
+  } else {
+    LookupResult R(*this, MemberOrBase, IdLoc, LookupOrdinaryName);
+    LookupParsedName(R, S, &SS);
+
+    TypeDecl *TyD = R.getAsSingle<TypeDecl>();
+    if (!TyD) {
+      if (R.isAmbiguous()) return true;
+
+      // We don't want access-control diagnostics here.
+      R.suppressDiagnostics();
+
+      if (SS.isSet() && isDependentScopeSpecifier(SS)) {
+        bool NotUnknownSpecialization = false;
+        DeclContext *DC = computeDeclContext(SS, false);
+        if (CXXRecordDecl *Record = dyn_cast_or_null<CXXRecordDecl>(DC)) 
+          NotUnknownSpecialization = !Record->hasAnyDependentBases();
+
+        if (!NotUnknownSpecialization) {
+          // When the scope specifier can refer to a member of an unknown
+          // specialization, we take it as a type name.
+          BaseType = CheckTypenameType(ETK_None, SourceLocation(),
+                                       SS.getWithLocInContext(Context),
+                                       *MemberOrBase, IdLoc);
+          if (BaseType.isNull())
+            return true;
+
+          R.clear();
+          R.setLookupName(MemberOrBase);
+        }
+      }
+
+      // If no results were found, try to correct typos.
+      TypoCorrection Corr;
+      MemInitializerValidatorCCC Validator(ClassDecl);
+      if (R.empty() && BaseType.isNull() &&
+          (Corr = CorrectTypo(R.getLookupNameInfo(), R.getLookupKind(), S, &SS,
+                              Validator, ClassDecl))) {
+        std::string CorrectedStr(Corr.getAsString(getLangOpts()));
+        std::string CorrectedQuotedStr(Corr.getQuoted(getLangOpts()));
+        if (FieldDecl *Member = Corr.getCorrectionDeclAs<FieldDecl>()) {
+          // We have found a non-static data member with a similar
+          // name to what was typed; complain and initialize that
+          // member.
+          Diag(R.getNameLoc(), diag::err_mem_init_not_member_or_class_suggest)
+            << MemberOrBase << true << CorrectedQuotedStr
+            << FixItHint::CreateReplacement(R.getNameLoc(), CorrectedStr);
+          Diag(Member->getLocation(), diag::note_previous_decl)
+            << CorrectedQuotedStr;
+
+          return BuildMemberInitializer(Member, Init, IdLoc);
+        } else if (TypeDecl *Type = Corr.getCorrectionDeclAs<TypeDecl>()) {
+          const CXXBaseSpecifier *DirectBaseSpec;
+          const CXXBaseSpecifier *VirtualBaseSpec;
+          if (FindBaseInitializer(*this, ClassDecl, 
+                                  Context.getTypeDeclType(Type),
+                                  DirectBaseSpec, VirtualBaseSpec)) {
+            // We have found a direct or virtual base class with a
+            // similar name to what was typed; complain and initialize
+            // that base class.
+            Diag(R.getNameLoc(), diag::err_mem_init_not_member_or_class_suggest)
+              << MemberOrBase << false << CorrectedQuotedStr
+              << FixItHint::CreateReplacement(R.getNameLoc(), CorrectedStr);
+
+            const CXXBaseSpecifier *BaseSpec = DirectBaseSpec? DirectBaseSpec 
+                                                             : VirtualBaseSpec;
+            Diag(BaseSpec->getLocStart(),
+                 diag::note_base_class_specified_here)
+              << BaseSpec->getType()
+              << BaseSpec->getSourceRange();
+
+            TyD = Type;
+          }
+        }
+      }
+
+      if (!TyD && BaseType.isNull()) {
+        Diag(IdLoc, diag::err_mem_init_not_member_or_class)
+          << MemberOrBase << SourceRange(IdLoc,Init->getSourceRange().getEnd());
+        return true;
+      }
+    }
+
+    if (BaseType.isNull()) {
+      BaseType = Context.getTypeDeclType(TyD);
+      if (SS.isSet()) {
+        NestedNameSpecifier *Qualifier =
+          static_cast<NestedNameSpecifier*>(SS.getScopeRep());
+
+        // FIXME: preserve source range information
+        BaseType = Context.getElaboratedType(ETK_None, Qualifier, BaseType);
+      }
+    }
+  }
+
+  if (!TInfo)
+    TInfo = Context.getTrivialTypeSourceInfo(BaseType, IdLoc);
+
+  return BuildBaseInitializer(BaseType, TInfo, Init, ClassDecl, EllipsisLoc);
+}
+
+/// Checks a member initializer expression for cases where reference (or
+/// pointer) members are bound to by-value parameters (or their addresses).
+static void CheckForDanglingReferenceOrPointer(Sema &S, ValueDecl *Member,
+                                               Expr *Init,
+                                               SourceLocation IdLoc) {
+  QualType MemberTy = Member->getType();
+
+  // We only handle pointers and references currently.
+  // FIXME: Would this be relevant for ObjC object pointers? Or block pointers?
+  if (!MemberTy->isReferenceType() && !MemberTy->isPointerType())
+    return;
+
+  const bool IsPointer = MemberTy->isPointerType();
+  if (IsPointer) {
+    if (const UnaryOperator *Op
+          = dyn_cast<UnaryOperator>(Init->IgnoreParenImpCasts())) {
+      // The only case we're worried about with pointers requires taking the
+      // address.
+      if (Op->getOpcode() != UO_AddrOf)
+        return;
+
+      Init = Op->getSubExpr();
+    } else {
+      // We only handle address-of expression initializers for pointers.
+      return;
+    }
+  }
+
+  if (isa<MaterializeTemporaryExpr>(Init->IgnoreParens())) {
+    // Taking the address of a temporary will be diagnosed as a hard error.
+    if (IsPointer)
+      return;
+
+    S.Diag(Init->getExprLoc(), diag::warn_bind_ref_member_to_temporary)
+      << Member << Init->getSourceRange();
+  } else if (const DeclRefExpr *DRE
+               = dyn_cast<DeclRefExpr>(Init->IgnoreParens())) {
+    // We only warn when referring to a non-reference parameter declaration.
+    const ParmVarDecl *Parameter = dyn_cast<ParmVarDecl>(DRE->getDecl());
+    if (!Parameter || Parameter->getType()->isReferenceType())
+      return;
+
+    S.Diag(Init->getExprLoc(),
+           IsPointer ? diag::warn_init_ptr_member_to_parameter_addr
+                     : diag::warn_bind_ref_member_to_parameter)
+      << Member << Parameter << Init->getSourceRange();
+  } else {
+    // Other initializers are fine.
+    return;
+  }
+
+  S.Diag(Member->getLocation(), diag::note_ref_or_ptr_member_declared_here)
+    << (unsigned)IsPointer;
+}
+
+/// Checks an initializer expression for use of uninitialized fields, such as
+/// containing the field that is being initialized. Returns true if there is an
+/// uninitialized field was used an updates the SourceLocation parameter; false
+/// otherwise.
+static bool InitExprContainsUninitializedFields(const Stmt *S,
+                                                const ValueDecl *LhsField,
+                                                SourceLocation *L) {
+  assert(isa<FieldDecl>(LhsField) || isa<IndirectFieldDecl>(LhsField));
+
+  if (isa<CallExpr>(S)) {
+    // Do not descend into function calls or constructors, as the use
+    // of an uninitialized field may be valid. One would have to inspect
+    // the contents of the function/ctor to determine if it is safe or not.
+    // i.e. Pass-by-value is never safe, but pass-by-reference and pointers
+    // may be safe, depending on what the function/ctor does.
+    return false;
+  }
+  if (const MemberExpr *ME = dyn_cast<MemberExpr>(S)) {
+    const NamedDecl *RhsField = ME->getMemberDecl();
+
+    if (const VarDecl *VD = dyn_cast<VarDecl>(RhsField)) {
+      // The member expression points to a static data member.
+      assert(VD->isStaticDataMember() && 
+             "Member points to non-static data member!");
+      (void)VD;
+      return false;
+    }
+    
+    if (isa<EnumConstantDecl>(RhsField)) {
+      // The member expression points to an enum.
+      return false;
+    }
+
+    if (RhsField == LhsField) {
+      // Initializing a field with itself. Throw a warning.
+      // But wait; there are exceptions!
+      // Exception #1:  The field may not belong to this record.
+      // e.g. Foo(const Foo& rhs) : A(rhs.A) {}
+      const Expr *base = ME->getBase();
+      if (base != NULL && !isa<CXXThisExpr>(base->IgnoreParenCasts())) {
+        // Even though the field matches, it does not belong to this record.
+        return false;
+      }
+      // None of the exceptions triggered; return true to indicate an
+      // uninitialized field was used.
+      *L = ME->getMemberLoc();
+      return true;
+    }
+  } else if (isa<UnaryExprOrTypeTraitExpr>(S)) {
+    // sizeof/alignof doesn't reference contents, do not warn.
+    return false;
+  } else if (const UnaryOperator *UOE = dyn_cast<UnaryOperator>(S)) {
+    // address-of doesn't reference contents (the pointer may be dereferenced
+    // in the same expression but it would be rare; and weird).
+    if (UOE->getOpcode() == UO_AddrOf)
+      return false;
+  }
+  for (Stmt::const_child_range it = S->children(); it; ++it) {
+    if (!*it) {
+      // An expression such as 'member(arg ?: "")' may trigger this.
+      continue;
+    }
+    if (InitExprContainsUninitializedFields(*it, LhsField, L))
+      return true;
+  }
+  return false;
+}
+
+MemInitResult
+Sema::BuildMemberInitializer(ValueDecl *Member, Expr *Init,
+                             SourceLocation IdLoc) {
+  FieldDecl *DirectMember = dyn_cast<FieldDecl>(Member);
+  IndirectFieldDecl *IndirectMember = dyn_cast<IndirectFieldDecl>(Member);
+  assert((DirectMember || IndirectMember) &&
+         "Member must be a FieldDecl or IndirectFieldDecl");
+
+  if (DiagnoseUnexpandedParameterPack(Init, UPPC_Initializer))
+    return true;
+
+  if (Member->isInvalidDecl())
+    return true;
+
+  // Diagnose value-uses of fields to initialize themselves, e.g.
+  //   foo(foo)
+  // where foo is not also a parameter to the constructor.
+  // TODO: implement -Wuninitialized and fold this into that framework.
+  Expr **Args;
+  unsigned NumArgs;
+  if (ParenListExpr *ParenList = dyn_cast<ParenListExpr>(Init)) {
+    Args = ParenList->getExprs();
+    NumArgs = ParenList->getNumExprs();
+  } else {
+    InitListExpr *InitList = cast<InitListExpr>(Init);
+    Args = InitList->getInits();
+    NumArgs = InitList->getNumInits();
+  }
+  for (unsigned i = 0; i < NumArgs; ++i) {
+    SourceLocation L;
+    if (InitExprContainsUninitializedFields(Args[i], Member, &L)) {
+      // FIXME: Return true in the case when other fields are used before being
+      // uninitialized. For example, let this field be the i'th field. When
+      // initializing the i'th field, throw a warning if any of the >= i'th
+      // fields are used, as they are not yet initialized.
+      // Right now we are only handling the case where the i'th field uses
+      // itself in its initializer.
+      Diag(L, diag::warn_field_is_uninit);
+    }
+  }
+
+  SourceRange InitRange = Init->getSourceRange();
+
+  if (Member->getType()->isDependentType() || Init->isTypeDependent()) {
+    // Can't check initialization for a member of dependent type or when
+    // any of the arguments are type-dependent expressions.
+    DiscardCleanupsInEvaluationContext();
+  } else {
+    bool InitList = false;
+    if (isa<InitListExpr>(Init)) {
+      InitList = true;
+      Args = &Init;
+      NumArgs = 1;
+
+      if (isStdInitializerList(Member->getType(), 0)) {
+        Diag(IdLoc, diag::warn_dangling_std_initializer_list)
+            << /*at end of ctor*/1 << InitRange;
+      }
+    }
+
+    // Initialize the member.
+    InitializedEntity MemberEntity =
+      DirectMember ? InitializedEntity::InitializeMember(DirectMember, 0)
+                   : InitializedEntity::InitializeMember(IndirectMember, 0);
+    InitializationKind Kind =
+      InitList ? InitializationKind::CreateDirectList(IdLoc)
+               : InitializationKind::CreateDirect(IdLoc, InitRange.getBegin(),
+                                                  InitRange.getEnd());
+
+    InitializationSequence InitSeq(*this, MemberEntity, Kind, Args, NumArgs);
+    ExprResult MemberInit = InitSeq.Perform(*this, MemberEntity, Kind,
+                                            MultiExprArg(*this, Args, NumArgs),
+                                            0);
+    if (MemberInit.isInvalid())
+      return true;
+
+    CheckImplicitConversions(MemberInit.get(),
+                             InitRange.getBegin());
+
+    // C++0x [class.base.init]p7:
+    //   The initialization of each base and member constitutes a
+    //   full-expression.
+    MemberInit = MaybeCreateExprWithCleanups(MemberInit);
+    if (MemberInit.isInvalid())
+      return true;
+
+    // If we are in a dependent context, template instantiation will
+    // perform this type-checking again. Just save the arguments that we
+    // received.
+    // FIXME: This isn't quite ideal, since our ASTs don't capture all
+    // of the information that we have about the member
+    // initializer. However, deconstructing the ASTs is a dicey process,
+    // and this approach is far more likely to get the corner cases right.
+    if (CurContext->isDependentContext()) {
+      // The existing Init will do fine.
+    } else {
+      Init = MemberInit.get();
+      CheckForDanglingReferenceOrPointer(*this, Member, Init, IdLoc);
+    }
+  }
+
+  if (DirectMember) {
+    return new (Context) CXXCtorInitializer(Context, DirectMember, IdLoc,
+                                            InitRange.getBegin(), Init,
+                                            InitRange.getEnd());
+  } else {
+    return new (Context) CXXCtorInitializer(Context, IndirectMember, IdLoc,
+                                            InitRange.getBegin(), Init,
+                                            InitRange.getEnd());
+  }
+}
+
+MemInitResult
+Sema::BuildDelegatingInitializer(TypeSourceInfo *TInfo, Expr *Init,
+                                 CXXRecordDecl *ClassDecl) {
+  SourceLocation NameLoc = TInfo->getTypeLoc().getLocalSourceRange().getBegin();
+  if (!LangOpts.CPlusPlus0x)
+    return Diag(NameLoc, diag::err_delegating_ctor)
+      << TInfo->getTypeLoc().getLocalSourceRange();
+  Diag(NameLoc, diag::warn_cxx98_compat_delegating_ctor);
+
+  bool InitList = true;
+  Expr **Args = &Init;
+  unsigned NumArgs = 1;
+  if (ParenListExpr *ParenList = dyn_cast<ParenListExpr>(Init)) {
+    InitList = false;
+    Args = ParenList->getExprs();
+    NumArgs = ParenList->getNumExprs();
+  }
+
+  SourceRange InitRange = Init->getSourceRange();
+  // Initialize the object.
+  InitializedEntity DelegationEntity = InitializedEntity::InitializeDelegation(
+                                     QualType(ClassDecl->getTypeForDecl(), 0));
+  InitializationKind Kind =
+    InitList ? InitializationKind::CreateDirectList(NameLoc)
+             : InitializationKind::CreateDirect(NameLoc, InitRange.getBegin(),
+                                                InitRange.getEnd());
+  InitializationSequence InitSeq(*this, DelegationEntity, Kind, Args, NumArgs);
+  ExprResult DelegationInit = InitSeq.Perform(*this, DelegationEntity, Kind,
+                                              MultiExprArg(*this, Args,NumArgs),
+                                              0);
+  if (DelegationInit.isInvalid())
+    return true;
+
+  assert(cast<CXXConstructExpr>(DelegationInit.get())->getConstructor() &&
+         "Delegating constructor with no target?");
+
+  CheckImplicitConversions(DelegationInit.get(), InitRange.getBegin());
+
+  // C++0x [class.base.init]p7:
+  //   The initialization of each base and member constitutes a
+  //   full-expression.
+  DelegationInit = MaybeCreateExprWithCleanups(DelegationInit);
+  if (DelegationInit.isInvalid())
+    return true;
+
+  return new (Context) CXXCtorInitializer(Context, TInfo, InitRange.getBegin(), 
+                                          DelegationInit.takeAs<Expr>(),
+                                          InitRange.getEnd());
+}
+
+MemInitResult
+Sema::BuildBaseInitializer(QualType BaseType, TypeSourceInfo *BaseTInfo,
+                           Expr *Init, CXXRecordDecl *ClassDecl,
+                           SourceLocation EllipsisLoc) {
+  SourceLocation BaseLoc
+    = BaseTInfo->getTypeLoc().getLocalSourceRange().getBegin();
+
+  if (!BaseType->isDependentType() && !BaseType->isRecordType())
+    return Diag(BaseLoc, diag::err_base_init_does_not_name_class)
+             << BaseType << BaseTInfo->getTypeLoc().getLocalSourceRange();
+
+  // C++ [class.base.init]p2:
+  //   [...] Unless the mem-initializer-id names a nonstatic data
+  //   member of the constructor's class or a direct or virtual base
+  //   of that class, the mem-initializer is ill-formed. A
+  //   mem-initializer-list can initialize a base class using any
+  //   name that denotes that base class type.
+  bool Dependent = BaseType->isDependentType() || Init->isTypeDependent();
+
+  SourceRange InitRange = Init->getSourceRange();
+  if (EllipsisLoc.isValid()) {
+    // This is a pack expansion.
+    if (!BaseType->containsUnexpandedParameterPack())  {
+      Diag(EllipsisLoc, diag::err_pack_expansion_without_parameter_packs)
+        << SourceRange(BaseLoc, InitRange.getEnd());
+
+      EllipsisLoc = SourceLocation();
+    }
+  } else {
+    // Check for any unexpanded parameter packs.
+    if (DiagnoseUnexpandedParameterPack(BaseLoc, BaseTInfo, UPPC_Initializer))
+      return true;
+
+    if (DiagnoseUnexpandedParameterPack(Init, UPPC_Initializer))
+      return true;
+  }
+
+  // Check for direct and virtual base classes.
+  const CXXBaseSpecifier *DirectBaseSpec = 0;
+  const CXXBaseSpecifier *VirtualBaseSpec = 0;
+  if (!Dependent) { 
+    if (Context.hasSameUnqualifiedType(QualType(ClassDecl->getTypeForDecl(),0),
+                                       BaseType))
+      return BuildDelegatingInitializer(BaseTInfo, Init, ClassDecl);
+
+    FindBaseInitializer(*this, ClassDecl, BaseType, DirectBaseSpec, 
+                        VirtualBaseSpec);
+
+    // C++ [base.class.init]p2:
+    // Unless the mem-initializer-id names a nonstatic data member of the
+    // constructor's class or a direct or virtual base of that class, the
+    // mem-initializer is ill-formed.
+    if (!DirectBaseSpec && !VirtualBaseSpec) {
+      // If the class has any dependent bases, then it's possible that
+      // one of those types will resolve to the same type as
+      // BaseType. Therefore, just treat this as a dependent base
+      // class initialization.  FIXME: Should we try to check the
+      // initialization anyway? It seems odd.
+      if (ClassDecl->hasAnyDependentBases())
+        Dependent = true;
+      else
+        return Diag(BaseLoc, diag::err_not_direct_base_or_virtual)
+          << BaseType << Context.getTypeDeclType(ClassDecl)
+          << BaseTInfo->getTypeLoc().getLocalSourceRange();
+    }
+  }
+
+  if (Dependent) {
+    DiscardCleanupsInEvaluationContext();
+
+    return new (Context) CXXCtorInitializer(Context, BaseTInfo,
+                                            /*IsVirtual=*/false,
+                                            InitRange.getBegin(), Init,
+                                            InitRange.getEnd(), EllipsisLoc);
+  }
+
+  // C++ [base.class.init]p2:
+  //   If a mem-initializer-id is ambiguous because it designates both
+  //   a direct non-virtual base class and an inherited virtual base
+  //   class, the mem-initializer is ill-formed.
+  if (DirectBaseSpec && VirtualBaseSpec)
+    return Diag(BaseLoc, diag::err_base_init_direct_and_virtual)
+      << BaseType << BaseTInfo->getTypeLoc().getLocalSourceRange();
+
+  CXXBaseSpecifier *BaseSpec = const_cast<CXXBaseSpecifier *>(DirectBaseSpec);
+  if (!BaseSpec)
+    BaseSpec = const_cast<CXXBaseSpecifier *>(VirtualBaseSpec);
+
+  // Initialize the base.
+  bool InitList = true;
+  Expr **Args = &Init;
+  unsigned NumArgs = 1;
+  if (ParenListExpr *ParenList = dyn_cast<ParenListExpr>(Init)) {
+    InitList = false;
+    Args = ParenList->getExprs();
+    NumArgs = ParenList->getNumExprs();
+  }
+
+  InitializedEntity BaseEntity =
+    InitializedEntity::InitializeBase(Context, BaseSpec, VirtualBaseSpec);
+  InitializationKind Kind =
+    InitList ? InitializationKind::CreateDirectList(BaseLoc)
+             : InitializationKind::CreateDirect(BaseLoc, InitRange.getBegin(),
+                                                InitRange.getEnd());
+  InitializationSequence InitSeq(*this, BaseEntity, Kind, Args, NumArgs);
+  ExprResult BaseInit = InitSeq.Perform(*this, BaseEntity, Kind,
+                                          MultiExprArg(*this, Args, NumArgs),
+                                          0);
+  if (BaseInit.isInvalid())
+    return true;
+
+  CheckImplicitConversions(BaseInit.get(), InitRange.getBegin());
+
+  // C++0x [class.base.init]p7:
+  //   The initialization of each base and member constitutes a 
+  //   full-expression.
+  BaseInit = MaybeCreateExprWithCleanups(BaseInit);
+  if (BaseInit.isInvalid())
+    return true;
+
+  // If we are in a dependent context, template instantiation will
+  // perform this type-checking again. Just save the arguments that we
+  // received in a ParenListExpr.
+  // FIXME: This isn't quite ideal, since our ASTs don't capture all
+  // of the information that we have about the base
+  // initializer. However, deconstructing the ASTs is a dicey process,
+  // and this approach is far more likely to get the corner cases right.
+  if (CurContext->isDependentContext())
+    BaseInit = Owned(Init);
+
+  return new (Context) CXXCtorInitializer(Context, BaseTInfo,
+                                          BaseSpec->isVirtual(),
+                                          InitRange.getBegin(),
+                                          BaseInit.takeAs<Expr>(),
+                                          InitRange.getEnd(), EllipsisLoc);
+}
+
+// Create a static_cast\<T&&>(expr).
+static Expr *CastForMoving(Sema &SemaRef, Expr *E) {
+  QualType ExprType = E->getType();
+  QualType TargetType = SemaRef.Context.getRValueReferenceType(ExprType);
+  SourceLocation ExprLoc = E->getLocStart();
+  TypeSourceInfo *TargetLoc = SemaRef.Context.getTrivialTypeSourceInfo(
+      TargetType, ExprLoc);
+
+  return SemaRef.BuildCXXNamedCast(ExprLoc, tok::kw_static_cast, TargetLoc, E,
+                                   SourceRange(ExprLoc, ExprLoc),
+                                   E->getSourceRange()).take();
+}
+
+/// ImplicitInitializerKind - How an implicit base or member initializer should
+/// initialize its base or member.
+enum ImplicitInitializerKind {
+  IIK_Default,
+  IIK_Copy,
+  IIK_Move
+};
+
+static bool
+BuildImplicitBaseInitializer(Sema &SemaRef, CXXConstructorDecl *Constructor,
+                             ImplicitInitializerKind ImplicitInitKind,
+                             CXXBaseSpecifier *BaseSpec,
+                             bool IsInheritedVirtualBase,
+                             CXXCtorInitializer *&CXXBaseInit) {
+  InitializedEntity InitEntity
+    = InitializedEntity::InitializeBase(SemaRef.Context, BaseSpec,
+                                        IsInheritedVirtualBase);
+
+  ExprResult BaseInit;
+  
+  switch (ImplicitInitKind) {
+  case IIK_Default: {
+    InitializationKind InitKind
+      = InitializationKind::CreateDefault(Constructor->getLocation());
+    InitializationSequence InitSeq(SemaRef, InitEntity, InitKind, 0, 0);
+    BaseInit = InitSeq.Perform(SemaRef, InitEntity, InitKind,
+                               MultiExprArg(SemaRef, 0, 0));
+    break;
+  }
+
+  case IIK_Move:
+  case IIK_Copy: {
+    bool Moving = ImplicitInitKind == IIK_Move;
+    ParmVarDecl *Param = Constructor->getParamDecl(0);
+    QualType ParamType = Param->getType().getNonReferenceType();
+
+    Expr *CopyCtorArg = 
+      DeclRefExpr::Create(SemaRef.Context, NestedNameSpecifierLoc(),
+                          SourceLocation(), Param, false,
+                          Constructor->getLocation(), ParamType,
+                          VK_LValue, 0);
+
+    SemaRef.MarkDeclRefReferenced(cast<DeclRefExpr>(CopyCtorArg));
+
+    // Cast to the base class to avoid ambiguities.
+    QualType ArgTy = 
+      SemaRef.Context.getQualifiedType(BaseSpec->getType().getUnqualifiedType(), 
+                                       ParamType.getQualifiers());
+
+    if (Moving) {
+      CopyCtorArg = CastForMoving(SemaRef, CopyCtorArg);
+    }
+
+    CXXCastPath BasePath;
+    BasePath.push_back(BaseSpec);
+    CopyCtorArg = SemaRef.ImpCastExprToType(CopyCtorArg, ArgTy,
+                                            CK_UncheckedDerivedToBase,
+                                            Moving ? VK_XValue : VK_LValue,
+                                            &BasePath).take();
+
+    InitializationKind InitKind
+      = InitializationKind::CreateDirect(Constructor->getLocation(),
+                                         SourceLocation(), SourceLocation());
+    InitializationSequence InitSeq(SemaRef, InitEntity, InitKind, 
+                                   &CopyCtorArg, 1);
+    BaseInit = InitSeq.Perform(SemaRef, InitEntity, InitKind,
+                               MultiExprArg(&CopyCtorArg, 1));
+    break;
+  }
+  }
+
+  BaseInit = SemaRef.MaybeCreateExprWithCleanups(BaseInit);
+  if (BaseInit.isInvalid())
+    return true;
+        
+  CXXBaseInit =
+    new (SemaRef.Context) CXXCtorInitializer(SemaRef.Context,
+               SemaRef.Context.getTrivialTypeSourceInfo(BaseSpec->getType(), 
+                                                        SourceLocation()),
+                                             BaseSpec->isVirtual(),
+                                             SourceLocation(),
+                                             BaseInit.takeAs<Expr>(),
+                                             SourceLocation(),
+                                             SourceLocation());
+
+  return false;
+}
+
+static bool RefersToRValueRef(Expr *MemRef) {
+  ValueDecl *Referenced = cast<MemberExpr>(MemRef)->getMemberDecl();
+  return Referenced->getType()->isRValueReferenceType();
+}
+
+static bool
+BuildImplicitMemberInitializer(Sema &SemaRef, CXXConstructorDecl *Constructor,
+                               ImplicitInitializerKind ImplicitInitKind,
+                               FieldDecl *Field, IndirectFieldDecl *Indirect,
+                               CXXCtorInitializer *&CXXMemberInit) {
+  if (Field->isInvalidDecl())
+    return true;
+
+  SourceLocation Loc = Constructor->getLocation();
+
+  if (ImplicitInitKind == IIK_Copy || ImplicitInitKind == IIK_Move) {
+    bool Moving = ImplicitInitKind == IIK_Move;
+    ParmVarDecl *Param = Constructor->getParamDecl(0);
+    QualType ParamType = Param->getType().getNonReferenceType();
+
+    // Suppress copying zero-width bitfields.
+    if (Field->isBitField() && Field->getBitWidthValue(SemaRef.Context) == 0)
+      return false;
+        
+    Expr *MemberExprBase = 
+      DeclRefExpr::Create(SemaRef.Context, NestedNameSpecifierLoc(),
+                          SourceLocation(), Param, false,
+                          Loc, ParamType, VK_LValue, 0);
+
+    SemaRef.MarkDeclRefReferenced(cast<DeclRefExpr>(MemberExprBase));
+
+    if (Moving) {
+      MemberExprBase = CastForMoving(SemaRef, MemberExprBase);
+    }
+
+    // Build a reference to this field within the parameter.
+    CXXScopeSpec SS;
+    LookupResult MemberLookup(SemaRef, Field->getDeclName(), Loc,
+                              Sema::LookupMemberName);
+    MemberLookup.addDecl(Indirect ? cast<ValueDecl>(Indirect)
+                                  : cast<ValueDecl>(Field), AS_public);
+    MemberLookup.resolveKind();
+    ExprResult CtorArg 
+      = SemaRef.BuildMemberReferenceExpr(MemberExprBase,
+                                         ParamType, Loc,
+                                         /*IsArrow=*/false,
+                                         SS,
+                                         /*TemplateKWLoc=*/SourceLocation(),
+                                         /*FirstQualifierInScope=*/0,
+                                         MemberLookup,
+                                         /*TemplateArgs=*/0);    
+    if (CtorArg.isInvalid())
+      return true;
+
+    // C++11 [class.copy]p15:
+    //   - if a member m has rvalue reference type T&&, it is direct-initialized
+    //     with static_cast<T&&>(x.m);
+    if (RefersToRValueRef(CtorArg.get())) {
+      CtorArg = CastForMoving(SemaRef, CtorArg.take());
+    }
+
+    // When the field we are copying is an array, create index variables for 
+    // each dimension of the array. We use these index variables to subscript
+    // the source array, and other clients (e.g., CodeGen) will perform the
+    // necessary iteration with these index variables.
+    SmallVector<VarDecl *, 4> IndexVariables;
+    QualType BaseType = Field->getType();
+    QualType SizeType = SemaRef.Context.getSizeType();
+    bool InitializingArray = false;
+    while (const ConstantArrayType *Array
+                          = SemaRef.Context.getAsConstantArrayType(BaseType)) {
+      InitializingArray = true;
+      // Create the iteration variable for this array index.
+      IdentifierInfo *IterationVarName = 0;
+      {
+        SmallString<8> Str;
+        llvm::raw_svector_ostream OS(Str);
+        OS << "__i" << IndexVariables.size();
+        IterationVarName = &SemaRef.Context.Idents.get(OS.str());
+      }
+      VarDecl *IterationVar
+        = VarDecl::Create(SemaRef.Context, SemaRef.CurContext, Loc, Loc,
+                          IterationVarName, SizeType,
+                        SemaRef.Context.getTrivialTypeSourceInfo(SizeType, Loc),
+                          SC_None, SC_None);
+      IndexVariables.push_back(IterationVar);
+      
+      // Create a reference to the iteration variable.
+      ExprResult IterationVarRef
+        = SemaRef.BuildDeclRefExpr(IterationVar, SizeType, VK_LValue, Loc);
+      assert(!IterationVarRef.isInvalid() &&
+             "Reference to invented variable cannot fail!");
+      IterationVarRef = SemaRef.DefaultLvalueConversion(IterationVarRef.take());
+      assert(!IterationVarRef.isInvalid() &&
+             "Conversion of invented variable cannot fail!");
+
+      // Subscript the array with this iteration variable.
+      CtorArg = SemaRef.CreateBuiltinArraySubscriptExpr(CtorArg.take(), Loc,
+                                                        IterationVarRef.take(),
+                                                        Loc);
+      if (CtorArg.isInvalid())
+        return true;
+
+      BaseType = Array->getElementType();
+    }
+
+    // The array subscript expression is an lvalue, which is wrong for moving.
+    if (Moving && InitializingArray)
+      CtorArg = CastForMoving(SemaRef, CtorArg.take());
+
+    // Construct the entity that we will be initializing. For an array, this
+    // will be first element in the array, which may require several levels
+    // of array-subscript entities. 
+    SmallVector<InitializedEntity, 4> Entities;
+    Entities.reserve(1 + IndexVariables.size());
+    if (Indirect)
+      Entities.push_back(InitializedEntity::InitializeMember(Indirect));
+    else
+      Entities.push_back(InitializedEntity::InitializeMember(Field));
+    for (unsigned I = 0, N = IndexVariables.size(); I != N; ++I)
+      Entities.push_back(InitializedEntity::InitializeElement(SemaRef.Context,
+                                                              0,
+                                                              Entities.back()));
+    
+    // Direct-initialize to use the copy constructor.
+    InitializationKind InitKind =
+      InitializationKind::CreateDirect(Loc, SourceLocation(), SourceLocation());
+    
+    Expr *CtorArgE = CtorArg.takeAs<Expr>();
+    InitializationSequence InitSeq(SemaRef, Entities.back(), InitKind,
+                                   &CtorArgE, 1);
+    
+    ExprResult MemberInit
+      = InitSeq.Perform(SemaRef, Entities.back(), InitKind, 
+                        MultiExprArg(&CtorArgE, 1));
+    MemberInit = SemaRef.MaybeCreateExprWithCleanups(MemberInit);
+    if (MemberInit.isInvalid())
+      return true;
+
+    if (Indirect) {
+      assert(IndexVariables.size() == 0 && 
+             "Indirect field improperly initialized");
+      CXXMemberInit
+        = new (SemaRef.Context) CXXCtorInitializer(SemaRef.Context, Indirect, 
+                                                   Loc, Loc, 
+                                                   MemberInit.takeAs<Expr>(), 
+                                                   Loc);
+    } else
+      CXXMemberInit = CXXCtorInitializer::Create(SemaRef.Context, Field, Loc, 
+                                                 Loc, MemberInit.takeAs<Expr>(), 
+                                                 Loc,
+                                                 IndexVariables.data(),
+                                                 IndexVariables.size());
+    return false;
+  }
+
+  assert(ImplicitInitKind == IIK_Default && "Unhandled implicit init kind!");
+
+  QualType FieldBaseElementType = 
+    SemaRef.Context.getBaseElementType(Field->getType());
+  
+  if (FieldBaseElementType->isRecordType()) {
+    InitializedEntity InitEntity 
+      = Indirect? InitializedEntity::InitializeMember(Indirect)
+                : InitializedEntity::InitializeMember(Field);
+    InitializationKind InitKind = 
+      InitializationKind::CreateDefault(Loc);
+    
+    InitializationSequence InitSeq(SemaRef, InitEntity, InitKind, 0, 0);
+    ExprResult MemberInit = 
+      InitSeq.Perform(SemaRef, InitEntity, InitKind, MultiExprArg());
+
+    MemberInit = SemaRef.MaybeCreateExprWithCleanups(MemberInit);
+    if (MemberInit.isInvalid())
+      return true;
+    
+    if (Indirect)
+      CXXMemberInit = new (SemaRef.Context) CXXCtorInitializer(SemaRef.Context,
+                                                               Indirect, Loc, 
+                                                               Loc,
+                                                               MemberInit.get(),
+                                                               Loc);
+    else
+      CXXMemberInit = new (SemaRef.Context) CXXCtorInitializer(SemaRef.Context,
+                                                               Field, Loc, Loc,
+                                                               MemberInit.get(),
+                                                               Loc);
+    return false;
+  }
+
+  if (!Field->getParent()->isUnion()) {
+    if (FieldBaseElementType->isReferenceType()) {
+      SemaRef.Diag(Constructor->getLocation(), 
+                   diag::err_uninitialized_member_in_ctor)
+      << (int)Constructor->isImplicit() 
+      << SemaRef.Context.getTagDeclType(Constructor->getParent())
+      << 0 << Field->getDeclName();
+      SemaRef.Diag(Field->getLocation(), diag::note_declared_at);
+      return true;
+    }
+
+    if (FieldBaseElementType.isConstQualified()) {
+      SemaRef.Diag(Constructor->getLocation(), 
+                   diag::err_uninitialized_member_in_ctor)
+      << (int)Constructor->isImplicit() 
+      << SemaRef.Context.getTagDeclType(Constructor->getParent())
+      << 1 << Field->getDeclName();
+      SemaRef.Diag(Field->getLocation(), diag::note_declared_at);
+      return true;
+    }
+  }
+  
+  if (SemaRef.getLangOpts().ObjCAutoRefCount &&
+      FieldBaseElementType->isObjCRetainableType() &&
+      FieldBaseElementType.getObjCLifetime() != Qualifiers::OCL_None &&
+      FieldBaseElementType.getObjCLifetime() != Qualifiers::OCL_ExplicitNone) {
+    // Instant objects:
+    //   Default-initialize Objective-C pointers to NULL.
+    CXXMemberInit
+      = new (SemaRef.Context) CXXCtorInitializer(SemaRef.Context, Field, 
+                                                 Loc, Loc, 
+                 new (SemaRef.Context) ImplicitValueInitExpr(Field->getType()), 
+                                                 Loc);
+    return false;
+  }
+      
+  // Nothing to initialize.
+  CXXMemberInit = 0;
+  return false;
+}
+
+namespace {
+struct BaseAndFieldInfo {
+  Sema &S;
+  CXXConstructorDecl *Ctor;
+  bool AnyErrorsInInits;
+  ImplicitInitializerKind IIK;
+  llvm::DenseMap<const void *, CXXCtorInitializer*> AllBaseFields;
+  SmallVector<CXXCtorInitializer*, 8> AllToInit;
+
+  BaseAndFieldInfo(Sema &S, CXXConstructorDecl *Ctor, bool ErrorsInInits)
+    : S(S), Ctor(Ctor), AnyErrorsInInits(ErrorsInInits) {
+    bool Generated = Ctor->isImplicit() || Ctor->isDefaulted();
+    if (Generated && Ctor->isCopyConstructor())
+      IIK = IIK_Copy;
+    else if (Generated && Ctor->isMoveConstructor())
+      IIK = IIK_Move;
+    else
+      IIK = IIK_Default;
+  }
+  
+  bool isImplicitCopyOrMove() const {
+    switch (IIK) {
+    case IIK_Copy:
+    case IIK_Move:
+      return true;
+      
+    case IIK_Default:
+      return false;
+    }
+
+    llvm_unreachable("Invalid ImplicitInitializerKind!");
+  }
+};
+}
+
+/// \brief Determine whether the given indirect field declaration is somewhere
+/// within an anonymous union.
+static bool isWithinAnonymousUnion(IndirectFieldDecl *F) {
+  for (IndirectFieldDecl::chain_iterator C = F->chain_begin(), 
+                                      CEnd = F->chain_end();
+       C != CEnd; ++C)
+    if (CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>((*C)->getDeclContext()))
+      if (Record->isUnion())
+        return true;
+        
+  return false;
+}
+
+/// \brief Determine whether the given type is an incomplete or zero-lenfgth
+/// array type.
+static bool isIncompleteOrZeroLengthArrayType(ASTContext &Context, QualType T) {
+  if (T->isIncompleteArrayType())
+    return true;
+  
+  while (const ConstantArrayType *ArrayT = Context.getAsConstantArrayType(T)) {
+    if (!ArrayT->getSize())
+      return true;
+    
+    T = ArrayT->getElementType();
+  }
+  
+  return false;
+}
+
+static bool CollectFieldInitializer(Sema &SemaRef, BaseAndFieldInfo &Info,
+                                    FieldDecl *Field, 
+                                    IndirectFieldDecl *Indirect = 0) {
+
+  // Overwhelmingly common case: we have a direct initializer for this field.
+  if (CXXCtorInitializer *Init = Info.AllBaseFields.lookup(Field)) {
+    Info.AllToInit.push_back(Init);
+    return false;
+  }
+
+  // C++0x [class.base.init]p8: if the entity is a non-static data member that
+  // has a brace-or-equal-initializer, the entity is initialized as specified
+  // in [dcl.init].
+  if (Field->hasInClassInitializer() && !Info.isImplicitCopyOrMove()) {
+    CXXCtorInitializer *Init;
+    if (Indirect)
+      Init = new (SemaRef.Context) CXXCtorInitializer(SemaRef.Context, Indirect,
+                                                      SourceLocation(),
+                                                      SourceLocation(), 0,
+                                                      SourceLocation());
+    else
+      Init = new (SemaRef.Context) CXXCtorInitializer(SemaRef.Context, Field,
+                                                      SourceLocation(),
+                                                      SourceLocation(), 0,
+                                                      SourceLocation());
+    Info.AllToInit.push_back(Init);
+    return false;
+  }
+
+  // Don't build an implicit initializer for union members if none was
+  // explicitly specified.
+  if (Field->getParent()->isUnion() ||
+      (Indirect && isWithinAnonymousUnion(Indirect)))
+    return false;
+
+  // Don't initialize incomplete or zero-length arrays.
+  if (isIncompleteOrZeroLengthArrayType(SemaRef.Context, Field->getType()))
+    return false;
+
+  // Don't try to build an implicit initializer if there were semantic
+  // errors in any of the initializers (and therefore we might be
+  // missing some that the user actually wrote).
+  if (Info.AnyErrorsInInits || Field->isInvalidDecl())
+    return false;
+
+  CXXCtorInitializer *Init = 0;
+  if (BuildImplicitMemberInitializer(Info.S, Info.Ctor, Info.IIK, Field,
+                                     Indirect, Init))
+    return true;
+
+  if (Init)
+    Info.AllToInit.push_back(Init);
+
+  return false;
+}
+
+bool
+Sema::SetDelegatingInitializer(CXXConstructorDecl *Constructor,
+                               CXXCtorInitializer *Initializer) {
+  assert(Initializer->isDelegatingInitializer());
+  Constructor->setNumCtorInitializers(1);
+  CXXCtorInitializer **initializer =
+    new (Context) CXXCtorInitializer*[1];
+  memcpy(initializer, &Initializer, sizeof (CXXCtorInitializer*));
+  Constructor->setCtorInitializers(initializer);
+
+  if (CXXDestructorDecl *Dtor = LookupDestructor(Constructor->getParent())) {
+    MarkFunctionReferenced(Initializer->getSourceLocation(), Dtor);
+    DiagnoseUseOfDecl(Dtor, Initializer->getSourceLocation());
+  }
+
+  DelegatingCtorDecls.push_back(Constructor);
+
+  return false;
+}
+
+bool Sema::SetCtorInitializers(CXXConstructorDecl *Constructor,
+                               CXXCtorInitializer **Initializers,
+                               unsigned NumInitializers,
+                               bool AnyErrors) {
+  if (Constructor->isDependentContext()) {
+    // Just store the initializers as written, they will be checked during
+    // instantiation.
+    if (NumInitializers > 0) {
+      Constructor->setNumCtorInitializers(NumInitializers);
+      CXXCtorInitializer **baseOrMemberInitializers =
+        new (Context) CXXCtorInitializer*[NumInitializers];
+      memcpy(baseOrMemberInitializers, Initializers,
+             NumInitializers * sizeof(CXXCtorInitializer*));
+      Constructor->setCtorInitializers(baseOrMemberInitializers);
+    }
+    
+    return false;
+  }
+
+  BaseAndFieldInfo Info(*this, Constructor, AnyErrors);
+
+  // We need to build the initializer AST according to order of construction
+  // and not what user specified in the Initializers list.
+  CXXRecordDecl *ClassDecl = Constructor->getParent()->getDefinition();
+  if (!ClassDecl)
+    return true;
+  
+  bool HadError = false;
+
+  for (unsigned i = 0; i < NumInitializers; i++) {
+    CXXCtorInitializer *Member = Initializers[i];
+    
+    if (Member->isBaseInitializer())
+      Info.AllBaseFields[Member->getBaseClass()->getAs<RecordType>()] = Member;
+    else
+      Info.AllBaseFields[Member->getAnyMember()] = Member;
+  }
+
+  // Keep track of the direct virtual bases.
+  llvm::SmallPtrSet<CXXBaseSpecifier *, 16> DirectVBases;
+  for (CXXRecordDecl::base_class_iterator I = ClassDecl->bases_begin(),
+       E = ClassDecl->bases_end(); I != E; ++I) {
+    if (I->isVirtual())
+      DirectVBases.insert(I);
+  }
+
+  // Push virtual bases before others.
+  for (CXXRecordDecl::base_class_iterator VBase = ClassDecl->vbases_begin(),
+       E = ClassDecl->vbases_end(); VBase != E; ++VBase) {
+
+    if (CXXCtorInitializer *Value
+        = Info.AllBaseFields.lookup(VBase->getType()->getAs<RecordType>())) {
+      Info.AllToInit.push_back(Value);
+    } else if (!AnyErrors) {
+      bool IsInheritedVirtualBase = !DirectVBases.count(VBase);
+      CXXCtorInitializer *CXXBaseInit;
+      if (BuildImplicitBaseInitializer(*this, Constructor, Info.IIK,
+                                       VBase, IsInheritedVirtualBase, 
+                                       CXXBaseInit)) {
+        HadError = true;
+        continue;
+      }
+
+      Info.AllToInit.push_back(CXXBaseInit);
+    }
+  }
+
+  // Non-virtual bases.
+  for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin(),
+       E = ClassDecl->bases_end(); Base != E; ++Base) {
+    // Virtuals are in the virtual base list and already constructed.
+    if (Base->isVirtual())
+      continue;
+
+    if (CXXCtorInitializer *Value
+          = Info.AllBaseFields.lookup(Base->getType()->getAs<RecordType>())) {
+      Info.AllToInit.push_back(Value);
+    } else if (!AnyErrors) {
+      CXXCtorInitializer *CXXBaseInit;
+      if (BuildImplicitBaseInitializer(*this, Constructor, Info.IIK,
+                                       Base, /*IsInheritedVirtualBase=*/false,
+                                       CXXBaseInit)) {
+        HadError = true;
+        continue;
+      }
+
+      Info.AllToInit.push_back(CXXBaseInit);
+    }
+  }
+
+  // Fields.
+  for (DeclContext::decl_iterator Mem = ClassDecl->decls_begin(),
+                               MemEnd = ClassDecl->decls_end();
+       Mem != MemEnd; ++Mem) {
+    if (FieldDecl *F = dyn_cast<FieldDecl>(*Mem)) {
+      // C++ [class.bit]p2:
+      //   A declaration for a bit-field that omits the identifier declares an
+      //   unnamed bit-field. Unnamed bit-fields are not members and cannot be
+      //   initialized.
+      if (F->isUnnamedBitfield())
+        continue;
+            
+      // If we're not generating the implicit copy/move constructor, then we'll
+      // handle anonymous struct/union fields based on their individual
+      // indirect fields.
+      if (F->isAnonymousStructOrUnion() && Info.IIK == IIK_Default)
+        continue;
+          
+      if (CollectFieldInitializer(*this, Info, F))
+        HadError = true;
+      continue;
+    }
+    
+    // Beyond this point, we only consider default initialization.
+    if (Info.IIK != IIK_Default)
+      continue;
+    
+    if (IndirectFieldDecl *F = dyn_cast<IndirectFieldDecl>(*Mem)) {
+      if (F->getType()->isIncompleteArrayType()) {
+        assert(ClassDecl->hasFlexibleArrayMember() &&
+               "Incomplete array type is not valid");
+        continue;
+      }
+      
+      // Initialize each field of an anonymous struct individually.
+      if (CollectFieldInitializer(*this, Info, F->getAnonField(), F))
+        HadError = true;
+      
+      continue;        
+    }
+  }
+
+  NumInitializers = Info.AllToInit.size();
+  if (NumInitializers > 0) {
+    Constructor->setNumCtorInitializers(NumInitializers);
+    CXXCtorInitializer **baseOrMemberInitializers =
+      new (Context) CXXCtorInitializer*[NumInitializers];
+    memcpy(baseOrMemberInitializers, Info.AllToInit.data(),
+           NumInitializers * sizeof(CXXCtorInitializer*));
+    Constructor->setCtorInitializers(baseOrMemberInitializers);
+
+    // Constructors implicitly reference the base and member
+    // destructors.
+    MarkBaseAndMemberDestructorsReferenced(Constructor->getLocation(),
+                                           Constructor->getParent());
+  }
+
+  return HadError;
+}
+
+static void *GetKeyForTopLevelField(FieldDecl *Field) {
+  // For anonymous unions, use the class declaration as the key.
+  if (const RecordType *RT = Field->getType()->getAs<RecordType>()) {
+    if (RT->getDecl()->isAnonymousStructOrUnion())
+      return static_cast<void *>(RT->getDecl());
+  }
+  return static_cast<void *>(Field);
+}
+
+static void *GetKeyForBase(ASTContext &Context, QualType BaseType) {
+  return const_cast<Type*>(Context.getCanonicalType(BaseType).getTypePtr());
+}
+
+static void *GetKeyForMember(ASTContext &Context,
+                             CXXCtorInitializer *Member) {
+  if (!Member->isAnyMemberInitializer())
+    return GetKeyForBase(Context, QualType(Member->getBaseClass(), 0));
+    
+  // For fields injected into the class via declaration of an anonymous union,
+  // use its anonymous union class declaration as the unique key.
+  FieldDecl *Field = Member->getAnyMember();
+ 
+  // If the field is a member of an anonymous struct or union, our key
+  // is the anonymous record decl that's a direct child of the class.
+  RecordDecl *RD = Field->getParent();
+  if (RD->isAnonymousStructOrUnion()) {
+    while (true) {
+      RecordDecl *Parent = cast<RecordDecl>(RD->getDeclContext());
+      if (Parent->isAnonymousStructOrUnion())
+        RD = Parent;
+      else
+        break;
+    }
+      
+    return static_cast<void *>(RD);
+  }
+
+  return static_cast<void *>(Field);
+}
+
+static void
+DiagnoseBaseOrMemInitializerOrder(Sema &SemaRef,
+                                  const CXXConstructorDecl *Constructor,
+                                  CXXCtorInitializer **Inits,
+                                  unsigned NumInits) {
+  if (Constructor->getDeclContext()->isDependentContext())
+    return;
+
+  // Don't check initializers order unless the warning is enabled at the
+  // location of at least one initializer. 
+  bool ShouldCheckOrder = false;
+  for (unsigned InitIndex = 0; InitIndex != NumInits; ++InitIndex) {
+    CXXCtorInitializer *Init = Inits[InitIndex];
+    if (SemaRef.Diags.getDiagnosticLevel(diag::warn_initializer_out_of_order,
+                                         Init->getSourceLocation())
+          != DiagnosticsEngine::Ignored) {
+      ShouldCheckOrder = true;
+      break;
+    }
+  }
+  if (!ShouldCheckOrder)
+    return;
+  
+  // Build the list of bases and members in the order that they'll
+  // actually be initialized.  The explicit initializers should be in
+  // this same order but may be missing things.
+  SmallVector<const void*, 32> IdealInitKeys;
+
+  const CXXRecordDecl *ClassDecl = Constructor->getParent();
+
+  // 1. Virtual bases.
+  for (CXXRecordDecl::base_class_const_iterator VBase =
+       ClassDecl->vbases_begin(),
+       E = ClassDecl->vbases_end(); VBase != E; ++VBase)
+    IdealInitKeys.push_back(GetKeyForBase(SemaRef.Context, VBase->getType()));
+
+  // 2. Non-virtual bases.
+  for (CXXRecordDecl::base_class_const_iterator Base = ClassDecl->bases_begin(),
+       E = ClassDecl->bases_end(); Base != E; ++Base) {
+    if (Base->isVirtual())
+      continue;
+    IdealInitKeys.push_back(GetKeyForBase(SemaRef.Context, Base->getType()));
+  }
+
+  // 3. Direct fields.
+  for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(),
+       E = ClassDecl->field_end(); Field != E; ++Field) {
+    if (Field->isUnnamedBitfield())
+      continue;
+    
+    IdealInitKeys.push_back(GetKeyForTopLevelField(*Field));
+  }
+  
+  unsigned NumIdealInits = IdealInitKeys.size();
+  unsigned IdealIndex = 0;
+
+  CXXCtorInitializer *PrevInit = 0;
+  for (unsigned InitIndex = 0; InitIndex != NumInits; ++InitIndex) {
+    CXXCtorInitializer *Init = Inits[InitIndex];
+    void *InitKey = GetKeyForMember(SemaRef.Context, Init);
+
+    // Scan forward to try to find this initializer in the idealized
+    // initializers list.
+    for (; IdealIndex != NumIdealInits; ++IdealIndex)
+      if (InitKey == IdealInitKeys[IdealIndex])
+        break;
+
+    // If we didn't find this initializer, it must be because we
+    // scanned past it on a previous iteration.  That can only
+    // happen if we're out of order;  emit a warning.
+    if (IdealIndex == NumIdealInits && PrevInit) {
+      Sema::SemaDiagnosticBuilder D =
+        SemaRef.Diag(PrevInit->getSourceLocation(),
+                     diag::warn_initializer_out_of_order);
+
+      if (PrevInit->isAnyMemberInitializer())
+        D << 0 << PrevInit->getAnyMember()->getDeclName();
+      else
+        D << 1 << PrevInit->getTypeSourceInfo()->getType();
+      
+      if (Init->isAnyMemberInitializer())
+        D << 0 << Init->getAnyMember()->getDeclName();
+      else
+        D << 1 << Init->getTypeSourceInfo()->getType();
+
+      // Move back to the initializer's location in the ideal list.
+      for (IdealIndex = 0; IdealIndex != NumIdealInits; ++IdealIndex)
+        if (InitKey == IdealInitKeys[IdealIndex])
+          break;
+
+      assert(IdealIndex != NumIdealInits &&
+             "initializer not found in initializer list");
+    }
+
+    PrevInit = Init;
+  }
+}
+
+namespace {
+bool CheckRedundantInit(Sema &S,
+                        CXXCtorInitializer *Init,
+                        CXXCtorInitializer *&PrevInit) {
+  if (!PrevInit) {
+    PrevInit = Init;
+    return false;
+  }
+
+  if (FieldDecl *Field = Init->getMember())
+    S.Diag(Init->getSourceLocation(),
+           diag::err_multiple_mem_initialization)
+      << Field->getDeclName()
+      << Init->getSourceRange();
+  else {
+    const Type *BaseClass = Init->getBaseClass();
+    assert(BaseClass && "neither field nor base");
+    S.Diag(Init->getSourceLocation(),
+           diag::err_multiple_base_initialization)
+      << QualType(BaseClass, 0)
+      << Init->getSourceRange();
+  }
+  S.Diag(PrevInit->getSourceLocation(), diag::note_previous_initializer)
+    << 0 << PrevInit->getSourceRange();
+
+  return true;
+}
+
+typedef std::pair<NamedDecl *, CXXCtorInitializer *> UnionEntry;
+typedef llvm::DenseMap<RecordDecl*, UnionEntry> RedundantUnionMap;
+
+bool CheckRedundantUnionInit(Sema &S,
+                             CXXCtorInitializer *Init,
+                             RedundantUnionMap &Unions) {
+  FieldDecl *Field = Init->getAnyMember();
+  RecordDecl *Parent = Field->getParent();
+  NamedDecl *Child = Field;
+
+  while (Parent->isAnonymousStructOrUnion() || Parent->isUnion()) {
+    if (Parent->isUnion()) {
+      UnionEntry &En = Unions[Parent];
+      if (En.first && En.first != Child) {
+        S.Diag(Init->getSourceLocation(),
+               diag::err_multiple_mem_union_initialization)
+          << Field->getDeclName()
+          << Init->getSourceRange();
+        S.Diag(En.second->getSourceLocation(), diag::note_previous_initializer)
+          << 0 << En.second->getSourceRange();
+        return true;
+      } 
+      if (!En.first) {
+        En.first = Child;
+        En.second = Init;
+      }
+      if (!Parent->isAnonymousStructOrUnion())
+        return false;
+    }
+
+    Child = Parent;
+    Parent = cast<RecordDecl>(Parent->getDeclContext());
+  }
+
+  return false;
+}
+}
+
+/// ActOnMemInitializers - Handle the member initializers for a constructor.
+void Sema::ActOnMemInitializers(Decl *ConstructorDecl,
+                                SourceLocation ColonLoc,
+                                CXXCtorInitializer **meminits,
+                                unsigned NumMemInits,
+                                bool AnyErrors) {
+  if (!ConstructorDecl)
+    return;
+
+  AdjustDeclIfTemplate(ConstructorDecl);
+
+  CXXConstructorDecl *Constructor
+    = dyn_cast<CXXConstructorDecl>(ConstructorDecl);
+
+  if (!Constructor) {
+    Diag(ColonLoc, diag::err_only_constructors_take_base_inits);
+    return;
+  }
+  
+  CXXCtorInitializer **MemInits =
+    reinterpret_cast<CXXCtorInitializer **>(meminits);
+
+  // Mapping for the duplicate initializers check.
+  // For member initializers, this is keyed with a FieldDecl*.
+  // For base initializers, this is keyed with a Type*.
+  llvm::DenseMap<void*, CXXCtorInitializer *> Members;
+
+  // Mapping for the inconsistent anonymous-union initializers check.
+  RedundantUnionMap MemberUnions;
+
+  bool HadError = false;
+  for (unsigned i = 0; i < NumMemInits; i++) {
+    CXXCtorInitializer *Init = MemInits[i];
+
+    // Set the source order index.
+    Init->setSourceOrder(i);
+
+    if (Init->isAnyMemberInitializer()) {
+      FieldDecl *Field = Init->getAnyMember();
+      if (CheckRedundantInit(*this, Init, Members[Field]) ||
+          CheckRedundantUnionInit(*this, Init, MemberUnions))
+        HadError = true;
+    } else if (Init->isBaseInitializer()) {
+      void *Key = GetKeyForBase(Context, QualType(Init->getBaseClass(), 0));
+      if (CheckRedundantInit(*this, Init, Members[Key]))
+        HadError = true;
+    } else {
+      assert(Init->isDelegatingInitializer());
+      // This must be the only initializer
+      if (i != 0 || NumMemInits > 1) {
+        Diag(MemInits[0]->getSourceLocation(),
+             diag::err_delegating_initializer_alone)
+          << MemInits[0]->getSourceRange();
+        HadError = true;
+        // We will treat this as being the only initializer.
+      }
+      SetDelegatingInitializer(Constructor, MemInits[i]);
+      // Return immediately as the initializer is set.
+      return;
+    }
+  }
+
+  if (HadError)
+    return;
+
+  DiagnoseBaseOrMemInitializerOrder(*this, Constructor, MemInits, NumMemInits);
+
+  SetCtorInitializers(Constructor, MemInits, NumMemInits, AnyErrors);
+}
+
+void
+Sema::MarkBaseAndMemberDestructorsReferenced(SourceLocation Location,
+                                             CXXRecordDecl *ClassDecl) {
+  // Ignore dependent contexts. Also ignore unions, since their members never
+  // have destructors implicitly called.
+  if (ClassDecl->isDependentContext() || ClassDecl->isUnion())
+    return;
+
+  // FIXME: all the access-control diagnostics are positioned on the
+  // field/base declaration.  That's probably good; that said, the
+  // user might reasonably want to know why the destructor is being
+  // emitted, and we currently don't say.
+  
+  // Non-static data members.
+  for (CXXRecordDecl::field_iterator I = ClassDecl->field_begin(),
+       E = ClassDecl->field_end(); I != E; ++I) {
+    FieldDecl *Field = *I;
+    if (Field->isInvalidDecl())
+      continue;
+    
+    // Don't destroy incomplete or zero-length arrays.
+    if (isIncompleteOrZeroLengthArrayType(Context, Field->getType()))
+      continue;
+
+    QualType FieldType = Context.getBaseElementType(Field->getType());
+    
+    const RecordType* RT = FieldType->getAs<RecordType>();
+    if (!RT)
+      continue;
+    
+    CXXRecordDecl *FieldClassDecl = cast<CXXRecordDecl>(RT->getDecl());
+    if (FieldClassDecl->isInvalidDecl())
+      continue;
+    if (FieldClassDecl->hasIrrelevantDestructor())
+      continue;
+    // The destructor for an implicit anonymous union member is never invoked.
+    if (FieldClassDecl->isUnion() && FieldClassDecl->isAnonymousStructOrUnion())
+      continue;
+
+    CXXDestructorDecl *Dtor = LookupDestructor(FieldClassDecl);
+    assert(Dtor && "No dtor found for FieldClassDecl!");
+    CheckDestructorAccess(Field->getLocation(), Dtor,
+                          PDiag(diag::err_access_dtor_field)
+                            << Field->getDeclName()
+                            << FieldType);
+
+    MarkFunctionReferenced(Location, const_cast<CXXDestructorDecl*>(Dtor));
+    DiagnoseUseOfDecl(Dtor, Location);
+  }
+
+  llvm::SmallPtrSet<const RecordType *, 8> DirectVirtualBases;
+
+  // Bases.
+  for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin(),
+       E = ClassDecl->bases_end(); Base != E; ++Base) {
+    // Bases are always records in a well-formed non-dependent class.
+    const RecordType *RT = Base->getType()->getAs<RecordType>();
+
+    // Remember direct virtual bases.
+    if (Base->isVirtual())
+      DirectVirtualBases.insert(RT);
+
+    CXXRecordDecl *BaseClassDecl = cast<CXXRecordDecl>(RT->getDecl());
+    // If our base class is invalid, we probably can't get its dtor anyway.
+    if (BaseClassDecl->isInvalidDecl())
+      continue;
+    if (BaseClassDecl->hasIrrelevantDestructor())
+      continue;
+
+    CXXDestructorDecl *Dtor = LookupDestructor(BaseClassDecl);
+    assert(Dtor && "No dtor found for BaseClassDecl!");
+
+    // FIXME: caret should be on the start of the class name
+    CheckDestructorAccess(Base->getLocStart(), Dtor,
+                          PDiag(diag::err_access_dtor_base)
+                            << Base->getType()
+                            << Base->getSourceRange(),
+                          Context.getTypeDeclType(ClassDecl));
+    
+    MarkFunctionReferenced(Location, const_cast<CXXDestructorDecl*>(Dtor));
+    DiagnoseUseOfDecl(Dtor, Location);
+  }
+  
+  // Virtual bases.
+  for (CXXRecordDecl::base_class_iterator VBase = ClassDecl->vbases_begin(),
+       E = ClassDecl->vbases_end(); VBase != E; ++VBase) {
+
+    // Bases are always records in a well-formed non-dependent class.
+    const RecordType *RT = VBase->getType()->castAs<RecordType>();
+
+    // Ignore direct virtual bases.
+    if (DirectVirtualBases.count(RT))
+      continue;
+
+    CXXRecordDecl *BaseClassDecl = cast<CXXRecordDecl>(RT->getDecl());
+    // If our base class is invalid, we probably can't get its dtor anyway.
+    if (BaseClassDecl->isInvalidDecl())
+      continue;
+    if (BaseClassDecl->hasIrrelevantDestructor())
+      continue;
+
+    CXXDestructorDecl *Dtor = LookupDestructor(BaseClassDecl);
+    assert(Dtor && "No dtor found for BaseClassDecl!");
+    CheckDestructorAccess(ClassDecl->getLocation(), Dtor,
+                          PDiag(diag::err_access_dtor_vbase)
+                            << VBase->getType(),
+                          Context.getTypeDeclType(ClassDecl));
+
+    MarkFunctionReferenced(Location, const_cast<CXXDestructorDecl*>(Dtor));
+    DiagnoseUseOfDecl(Dtor, Location);
+  }
+}
+
+void Sema::ActOnDefaultCtorInitializers(Decl *CDtorDecl) {
+  if (!CDtorDecl)
+    return;
+
+  if (CXXConstructorDecl *Constructor
+      = dyn_cast<CXXConstructorDecl>(CDtorDecl))
+    SetCtorInitializers(Constructor, 0, 0, /*AnyErrors=*/false);
+}
+
+bool Sema::RequireNonAbstractType(SourceLocation Loc, QualType T,
+                                  unsigned DiagID, AbstractDiagSelID SelID) {
+  if (SelID == -1)
+    return RequireNonAbstractType(Loc, T, PDiag(DiagID));
+  else
+    return RequireNonAbstractType(Loc, T, PDiag(DiagID) << SelID);
+}
+
+bool Sema::RequireNonAbstractType(SourceLocation Loc, QualType T,
+                                  const PartialDiagnostic &PD) {
+  if (!getLangOpts().CPlusPlus)
+    return false;
+
+  if (const ArrayType *AT = Context.getAsArrayType(T))
+    return RequireNonAbstractType(Loc, AT->getElementType(), PD);
+
+  if (const PointerType *PT = T->getAs<PointerType>()) {
+    // Find the innermost pointer type.
+    while (const PointerType *T = PT->getPointeeType()->getAs<PointerType>())
+      PT = T;
+
+    if (const ArrayType *AT = Context.getAsArrayType(PT->getPointeeType()))
+      return RequireNonAbstractType(Loc, AT->getElementType(), PD);
+  }
+
+  const RecordType *RT = T->getAs<RecordType>();
+  if (!RT)
+    return false;
+
+  const CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
+
+  // We can't answer whether something is abstract until it has a
+  // definition.  If it's currently being defined, we'll walk back
+  // over all the declarations when we have a full definition.
+  const CXXRecordDecl *Def = RD->getDefinition();
+  if (!Def || Def->isBeingDefined())
+    return false;
+
+  if (!RD->isAbstract())
+    return false;
+
+  Diag(Loc, PD) << RD->getDeclName();
+  DiagnoseAbstractType(RD);
+
+  return true;
+}
+
+void Sema::DiagnoseAbstractType(const CXXRecordDecl *RD) {
+  // Check if we've already emitted the list of pure virtual functions
+  // for this class.
+  if (PureVirtualClassDiagSet && PureVirtualClassDiagSet->count(RD))
+    return;
+
+  CXXFinalOverriderMap FinalOverriders;
+  RD->getFinalOverriders(FinalOverriders);
+
+  // Keep a set of seen pure methods so we won't diagnose the same method
+  // more than once.
+  llvm::SmallPtrSet<const CXXMethodDecl *, 8> SeenPureMethods;
+  
+  for (CXXFinalOverriderMap::iterator M = FinalOverriders.begin(), 
+                                   MEnd = FinalOverriders.end();
+       M != MEnd; 
+       ++M) {
+    for (OverridingMethods::iterator SO = M->second.begin(), 
+                                  SOEnd = M->second.end();
+         SO != SOEnd; ++SO) {
+      // C++ [class.abstract]p4:
+      //   A class is abstract if it contains or inherits at least one
+      //   pure virtual function for which the final overrider is pure
+      //   virtual.
+
+      // 
+      if (SO->second.size() != 1)
+        continue;
+
+      if (!SO->second.front().Method->isPure())
+        continue;
+
+      if (!SeenPureMethods.insert(SO->second.front().Method))
+        continue;
+
+      Diag(SO->second.front().Method->getLocation(), 
+           diag::note_pure_virtual_function) 
+        << SO->second.front().Method->getDeclName() << RD->getDeclName();
+    }
+  }
+
+  if (!PureVirtualClassDiagSet)
+    PureVirtualClassDiagSet.reset(new RecordDeclSetTy);
+  PureVirtualClassDiagSet->insert(RD);
+}
+
+namespace {
+struct AbstractUsageInfo {
+  Sema &S;
+  CXXRecordDecl *Record;
+  CanQualType AbstractType;
+  bool Invalid;
+
+  AbstractUsageInfo(Sema &S, CXXRecordDecl *Record)
+    : S(S), Record(Record),
+      AbstractType(S.Context.getCanonicalType(
+                   S.Context.getTypeDeclType(Record))),
+      Invalid(false) {}
+
+  void DiagnoseAbstractType() {
+    if (Invalid) return;
+    S.DiagnoseAbstractType(Record);
+    Invalid = true;
+  }
+
+  void CheckType(const NamedDecl *D, TypeLoc TL, Sema::AbstractDiagSelID Sel);
+};
+
+struct CheckAbstractUsage {
+  AbstractUsageInfo &Info;
+  const NamedDecl *Ctx;
+
+  CheckAbstractUsage(AbstractUsageInfo &Info, const NamedDecl *Ctx)
+    : Info(Info), Ctx(Ctx) {}
+
+  void Visit(TypeLoc TL, Sema::AbstractDiagSelID Sel) {
+    switch (TL.getTypeLocClass()) {
+#define ABSTRACT_TYPELOC(CLASS, PARENT)
+#define TYPELOC(CLASS, PARENT) \
+    case TypeLoc::CLASS: Check(cast<CLASS##TypeLoc>(TL), Sel); break;
+#include "clang/AST/TypeLocNodes.def"
+    }
+  }
+
+  void Check(FunctionProtoTypeLoc TL, Sema::AbstractDiagSelID Sel) {
+    Visit(TL.getResultLoc(), Sema::AbstractReturnType);
+    for (unsigned I = 0, E = TL.getNumArgs(); I != E; ++I) {
+      if (!TL.getArg(I))
+        continue;
+      
+      TypeSourceInfo *TSI = TL.getArg(I)->getTypeSourceInfo();
+      if (TSI) Visit(TSI->getTypeLoc(), Sema::AbstractParamType);
+    }
+  }
+
+  void Check(ArrayTypeLoc TL, Sema::AbstractDiagSelID Sel) {
+    Visit(TL.getElementLoc(), Sema::AbstractArrayType);
+  }
+
+  void Check(TemplateSpecializationTypeLoc TL, Sema::AbstractDiagSelID Sel) {
+    // Visit the type parameters from a permissive context.
+    for (unsigned I = 0, E = TL.getNumArgs(); I != E; ++I) {
+      TemplateArgumentLoc TAL = TL.getArgLoc(I);
+      if (TAL.getArgument().getKind() == TemplateArgument::Type)
+        if (TypeSourceInfo *TSI = TAL.getTypeSourceInfo())
+          Visit(TSI->getTypeLoc(), Sema::AbstractNone);
+      // TODO: other template argument types?
+    }
+  }
+
+  // Visit pointee types from a permissive context.
+#define CheckPolymorphic(Type) \
+  void Check(Type TL, Sema::AbstractDiagSelID Sel) { \
+    Visit(TL.getNextTypeLoc(), Sema::AbstractNone); \
+  }
+  CheckPolymorphic(PointerTypeLoc)
+  CheckPolymorphic(ReferenceTypeLoc)
+  CheckPolymorphic(MemberPointerTypeLoc)
+  CheckPolymorphic(BlockPointerTypeLoc)
+  CheckPolymorphic(AtomicTypeLoc)
+
+  /// Handle all the types we haven't given a more specific
+  /// implementation for above.
+  void Check(TypeLoc TL, Sema::AbstractDiagSelID Sel) {
+    // Every other kind of type that we haven't called out already
+    // that has an inner type is either (1) sugar or (2) contains that
+    // inner type in some way as a subobject.
+    if (TypeLoc Next = TL.getNextTypeLoc())
+      return Visit(Next, Sel);
+
+    // If there's no inner type and we're in a permissive context,
+    // don't diagnose.
+    if (Sel == Sema::AbstractNone) return;
+
+    // Check whether the type matches the abstract type.
+    QualType T = TL.getType();
+    if (T->isArrayType()) {
+      Sel = Sema::AbstractArrayType;
+      T = Info.S.Context.getBaseElementType(T);
+    }
+    CanQualType CT = T->getCanonicalTypeUnqualified().getUnqualifiedType();
+    if (CT != Info.AbstractType) return;
+
+    // It matched; do some magic.
+    if (Sel == Sema::AbstractArrayType) {
+      Info.S.Diag(Ctx->getLocation(), diag::err_array_of_abstract_type)
+        << T << TL.getSourceRange();
+    } else {
+      Info.S.Diag(Ctx->getLocation(), diag::err_abstract_type_in_decl)
+        << Sel << T << TL.getSourceRange();
+    }
+    Info.DiagnoseAbstractType();
+  }
+};
+
+void AbstractUsageInfo::CheckType(const NamedDecl *D, TypeLoc TL,
+                                  Sema::AbstractDiagSelID Sel) {
+  CheckAbstractUsage(*this, D).Visit(TL, Sel);
+}
+
+}
+
+/// Check for invalid uses of an abstract type in a method declaration.
+static void CheckAbstractClassUsage(AbstractUsageInfo &Info,
+                                    CXXMethodDecl *MD) {
+  // No need to do the check on definitions, which require that
+  // the return/param types be complete.
+  if (MD->doesThisDeclarationHaveABody())
+    return;
+
+  // For safety's sake, just ignore it if we don't have type source
+  // information.  This should never happen for non-implicit methods,
+  // but...
+  if (TypeSourceInfo *TSI = MD->getTypeSourceInfo())
+    Info.CheckType(MD, TSI->getTypeLoc(), Sema::AbstractNone);
+}
+
+/// Check for invalid uses of an abstract type within a class definition.
+static void CheckAbstractClassUsage(AbstractUsageInfo &Info,
+                                    CXXRecordDecl *RD) {
+  for (CXXRecordDecl::decl_iterator
+         I = RD->decls_begin(), E = RD->decls_end(); I != E; ++I) {
+    Decl *D = *I;
+    if (D->isImplicit()) continue;
+
+    // Methods and method templates.
+    if (isa<CXXMethodDecl>(D)) {
+      CheckAbstractClassUsage(Info, cast<CXXMethodDecl>(D));
+    } else if (isa<FunctionTemplateDecl>(D)) {
+      FunctionDecl *FD = cast<FunctionTemplateDecl>(D)->getTemplatedDecl();
+      CheckAbstractClassUsage(Info, cast<CXXMethodDecl>(FD));
+
+    // Fields and static variables.
+    } else if (isa<FieldDecl>(D)) {
+      FieldDecl *FD = cast<FieldDecl>(D);
+      if (TypeSourceInfo *TSI = FD->getTypeSourceInfo())
+        Info.CheckType(FD, TSI->getTypeLoc(), Sema::AbstractFieldType);
+    } else if (isa<VarDecl>(D)) {
+      VarDecl *VD = cast<VarDecl>(D);
+      if (TypeSourceInfo *TSI = VD->getTypeSourceInfo())
+        Info.CheckType(VD, TSI->getTypeLoc(), Sema::AbstractVariableType);
+
+    // Nested classes and class templates.
+    } else if (isa<CXXRecordDecl>(D)) {
+      CheckAbstractClassUsage(Info, cast<CXXRecordDecl>(D));
+    } else if (isa<ClassTemplateDecl>(D)) {
+      CheckAbstractClassUsage(Info,
+                             cast<ClassTemplateDecl>(D)->getTemplatedDecl());
+    }
+  }
+}
+
+/// \brief Perform semantic checks on a class definition that has been
+/// completing, introducing implicitly-declared members, checking for
+/// abstract types, etc.
+void Sema::CheckCompletedCXXClass(CXXRecordDecl *Record) {
+  if (!Record)
+    return;
+
+  if (Record->isAbstract() && !Record->isInvalidDecl()) {
+    AbstractUsageInfo Info(*this, Record);
+    CheckAbstractClassUsage(Info, Record);
+  }
+  
+  // If this is not an aggregate type and has no user-declared constructor,
+  // complain about any non-static data members of reference or const scalar
+  // type, since they will never get initializers.
+  if (!Record->isInvalidDecl() && !Record->isDependentType() &&
+      !Record->isAggregate() && !Record->hasUserDeclaredConstructor() &&
+      !Record->isLambda()) {
+    bool Complained = false;
+    for (RecordDecl::field_iterator F = Record->field_begin(), 
+                                 FEnd = Record->field_end();
+         F != FEnd; ++F) {
+      if (F->hasInClassInitializer() || F->isUnnamedBitfield())
+        continue;
+
+      if (F->getType()->isReferenceType() ||
+          (F->getType().isConstQualified() && F->getType()->isScalarType())) {
+        if (!Complained) {
+          Diag(Record->getLocation(), diag::warn_no_constructor_for_refconst)
+            << Record->getTagKind() << Record;
+          Complained = true;
+        }
+        
+        Diag(F->getLocation(), diag::note_refconst_member_not_initialized)
+          << F->getType()->isReferenceType()
+          << F->getDeclName();
+      }
+    }
+  }
+
+  if (Record->isDynamicClass() && !Record->isDependentType())
+    DynamicClasses.push_back(Record);
+
+  if (Record->getIdentifier()) {
+    // C++ [class.mem]p13:
+    //   If T is the name of a class, then each of the following shall have a 
+    //   name different from T:
+    //     - every member of every anonymous union that is a member of class T.
+    //
+    // C++ [class.mem]p14:
+    //   In addition, if class T has a user-declared constructor (12.1), every 
+    //   non-static data member of class T shall have a name different from T.
+    for (DeclContext::lookup_result R = Record->lookup(Record->getDeclName());
+         R.first != R.second; ++R.first) {
+      NamedDecl *D = *R.first;
+      if ((isa<FieldDecl>(D) && Record->hasUserDeclaredConstructor()) ||
+          isa<IndirectFieldDecl>(D)) {
+        Diag(D->getLocation(), diag::err_member_name_of_class)
+          << D->getDeclName();
+        break;
+      }
+    }
+  }
+
+  // Warn if the class has virtual methods but non-virtual public destructor.
+  if (Record->isPolymorphic() && !Record->isDependentType()) {
+    CXXDestructorDecl *dtor = Record->getDestructor();
+    if (!dtor || (!dtor->isVirtual() && dtor->getAccess() == AS_public))
+      Diag(dtor ? dtor->getLocation() : Record->getLocation(),
+           diag::warn_non_virtual_dtor) << Context.getRecordType(Record);
+  }
+
+  // See if a method overloads virtual methods in a base
+  /// class without overriding any.
+  if (!Record->isDependentType()) {
+    for (CXXRecordDecl::method_iterator M = Record->method_begin(),
+                                     MEnd = Record->method_end();
+         M != MEnd; ++M) {
+      if (!(*M)->isStatic())
+        DiagnoseHiddenVirtualMethods(Record, *M);
+    }
+  }
+
+  // C++0x [dcl.constexpr]p8: A constexpr specifier for a non-static member
+  // function that is not a constructor declares that member function to be
+  // const. [...] The class of which that function is a member shall be
+  // a literal type.
+  //
+  // If the class has virtual bases, any constexpr members will already have
+  // been diagnosed by the checks performed on the member declaration, so
+  // suppress this (less useful) diagnostic.
+  if (LangOpts.CPlusPlus0x && !Record->isDependentType() &&
+      !Record->isLiteral() && !Record->getNumVBases()) {
+    for (CXXRecordDecl::method_iterator M = Record->method_begin(),
+                                     MEnd = Record->method_end();
+         M != MEnd; ++M) {
+      if (M->isConstexpr() && M->isInstance() && !isa<CXXConstructorDecl>(*M)) {
+        switch (Record->getTemplateSpecializationKind()) {
+        case TSK_ImplicitInstantiation:
+        case TSK_ExplicitInstantiationDeclaration:
+        case TSK_ExplicitInstantiationDefinition:
+          // If a template instantiates to a non-literal type, but its members
+          // instantiate to constexpr functions, the template is technically
+          // ill-formed, but we allow it for sanity.
+          continue;
+
+        case TSK_Undeclared:
+        case TSK_ExplicitSpecialization:
+          RequireLiteralType((*M)->getLocation(), Context.getRecordType(Record),
+                             PDiag(diag::err_constexpr_method_non_literal));
+          break;
+        }
+
+        // Only produce one error per class.
+        break;
+      }
+    }
+  }
+
+  // Declare inherited constructors. We do this eagerly here because:
+  // - The standard requires an eager diagnostic for conflicting inherited
+  //   constructors from different classes.
+  // - The lazy declaration of the other implicit constructors is so as to not
+  //   waste space and performance on classes that are not meant to be
+  //   instantiated (e.g. meta-functions). This doesn't apply to classes that
+  //   have inherited constructors.
+  DeclareInheritedConstructors(Record);
+
+  if (!Record->isDependentType())
+    CheckExplicitlyDefaultedMethods(Record);
+}
+
+void Sema::CheckExplicitlyDefaultedMethods(CXXRecordDecl *Record) {
+  for (CXXRecordDecl::method_iterator MI = Record->method_begin(),
+                                      ME = Record->method_end();
+       MI != ME; ++MI) {
+    if (!MI->isInvalidDecl() && MI->isExplicitlyDefaulted()) {
+      switch (getSpecialMember(*MI)) {
+      case CXXDefaultConstructor:
+        CheckExplicitlyDefaultedDefaultConstructor(
+                                                  cast<CXXConstructorDecl>(*MI));
+        break;
+
+      case CXXDestructor:
+        CheckExplicitlyDefaultedDestructor(cast<CXXDestructorDecl>(*MI));
+        break;
+
+      case CXXCopyConstructor:
+        CheckExplicitlyDefaultedCopyConstructor(cast<CXXConstructorDecl>(*MI));
+        break;
+
+      case CXXCopyAssignment:
+        CheckExplicitlyDefaultedCopyAssignment(*MI);
+        break;
+
+      case CXXMoveConstructor:
+        CheckExplicitlyDefaultedMoveConstructor(cast<CXXConstructorDecl>(*MI));
+        break;
+
+      case CXXMoveAssignment:
+        CheckExplicitlyDefaultedMoveAssignment(*MI);
+        break;
+
+      case CXXInvalid:
+        llvm_unreachable("non-special member explicitly defaulted!");
+      }
+    }
+  }
+
+}
+
+void Sema::CheckExplicitlyDefaultedDefaultConstructor(CXXConstructorDecl *CD) {
+  assert(CD->isExplicitlyDefaulted() && CD->isDefaultConstructor());
+  
+  // Whether this was the first-declared instance of the constructor.
+  // This affects whether we implicitly add an exception spec (and, eventually,
+  // constexpr). It is also ill-formed to explicitly default a constructor such
+  // that it would be deleted. (C++0x [decl.fct.def.default])
+  bool First = CD == CD->getCanonicalDecl();
+
+  bool HadError = false;
+  if (CD->getNumParams() != 0) {
+    Diag(CD->getLocation(), diag::err_defaulted_default_ctor_params)
+      << CD->getSourceRange();
+    HadError = true;
+  }
+
+  ImplicitExceptionSpecification Spec
+    = ComputeDefaultedDefaultCtorExceptionSpec(CD->getParent());
+  FunctionProtoType::ExtProtoInfo EPI = Spec.getEPI();
+  if (EPI.ExceptionSpecType == EST_Delayed) {
+    // Exception specification depends on some deferred part of the class. We'll
+    // try again when the class's definition has been fully processed.
+    return;
+  }
+  const FunctionProtoType *CtorType = CD->getType()->getAs<FunctionProtoType>(),
+                          *ExceptionType = Context.getFunctionType(
+                         Context.VoidTy, 0, 0, EPI)->getAs<FunctionProtoType>();
+
+  // C++11 [dcl.fct.def.default]p2:
+  //   An explicitly-defaulted function may be declared constexpr only if it
+  //   would have been implicitly declared as constexpr,
+  // Do not apply this rule to templates, since core issue 1358 makes such
+  // functions always instantiate to constexpr functions.
+  if (CD->isConstexpr() &&
+      CD->getTemplatedKind() == FunctionDecl::TK_NonTemplate) {
+    if (!CD->getParent()->defaultedDefaultConstructorIsConstexpr()) {
+      Diag(CD->getLocStart(), diag::err_incorrect_defaulted_constexpr)
+        << CXXDefaultConstructor;
+      HadError = true;
+    }
+  }
+  //   and may have an explicit exception-specification only if it is compatible
+  //   with the exception-specification on the implicit declaration.
+  if (CtorType->hasExceptionSpec()) {
+    if (CheckEquivalentExceptionSpec(
+          PDiag(diag::err_incorrect_defaulted_exception_spec)
+            << CXXDefaultConstructor,
+          PDiag(),
+          ExceptionType, SourceLocation(),
+          CtorType, CD->getLocation())) {
+      HadError = true;
+    }
+  }
+
+  //   If a function is explicitly defaulted on its first declaration,
+  if (First) {
+    //  -- it is implicitly considered to be constexpr if the implicit
+    //     definition would be,
+    CD->setConstexpr(CD->getParent()->defaultedDefaultConstructorIsConstexpr());
+
+    //  -- it is implicitly considered to have the same
+    //     exception-specification as if it had been implicitly declared
+    //
+    // FIXME: a compatible, but different, explicit exception specification
+    // will be silently overridden. We should issue a warning if this happens.
+    EPI.ExtInfo = CtorType->getExtInfo();
+
+    // Such a function is also trivial if the implicitly-declared function
+    // would have been.
+    CD->setTrivial(CD->getParent()->hasTrivialDefaultConstructor());
+  }
+
+  if (HadError) {
+    CD->setInvalidDecl();
+    return;
+  }
+
+  if (ShouldDeleteSpecialMember(CD, CXXDefaultConstructor)) {
+    if (First) {
+      CD->setDeletedAsWritten();
+    } else {
+      Diag(CD->getLocation(), diag::err_out_of_line_default_deletes)
+        << CXXDefaultConstructor;
+      CD->setInvalidDecl();
+    }
+  }
+}
+
+void Sema::CheckExplicitlyDefaultedCopyConstructor(CXXConstructorDecl *CD) {
+  assert(CD->isExplicitlyDefaulted() && CD->isCopyConstructor());
+
+  // Whether this was the first-declared instance of the constructor.
+  bool First = CD == CD->getCanonicalDecl();
+
+  bool HadError = false;
+  if (CD->getNumParams() != 1) {
+    Diag(CD->getLocation(), diag::err_defaulted_copy_ctor_params)
+      << CD->getSourceRange();
+    HadError = true;
+  }
+
+  ImplicitExceptionSpecification Spec(*this);
+  bool Const;
+  llvm::tie(Spec, Const) =
+    ComputeDefaultedCopyCtorExceptionSpecAndConst(CD->getParent());
+  
+  FunctionProtoType::ExtProtoInfo EPI = Spec.getEPI();
+  const FunctionProtoType *CtorType = CD->getType()->getAs<FunctionProtoType>(),
+                          *ExceptionType = Context.getFunctionType(
+                         Context.VoidTy, 0, 0, EPI)->getAs<FunctionProtoType>();
+
+  // Check for parameter type matching.
+  // This is a copy ctor so we know it's a cv-qualified reference to T.
+  QualType ArgType = CtorType->getArgType(0);
+  if (ArgType->getPointeeType().isVolatileQualified()) {
+    Diag(CD->getLocation(), diag::err_defaulted_copy_ctor_volatile_param);
+    HadError = true;
+  }
+  if (ArgType->getPointeeType().isConstQualified() && !Const) {
+    Diag(CD->getLocation(), diag::err_defaulted_copy_ctor_const_param);
+    HadError = true;
+  }
+
+  // C++11 [dcl.fct.def.default]p2:
+  //   An explicitly-defaulted function may be declared constexpr only if it
+  //   would have been implicitly declared as constexpr,
+  // Do not apply this rule to templates, since core issue 1358 makes such
+  // functions always instantiate to constexpr functions.
+  if (CD->isConstexpr() &&
+      CD->getTemplatedKind() == FunctionDecl::TK_NonTemplate) {
+    if (!CD->getParent()->defaultedCopyConstructorIsConstexpr()) {
+      Diag(CD->getLocStart(), diag::err_incorrect_defaulted_constexpr)
+        << CXXCopyConstructor;
+      HadError = true;
+    }
+  }
+  //   and may have an explicit exception-specification only if it is compatible
+  //   with the exception-specification on the implicit declaration.
+  if (CtorType->hasExceptionSpec()) {
+    if (CheckEquivalentExceptionSpec(
+          PDiag(diag::err_incorrect_defaulted_exception_spec)
+            << CXXCopyConstructor,
+          PDiag(),
+          ExceptionType, SourceLocation(),
+          CtorType, CD->getLocation())) {
+      HadError = true;
+    }
+  }
+
+  //   If a function is explicitly defaulted on its first declaration,
+  if (First) {
+    //  -- it is implicitly considered to be constexpr if the implicit
+    //     definition would be,
+    CD->setConstexpr(CD->getParent()->defaultedCopyConstructorIsConstexpr());
+
+    //  -- it is implicitly considered to have the same
+    //     exception-specification as if it had been implicitly declared, and
+    //
+    // FIXME: a compatible, but different, explicit exception specification
+    // will be silently overridden. We should issue a warning if this happens.
+    EPI.ExtInfo = CtorType->getExtInfo();
+
+    //  -- [...] it shall have the same parameter type as if it had been
+    //     implicitly declared.
+    CD->setType(Context.getFunctionType(Context.VoidTy, &ArgType, 1, EPI));
+
+    // Such a function is also trivial if the implicitly-declared function
+    // would have been.
+    CD->setTrivial(CD->getParent()->hasTrivialCopyConstructor());
+  }
+
+  if (HadError) {
+    CD->setInvalidDecl();
+    return;
+  }
+
+  if (ShouldDeleteSpecialMember(CD, CXXCopyConstructor)) {
+    if (First) {
+      CD->setDeletedAsWritten();
+    } else {
+      Diag(CD->getLocation(), diag::err_out_of_line_default_deletes)
+        << CXXCopyConstructor;
+      CD->setInvalidDecl();
+    }
+  }
+}
+
+void Sema::CheckExplicitlyDefaultedCopyAssignment(CXXMethodDecl *MD) {
+  assert(MD->isExplicitlyDefaulted());
+
+  // Whether this was the first-declared instance of the operator
+  bool First = MD == MD->getCanonicalDecl();
+
+  bool HadError = false;
+  if (MD->getNumParams() != 1) {
+    Diag(MD->getLocation(), diag::err_defaulted_copy_assign_params)
+      << MD->getSourceRange();
+    HadError = true;
+  }
+
+  QualType ReturnType =
+    MD->getType()->getAs<FunctionType>()->getResultType();
+  if (!ReturnType->isLValueReferenceType() ||
+      !Context.hasSameType(
+        Context.getCanonicalType(ReturnType->getPointeeType()),
+        Context.getCanonicalType(Context.getTypeDeclType(MD->getParent())))) {
+    Diag(MD->getLocation(), diag::err_defaulted_copy_assign_return_type);
+    HadError = true;
+  }
+
+  ImplicitExceptionSpecification Spec(*this);
+  bool Const;
+  llvm::tie(Spec, Const) =
+    ComputeDefaultedCopyCtorExceptionSpecAndConst(MD->getParent());
+  
+  FunctionProtoType::ExtProtoInfo EPI = Spec.getEPI();
+  const FunctionProtoType *OperType = MD->getType()->getAs<FunctionProtoType>(),
+                          *ExceptionType = Context.getFunctionType(
+                         Context.VoidTy, 0, 0, EPI)->getAs<FunctionProtoType>();
+
+  QualType ArgType = OperType->getArgType(0);
+  if (!ArgType->isLValueReferenceType()) {
+    Diag(MD->getLocation(), diag::err_defaulted_copy_assign_not_ref);
+    HadError = true;
+  } else {
+    if (ArgType->getPointeeType().isVolatileQualified()) {
+      Diag(MD->getLocation(), diag::err_defaulted_copy_assign_volatile_param);
+      HadError = true;
+    }
+    if (ArgType->getPointeeType().isConstQualified() && !Const) {
+      Diag(MD->getLocation(), diag::err_defaulted_copy_assign_const_param);
+      HadError = true;
+    }
+  }
+
+  if (OperType->getTypeQuals()) {
+    Diag(MD->getLocation(), diag::err_defaulted_copy_assign_quals);
+    HadError = true;
+  }
+
+  if (OperType->hasExceptionSpec()) {
+    if (CheckEquivalentExceptionSpec(
+          PDiag(diag::err_incorrect_defaulted_exception_spec)
+            << CXXCopyAssignment,
+          PDiag(),
+          ExceptionType, SourceLocation(),
+          OperType, MD->getLocation())) {
+      HadError = true;
+    }
+  }
+  if (First) {
+    // We set the declaration to have the computed exception spec here.
+    // We duplicate the one parameter type.
+    EPI.RefQualifier = OperType->getRefQualifier();
+    EPI.ExtInfo = OperType->getExtInfo();
+    MD->setType(Context.getFunctionType(ReturnType, &ArgType, 1, EPI));
+
+    // Such a function is also trivial if the implicitly-declared function
+    // would have been.
+    MD->setTrivial(MD->getParent()->hasTrivialCopyAssignment());
+  }
+
+  if (HadError) {
+    MD->setInvalidDecl();
+    return;
+  }
+
+  if (ShouldDeleteSpecialMember(MD, CXXCopyAssignment)) {
+    if (First) {
+      MD->setDeletedAsWritten();
+    } else {
+      Diag(MD->getLocation(), diag::err_out_of_line_default_deletes)
+        << CXXCopyAssignment;
+      MD->setInvalidDecl();
+    }
+  }
+}
+
+void Sema::CheckExplicitlyDefaultedMoveConstructor(CXXConstructorDecl *CD) {
+  assert(CD->isExplicitlyDefaulted() && CD->isMoveConstructor());
+
+  // Whether this was the first-declared instance of the constructor.
+  bool First = CD == CD->getCanonicalDecl();
+
+  bool HadError = false;
+  if (CD->getNumParams() != 1) {
+    Diag(CD->getLocation(), diag::err_defaulted_move_ctor_params)
+      << CD->getSourceRange();
+    HadError = true;
+  }
+
+  ImplicitExceptionSpecification Spec(
+      ComputeDefaultedMoveCtorExceptionSpec(CD->getParent()));
+
+  FunctionProtoType::ExtProtoInfo EPI = Spec.getEPI();
+  const FunctionProtoType *CtorType = CD->getType()->getAs<FunctionProtoType>(),
+                          *ExceptionType = Context.getFunctionType(
+                         Context.VoidTy, 0, 0, EPI)->getAs<FunctionProtoType>();
+
+  // Check for parameter type matching.
+  // This is a move ctor so we know it's a cv-qualified rvalue reference to T.
+  QualType ArgType = CtorType->getArgType(0);
+  if (ArgType->getPointeeType().isVolatileQualified()) {
+    Diag(CD->getLocation(), diag::err_defaulted_move_ctor_volatile_param);
+    HadError = true;
+  }
+  if (ArgType->getPointeeType().isConstQualified()) {
+    Diag(CD->getLocation(), diag::err_defaulted_move_ctor_const_param);
+    HadError = true;
+  }
+
+  // C++11 [dcl.fct.def.default]p2:
+  //   An explicitly-defaulted function may be declared constexpr only if it
+  //   would have been implicitly declared as constexpr,
+  // Do not apply this rule to templates, since core issue 1358 makes such
+  // functions always instantiate to constexpr functions.
+  if (CD->isConstexpr() &&
+      CD->getTemplatedKind() == FunctionDecl::TK_NonTemplate) {
+    if (!CD->getParent()->defaultedMoveConstructorIsConstexpr()) {
+      Diag(CD->getLocStart(), diag::err_incorrect_defaulted_constexpr)
+        << CXXMoveConstructor;
+      HadError = true;
+    }
+  }
+  //   and may have an explicit exception-specification only if it is compatible
+  //   with the exception-specification on the implicit declaration.
+  if (CtorType->hasExceptionSpec()) {
+    if (CheckEquivalentExceptionSpec(
+          PDiag(diag::err_incorrect_defaulted_exception_spec)
+            << CXXMoveConstructor,
+          PDiag(),
+          ExceptionType, SourceLocation(),
+          CtorType, CD->getLocation())) {
+      HadError = true;
+    }
+  }
+
+  //   If a function is explicitly defaulted on its first declaration,
+  if (First) {
+    //  -- it is implicitly considered to be constexpr if the implicit
+    //     definition would be,
+    CD->setConstexpr(CD->getParent()->defaultedMoveConstructorIsConstexpr());
+
+    //  -- it is implicitly considered to have the same
+    //     exception-specification as if it had been implicitly declared, and
+    //
+    // FIXME: a compatible, but different, explicit exception specification
+    // will be silently overridden. We should issue a warning if this happens.
+    EPI.ExtInfo = CtorType->getExtInfo();
+
+    //  -- [...] it shall have the same parameter type as if it had been
+    //     implicitly declared.
+    CD->setType(Context.getFunctionType(Context.VoidTy, &ArgType, 1, EPI));
+
+    // Such a function is also trivial if the implicitly-declared function
+    // would have been.
+    CD->setTrivial(CD->getParent()->hasTrivialMoveConstructor());
+  }
+
+  if (HadError) {
+    CD->setInvalidDecl();
+    return;
+  }
+
+  if (ShouldDeleteSpecialMember(CD, CXXMoveConstructor)) {
+    if (First) {
+      CD->setDeletedAsWritten();
+    } else {
+      Diag(CD->getLocation(), diag::err_out_of_line_default_deletes)
+        << CXXMoveConstructor;
+      CD->setInvalidDecl();
+    }
+  }
+}
+
+void Sema::CheckExplicitlyDefaultedMoveAssignment(CXXMethodDecl *MD) {
+  assert(MD->isExplicitlyDefaulted());
+
+  // Whether this was the first-declared instance of the operator
+  bool First = MD == MD->getCanonicalDecl();
+
+  bool HadError = false;
+  if (MD->getNumParams() != 1) {
+    Diag(MD->getLocation(), diag::err_defaulted_move_assign_params)
+      << MD->getSourceRange();
+    HadError = true;
+  }
+
+  QualType ReturnType =
+    MD->getType()->getAs<FunctionType>()->getResultType();
+  if (!ReturnType->isLValueReferenceType() ||
+      !Context.hasSameType(
+        Context.getCanonicalType(ReturnType->getPointeeType()),
+        Context.getCanonicalType(Context.getTypeDeclType(MD->getParent())))) {
+    Diag(MD->getLocation(), diag::err_defaulted_move_assign_return_type);
+    HadError = true;
+  }
+
+  ImplicitExceptionSpecification Spec(
+      ComputeDefaultedMoveCtorExceptionSpec(MD->getParent()));
+  
+  FunctionProtoType::ExtProtoInfo EPI = Spec.getEPI();
+  const FunctionProtoType *OperType = MD->getType()->getAs<FunctionProtoType>(),
+                          *ExceptionType = Context.getFunctionType(
+                         Context.VoidTy, 0, 0, EPI)->getAs<FunctionProtoType>();
+
+  QualType ArgType = OperType->getArgType(0);
+  if (!ArgType->isRValueReferenceType()) {
+    Diag(MD->getLocation(), diag::err_defaulted_move_assign_not_ref);
+    HadError = true;
+  } else {
+    if (ArgType->getPointeeType().isVolatileQualified()) {
+      Diag(MD->getLocation(), diag::err_defaulted_move_assign_volatile_param);
+      HadError = true;
+    }
+    if (ArgType->getPointeeType().isConstQualified()) {
+      Diag(MD->getLocation(), diag::err_defaulted_move_assign_const_param);
+      HadError = true;
+    }
+  }
+
+  if (OperType->getTypeQuals()) {
+    Diag(MD->getLocation(), diag::err_defaulted_move_assign_quals);
+    HadError = true;
+  }
+
+  if (OperType->hasExceptionSpec()) {
+    if (CheckEquivalentExceptionSpec(
+          PDiag(diag::err_incorrect_defaulted_exception_spec)
+            << CXXMoveAssignment,
+          PDiag(),
+          ExceptionType, SourceLocation(),
+          OperType, MD->getLocation())) {
+      HadError = true;
+    }
+  }
+  if (First) {
+    // We set the declaration to have the computed exception spec here.
+    // We duplicate the one parameter type.
+    EPI.RefQualifier = OperType->getRefQualifier();
+    EPI.ExtInfo = OperType->getExtInfo();
+    MD->setType(Context.getFunctionType(ReturnType, &ArgType, 1, EPI));
+
+    // Such a function is also trivial if the implicitly-declared function
+    // would have been.
+    MD->setTrivial(MD->getParent()->hasTrivialMoveAssignment());
+  }
+
+  if (HadError) {
+    MD->setInvalidDecl();
+    return;
+  }
+
+  if (ShouldDeleteSpecialMember(MD, CXXMoveAssignment)) {
+    if (First) {
+      MD->setDeletedAsWritten();
+    } else {
+      Diag(MD->getLocation(), diag::err_out_of_line_default_deletes)
+        << CXXMoveAssignment;
+      MD->setInvalidDecl();
+    }
+  }
+}
+
+void Sema::CheckExplicitlyDefaultedDestructor(CXXDestructorDecl *DD) {
+  assert(DD->isExplicitlyDefaulted());
+
+  // Whether this was the first-declared instance of the destructor.
+  bool First = DD == DD->getCanonicalDecl();
+
+  ImplicitExceptionSpecification Spec
+    = ComputeDefaultedDtorExceptionSpec(DD->getParent());
+  FunctionProtoType::ExtProtoInfo EPI = Spec.getEPI();
+  const FunctionProtoType *DtorType = DD->getType()->getAs<FunctionProtoType>(),
+                          *ExceptionType = Context.getFunctionType(
+                         Context.VoidTy, 0, 0, EPI)->getAs<FunctionProtoType>();
+
+  if (DtorType->hasExceptionSpec()) {
+    if (CheckEquivalentExceptionSpec(
+          PDiag(diag::err_incorrect_defaulted_exception_spec)
+            << CXXDestructor,
+          PDiag(),
+          ExceptionType, SourceLocation(),
+          DtorType, DD->getLocation())) {
+      DD->setInvalidDecl();
+      return;
+    }
+  }
+  if (First) {
+    // We set the declaration to have the computed exception spec here.
+    // There are no parameters.
+    EPI.ExtInfo = DtorType->getExtInfo();
+    DD->setType(Context.getFunctionType(Context.VoidTy, 0, 0, EPI));
+
+    // Such a function is also trivial if the implicitly-declared function
+    // would have been.
+    DD->setTrivial(DD->getParent()->hasTrivialDestructor());
+  }
+
+  if (ShouldDeleteSpecialMember(DD, CXXDestructor)) {
+    if (First) {
+      DD->setDeletedAsWritten();
+    } else {
+      Diag(DD->getLocation(), diag::err_out_of_line_default_deletes)
+        << CXXDestructor;
+      DD->setInvalidDecl();
+    }
+  }
+}
+
+namespace {
+struct SpecialMemberDeletionInfo {
+  Sema &S;
+  CXXMethodDecl *MD;
+  Sema::CXXSpecialMember CSM;
+  bool Diagnose;
+
+  // Properties of the special member, computed for convenience.
+  bool IsConstructor, IsAssignment, IsMove, ConstArg, VolatileArg;
+  SourceLocation Loc;
+
+  bool AllFieldsAreConst;
+
+  SpecialMemberDeletionInfo(Sema &S, CXXMethodDecl *MD,
+                            Sema::CXXSpecialMember CSM, bool Diagnose)
+    : S(S), MD(MD), CSM(CSM), Diagnose(Diagnose),
+      IsConstructor(false), IsAssignment(false), IsMove(false),
+      ConstArg(false), VolatileArg(false), Loc(MD->getLocation()),
+      AllFieldsAreConst(true) {
+    switch (CSM) {
+      case Sema::CXXDefaultConstructor:
+      case Sema::CXXCopyConstructor:
+        IsConstructor = true;
+        break;
+      case Sema::CXXMoveConstructor:
+        IsConstructor = true;
+        IsMove = true;
+        break;
+      case Sema::CXXCopyAssignment:
+        IsAssignment = true;
+        break;
+      case Sema::CXXMoveAssignment:
+        IsAssignment = true;
+        IsMove = true;
+        break;
+      case Sema::CXXDestructor:
+        break;
+      case Sema::CXXInvalid:
+        llvm_unreachable("invalid special member kind");
+    }
+
+    if (MD->getNumParams()) {
+      ConstArg = MD->getParamDecl(0)->getType().isConstQualified();
+      VolatileArg = MD->getParamDecl(0)->getType().isVolatileQualified();
+    }
+  }
+
+  bool inUnion() const { return MD->getParent()->isUnion(); }
+
+  /// Look up the corresponding special member in the given class.
+  Sema::SpecialMemberOverloadResult *lookupIn(CXXRecordDecl *Class) {
+    unsigned TQ = MD->getTypeQualifiers();
+    return S.LookupSpecialMember(Class, CSM, ConstArg, VolatileArg,
+                                 MD->getRefQualifier() == RQ_RValue,
+                                 TQ & Qualifiers::Const,
+                                 TQ & Qualifiers::Volatile);
+  }
+
+  typedef llvm::PointerUnion<CXXBaseSpecifier*, FieldDecl*> Subobject;
+
+  bool shouldDeleteForBase(CXXBaseSpecifier *Base);
+  bool shouldDeleteForField(FieldDecl *FD);
+  bool shouldDeleteForAllConstMembers();
+
+  bool shouldDeleteForClassSubobject(CXXRecordDecl *Class, Subobject Subobj);
+  bool shouldDeleteForSubobjectCall(Subobject Subobj,
+                                    Sema::SpecialMemberOverloadResult *SMOR,
+                                    bool IsDtorCallInCtor);
+
+  bool isAccessible(Subobject Subobj, CXXMethodDecl *D);
+};
+}
+
+/// Is the given special member inaccessible when used on the given
+/// sub-object.
+bool SpecialMemberDeletionInfo::isAccessible(Subobject Subobj,
+                                             CXXMethodDecl *target) {
+  /// If we're operating on a base class, the object type is the
+  /// type of this special member.
+  QualType objectTy;
+  AccessSpecifier access = target->getAccess();;
+  if (CXXBaseSpecifier *base = Subobj.dyn_cast<CXXBaseSpecifier*>()) {
+    objectTy = S.Context.getTypeDeclType(MD->getParent());
+    access = CXXRecordDecl::MergeAccess(base->getAccessSpecifier(), access);
+
+  // If we're operating on a field, the object type is the type of the field.
+  } else {
+    objectTy = S.Context.getTypeDeclType(target->getParent());
+  }
+
+  return S.isSpecialMemberAccessibleForDeletion(target, access, objectTy);
+}
+
+/// Check whether we should delete a special member due to the implicit
+/// definition containing a call to a special member of a subobject.
+bool SpecialMemberDeletionInfo::shouldDeleteForSubobjectCall(
+    Subobject Subobj, Sema::SpecialMemberOverloadResult *SMOR,
+    bool IsDtorCallInCtor) {
+  CXXMethodDecl *Decl = SMOR->getMethod();
+  FieldDecl *Field = Subobj.dyn_cast<FieldDecl*>();
+
+  int DiagKind = -1;
+
+  if (SMOR->getKind() == Sema::SpecialMemberOverloadResult::NoMemberOrDeleted)
+    DiagKind = !Decl ? 0 : 1;
+  else if (SMOR->getKind() == Sema::SpecialMemberOverloadResult::Ambiguous)
+    DiagKind = 2;
+  else if (!isAccessible(Subobj, Decl))
+    DiagKind = 3;
+  else if (!IsDtorCallInCtor && Field && Field->getParent()->isUnion() &&
+           !Decl->isTrivial()) {
+    // A member of a union must have a trivial corresponding special member.
+    // As a weird special case, a destructor call from a union's constructor
+    // must be accessible and non-deleted, but need not be trivial. Such a
+    // destructor is never actually called, but is semantically checked as
+    // if it were.
+    DiagKind = 4;
+  }
+
+  if (DiagKind == -1)
+    return false;
+
+  if (Diagnose) {
+    if (Field) {
+      S.Diag(Field->getLocation(),
+             diag::note_deleted_special_member_class_subobject)
+        << CSM << MD->getParent() << /*IsField*/true
+        << Field << DiagKind << IsDtorCallInCtor;
+    } else {
+      CXXBaseSpecifier *Base = Subobj.get<CXXBaseSpecifier*>();
+      S.Diag(Base->getLocStart(),
+             diag::note_deleted_special_member_class_subobject)
+        << CSM << MD->getParent() << /*IsField*/false
+        << Base->getType() << DiagKind << IsDtorCallInCtor;
+    }
+
+    if (DiagKind == 1)
+      S.NoteDeletedFunction(Decl);
+    // FIXME: Explain inaccessibility if DiagKind == 3.
+  }
+
+  return true;
+}
+
+/// Check whether we should delete a special member function due to having a
+/// direct or virtual base class or static data member of class type M.
+bool SpecialMemberDeletionInfo::shouldDeleteForClassSubobject(
+    CXXRecordDecl *Class, Subobject Subobj) {
+  FieldDecl *Field = Subobj.dyn_cast<FieldDecl*>();
+
+  // C++11 [class.ctor]p5:
+  // -- any direct or virtual base class, or non-static data member with no
+  //    brace-or-equal-initializer, has class type M (or array thereof) and
+  //    either M has no default constructor or overload resolution as applied
+  //    to M's default constructor results in an ambiguity or in a function
+  //    that is deleted or inaccessible
+  // C++11 [class.copy]p11, C++11 [class.copy]p23:
+  // -- a direct or virtual base class B that cannot be copied/moved because
+  //    overload resolution, as applied to B's corresponding special member,
+  //    results in an ambiguity or a function that is deleted or inaccessible
+  //    from the defaulted special member
+  // C++11 [class.dtor]p5:
+  // -- any direct or virtual base class [...] has a type with a destructor
+  //    that is deleted or inaccessible
+  if (!(CSM == Sema::CXXDefaultConstructor &&
+        Field && Field->hasInClassInitializer()) &&
+      shouldDeleteForSubobjectCall(Subobj, lookupIn(Class), false))
+    return true;
+
+  // C++11 [class.ctor]p5, C++11 [class.copy]p11:
+  // -- any direct or virtual base class or non-static data member has a
+  //    type with a destructor that is deleted or inaccessible
+  if (IsConstructor) {
+    Sema::SpecialMemberOverloadResult *SMOR =
+        S.LookupSpecialMember(Class, Sema::CXXDestructor,
+                              false, false, false, false, false);
+    if (shouldDeleteForSubobjectCall(Subobj, SMOR, true))
+      return true;
+  }
+
+  return false;
+}
+
+/// Check whether we should delete a special member function due to the class
+/// having a particular direct or virtual base class.
+bool SpecialMemberDeletionInfo::shouldDeleteForBase(CXXBaseSpecifier *Base) {
+  CXXRecordDecl *BaseClass = Base->getType()->getAsCXXRecordDecl();
+  return shouldDeleteForClassSubobject(BaseClass, Base);
+}
+
+/// Check whether we should delete a special member function due to the class
+/// having a particular non-static data member.
+bool SpecialMemberDeletionInfo::shouldDeleteForField(FieldDecl *FD) {
+  QualType FieldType = S.Context.getBaseElementType(FD->getType());
+  CXXRecordDecl *FieldRecord = FieldType->getAsCXXRecordDecl();
+
+  if (CSM == Sema::CXXDefaultConstructor) {
+    // For a default constructor, all references must be initialized in-class
+    // and, if a union, it must have a non-const member.
+    if (FieldType->isReferenceType() && !FD->hasInClassInitializer()) {
+      if (Diagnose)
+        S.Diag(FD->getLocation(), diag::note_deleted_default_ctor_uninit_field)
+          << MD->getParent() << FD << FieldType << /*Reference*/0;
+      return true;
+    }
+    // C++11 [class.ctor]p5: any non-variant non-static data member of
+    // const-qualified type (or array thereof) with no
+    // brace-or-equal-initializer does not have a user-provided default
+    // constructor.
+    if (!inUnion() && FieldType.isConstQualified() &&
+        !FD->hasInClassInitializer() &&
+        (!FieldRecord || !FieldRecord->hasUserProvidedDefaultConstructor())) {
+      if (Diagnose)
+        S.Diag(FD->getLocation(), diag::note_deleted_default_ctor_uninit_field)
+          << MD->getParent() << FD << FieldType << /*Const*/1;
+      return true;
+    }
+
+    if (inUnion() && !FieldType.isConstQualified())
+      AllFieldsAreConst = false;
+  } else if (CSM == Sema::CXXCopyConstructor) {
+    // For a copy constructor, data members must not be of rvalue reference
+    // type.
+    if (FieldType->isRValueReferenceType()) {
+      if (Diagnose)
+        S.Diag(FD->getLocation(), diag::note_deleted_copy_ctor_rvalue_reference)
+          << MD->getParent() << FD << FieldType;
+      return true;
+    }
+  } else if (IsAssignment) {
+    // For an assignment operator, data members must not be of reference type.
+    if (FieldType->isReferenceType()) {
+      if (Diagnose)
+        S.Diag(FD->getLocation(), diag::note_deleted_assign_field)
+          << IsMove << MD->getParent() << FD << FieldType << /*Reference*/0;
+      return true;
+    }
+    if (!FieldRecord && FieldType.isConstQualified()) {
+      // C++11 [class.copy]p23:
+      // -- a non-static data member of const non-class type (or array thereof)
+      if (Diagnose)
+        S.Diag(FD->getLocation(), diag::note_deleted_assign_field)
+          << IsMove << MD->getParent() << FD << FieldType << /*Const*/1;
+      return true;
+    }
+  }
+
+  if (FieldRecord) {
+    // Some additional restrictions exist on the variant members.
+    if (!inUnion() && FieldRecord->isUnion() &&
+        FieldRecord->isAnonymousStructOrUnion()) {
+      bool AllVariantFieldsAreConst = true;
+
+      // FIXME: Handle anonymous unions declared within anonymous unions.
+      for (CXXRecordDecl::field_iterator UI = FieldRecord->field_begin(),
+                                         UE = FieldRecord->field_end();
+           UI != UE; ++UI) {
+        QualType UnionFieldType = S.Context.getBaseElementType(UI->getType());
+
+        if (!UnionFieldType.isConstQualified())
+          AllVariantFieldsAreConst = false;
+
+        CXXRecordDecl *UnionFieldRecord = UnionFieldType->getAsCXXRecordDecl();
+        if (UnionFieldRecord &&
+            shouldDeleteForClassSubobject(UnionFieldRecord, *UI))
+          return true;
+      }
+
+      // At least one member in each anonymous union must be non-const
+      if (CSM == Sema::CXXDefaultConstructor && AllVariantFieldsAreConst &&
+          FieldRecord->field_begin() != FieldRecord->field_end()) {
+        if (Diagnose)
+          S.Diag(FieldRecord->getLocation(),
+                 diag::note_deleted_default_ctor_all_const)
+            << MD->getParent() << /*anonymous union*/1;
+        return true;
+      }
+
+      // Don't check the implicit member of the anonymous union type.
+      // This is technically non-conformant, but sanity demands it.
+      return false;
+    }
+
+    if (shouldDeleteForClassSubobject(FieldRecord, FD))
+      return true;
+  }
+
+  return false;
+}
+
+/// C++11 [class.ctor] p5:
+///   A defaulted default constructor for a class X is defined as deleted if
+/// X is a union and all of its variant members are of const-qualified type.
+bool SpecialMemberDeletionInfo::shouldDeleteForAllConstMembers() {
+  // This is a silly definition, because it gives an empty union a deleted
+  // default constructor. Don't do that.
+  if (CSM == Sema::CXXDefaultConstructor && inUnion() && AllFieldsAreConst &&
+      (MD->getParent()->field_begin() != MD->getParent()->field_end())) {
+    if (Diagnose)
+      S.Diag(MD->getParent()->getLocation(),
+             diag::note_deleted_default_ctor_all_const)
+        << MD->getParent() << /*not anonymous union*/0;
+    return true;
+  }
+  return false;
+}
+
+/// Determine whether a defaulted special member function should be defined as
+/// deleted, as specified in C++11 [class.ctor]p5, C++11 [class.copy]p11,
+/// C++11 [class.copy]p23, and C++11 [class.dtor]p5.
+bool Sema::ShouldDeleteSpecialMember(CXXMethodDecl *MD, CXXSpecialMember CSM,
+                                     bool Diagnose) {
+  assert(!MD->isInvalidDecl());
+  CXXRecordDecl *RD = MD->getParent();
+  assert(!RD->isDependentType() && "do deletion after instantiation");
+  if (!LangOpts.CPlusPlus0x || RD->isInvalidDecl())
+    return false;
+
+  // C++11 [expr.lambda.prim]p19:
+  //   The closure type associated with a lambda-expression has a
+  //   deleted (8.4.3) default constructor and a deleted copy
+  //   assignment operator.
+  if (RD->isLambda() &&
+      (CSM == CXXDefaultConstructor || CSM == CXXCopyAssignment)) {
+    if (Diagnose)
+      Diag(RD->getLocation(), diag::note_lambda_decl);
+    return true;
+  }
+
+  // For an anonymous struct or union, the copy and assignment special members
+  // will never be used, so skip the check. For an anonymous union declared at
+  // namespace scope, the constructor and destructor are used.
+  if (CSM != CXXDefaultConstructor && CSM != CXXDestructor &&
+      RD->isAnonymousStructOrUnion())
+    return false;
+
+  // C++11 [class.copy]p7, p18:
+  //   If the class definition declares a move constructor or move assignment
+  //   operator, an implicitly declared copy constructor or copy assignment
+  //   operator is defined as deleted.
+  if (MD->isImplicit() &&
+      (CSM == CXXCopyConstructor || CSM == CXXCopyAssignment)) {
+    CXXMethodDecl *UserDeclaredMove = 0;
+
+    // In Microsoft mode, a user-declared move only causes the deletion of the
+    // corresponding copy operation, not both copy operations.
+    if (RD->hasUserDeclaredMoveConstructor() &&
+        (!getLangOpts().MicrosoftMode || CSM == CXXCopyConstructor)) {
+      if (!Diagnose) return true;
+      UserDeclaredMove = RD->getMoveConstructor();
+      assert(UserDeclaredMove);
+    } else if (RD->hasUserDeclaredMoveAssignment() &&
+               (!getLangOpts().MicrosoftMode || CSM == CXXCopyAssignment)) {
+      if (!Diagnose) return true;
+      UserDeclaredMove = RD->getMoveAssignmentOperator();
+      assert(UserDeclaredMove);
+    }
+
+    if (UserDeclaredMove) {
+      Diag(UserDeclaredMove->getLocation(),
+           diag::note_deleted_copy_user_declared_move)
+        << (CSM == CXXCopyAssignment) << RD
+        << UserDeclaredMove->isMoveAssignmentOperator();
+      return true;
+    }
+  }
+
+  // Do access control from the special member function
+  ContextRAII MethodContext(*this, MD);
+
+  // C++11 [class.dtor]p5:
+  // -- for a virtual destructor, lookup of the non-array deallocation function
+  //    results in an ambiguity or in a function that is deleted or inaccessible
+  if (CSM == CXXDestructor && MD->isVirtual()) {
+    FunctionDecl *OperatorDelete = 0;
+    DeclarationName Name =
+      Context.DeclarationNames.getCXXOperatorName(OO_Delete);
+    if (FindDeallocationFunction(MD->getLocation(), MD->getParent(), Name,
+                                 OperatorDelete, false)) {
+      if (Diagnose)
+        Diag(RD->getLocation(), diag::note_deleted_dtor_no_operator_delete);
+      return true;
+    }
+  }
+
+  SpecialMemberDeletionInfo SMI(*this, MD, CSM, Diagnose);
+
+  for (CXXRecordDecl::base_class_iterator BI = RD->bases_begin(),
+                                          BE = RD->bases_end(); BI != BE; ++BI)
+    if (!BI->isVirtual() &&
+        SMI.shouldDeleteForBase(BI))
+      return true;
+
+  for (CXXRecordDecl::base_class_iterator BI = RD->vbases_begin(),
+                                          BE = RD->vbases_end(); BI != BE; ++BI)
+    if (SMI.shouldDeleteForBase(BI))
+      return true;
+
+  for (CXXRecordDecl::field_iterator FI = RD->field_begin(),
+                                     FE = RD->field_end(); FI != FE; ++FI)
+    if (!FI->isInvalidDecl() && !FI->isUnnamedBitfield() &&
+        SMI.shouldDeleteForField(*FI))
+      return true;
+
+  if (SMI.shouldDeleteForAllConstMembers())
+    return true;
+
+  return false;
+}
+
+/// \brief Data used with FindHiddenVirtualMethod
+namespace {
+  struct FindHiddenVirtualMethodData {
+    Sema *S;
+    CXXMethodDecl *Method;
+    llvm::SmallPtrSet<const CXXMethodDecl *, 8> OverridenAndUsingBaseMethods;
+    SmallVector<CXXMethodDecl *, 8> OverloadedMethods;
+  };
+}
+
+/// \brief Member lookup function that determines whether a given C++
+/// method overloads virtual methods in a base class without overriding any,
+/// to be used with CXXRecordDecl::lookupInBases().
+static bool FindHiddenVirtualMethod(const CXXBaseSpecifier *Specifier,
+                                    CXXBasePath &Path,
+                                    void *UserData) {
+  RecordDecl *BaseRecord = Specifier->getType()->getAs<RecordType>()->getDecl();
+
+  FindHiddenVirtualMethodData &Data
+    = *static_cast<FindHiddenVirtualMethodData*>(UserData);
+
+  DeclarationName Name = Data.Method->getDeclName();
+  assert(Name.getNameKind() == DeclarationName::Identifier);
+
+  bool foundSameNameMethod = false;
+  SmallVector<CXXMethodDecl *, 8> overloadedMethods;
+  for (Path.Decls = BaseRecord->lookup(Name);
+       Path.Decls.first != Path.Decls.second;
+       ++Path.Decls.first) {
+    NamedDecl *D = *Path.Decls.first;
+    if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(D)) {
+      MD = MD->getCanonicalDecl();
+      foundSameNameMethod = true;
+      // Interested only in hidden virtual methods.
+      if (!MD->isVirtual())
+        continue;
+      // If the method we are checking overrides a method from its base
+      // don't warn about the other overloaded methods.
+      if (!Data.S->IsOverload(Data.Method, MD, false))
+        return true;
+      // Collect the overload only if its hidden.
+      if (!Data.OverridenAndUsingBaseMethods.count(MD))
+        overloadedMethods.push_back(MD);
+    }
+  }
+
+  if (foundSameNameMethod)
+    Data.OverloadedMethods.append(overloadedMethods.begin(),
+                                   overloadedMethods.end());
+  return foundSameNameMethod;
+}
+
+/// \brief See if a method overloads virtual methods in a base class without
+/// overriding any.
+void Sema::DiagnoseHiddenVirtualMethods(CXXRecordDecl *DC, CXXMethodDecl *MD) {
+  if (Diags.getDiagnosticLevel(diag::warn_overloaded_virtual,
+                               MD->getLocation()) == DiagnosticsEngine::Ignored)
+    return;
+  if (MD->getDeclName().getNameKind() != DeclarationName::Identifier)
+    return;
+
+  CXXBasePaths Paths(/*FindAmbiguities=*/true, // true to look in all bases.
+                     /*bool RecordPaths=*/false,
+                     /*bool DetectVirtual=*/false);
+  FindHiddenVirtualMethodData Data;
+  Data.Method = MD;
+  Data.S = this;
+
+  // Keep the base methods that were overriden or introduced in the subclass
+  // by 'using' in a set. A base method not in this set is hidden.
+  for (DeclContext::lookup_result res = DC->lookup(MD->getDeclName());
+       res.first != res.second; ++res.first) {
+    if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(*res.first))
+      for (CXXMethodDecl::method_iterator I = MD->begin_overridden_methods(),
+                                          E = MD->end_overridden_methods();
+           I != E; ++I)
+        Data.OverridenAndUsingBaseMethods.insert((*I)->getCanonicalDecl());
+    if (UsingShadowDecl *shad = dyn_cast<UsingShadowDecl>(*res.first))
+      if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(shad->getTargetDecl()))
+        Data.OverridenAndUsingBaseMethods.insert(MD->getCanonicalDecl());
+  }
+
+  if (DC->lookupInBases(&FindHiddenVirtualMethod, &Data, Paths) &&
+      !Data.OverloadedMethods.empty()) {
+    Diag(MD->getLocation(), diag::warn_overloaded_virtual)
+      << MD << (Data.OverloadedMethods.size() > 1);
+
+    for (unsigned i = 0, e = Data.OverloadedMethods.size(); i != e; ++i) {
+      CXXMethodDecl *overloadedMD = Data.OverloadedMethods[i];
+      Diag(overloadedMD->getLocation(),
+           diag::note_hidden_overloaded_virtual_declared_here) << overloadedMD;
+    }
+  }
+}
+
+void Sema::ActOnFinishCXXMemberSpecification(Scope* S, SourceLocation RLoc,
+                                             Decl *TagDecl,
+                                             SourceLocation LBrac,
+                                             SourceLocation RBrac,
+                                             AttributeList *AttrList) {
+  if (!TagDecl)
+    return;
+
+  AdjustDeclIfTemplate(TagDecl);
+
+  ActOnFields(S, RLoc, TagDecl, llvm::makeArrayRef(
+              // strict aliasing violation!
+              reinterpret_cast<Decl**>(FieldCollector->getCurFields()),
+              FieldCollector->getCurNumFields()), LBrac, RBrac, AttrList);
+
+  CheckCompletedCXXClass(
+                        dyn_cast_or_null<CXXRecordDecl>(TagDecl));
+}
+
+/// AddImplicitlyDeclaredMembersToClass - Adds any implicitly-declared
+/// special functions, such as the default constructor, copy
+/// constructor, or destructor, to the given C++ class (C++
+/// [special]p1).  This routine can only be executed just before the
+/// definition of the class is complete.
+void Sema::AddImplicitlyDeclaredMembersToClass(CXXRecordDecl *ClassDecl) {
+  if (!ClassDecl->hasUserDeclaredConstructor())
+    ++ASTContext::NumImplicitDefaultConstructors;
+
+  if (!ClassDecl->hasUserDeclaredCopyConstructor())
+    ++ASTContext::NumImplicitCopyConstructors;
+
+  if (getLangOpts().CPlusPlus0x && ClassDecl->needsImplicitMoveConstructor())
+    ++ASTContext::NumImplicitMoveConstructors;
+
+  if (!ClassDecl->hasUserDeclaredCopyAssignment()) {
+    ++ASTContext::NumImplicitCopyAssignmentOperators;
+    
+    // If we have a dynamic class, then the copy assignment operator may be 
+    // virtual, so we have to declare it immediately. This ensures that, e.g.,
+    // it shows up in the right place in the vtable and that we diagnose 
+    // problems with the implicit exception specification.    
+    if (ClassDecl->isDynamicClass())
+      DeclareImplicitCopyAssignment(ClassDecl);
+  }
+
+  if (getLangOpts().CPlusPlus0x && ClassDecl->needsImplicitMoveAssignment()) {
+    ++ASTContext::NumImplicitMoveAssignmentOperators;
+
+    // Likewise for the move assignment operator.
+    if (ClassDecl->isDynamicClass())
+      DeclareImplicitMoveAssignment(ClassDecl);
+  }
+
+  if (!ClassDecl->hasUserDeclaredDestructor()) {
+    ++ASTContext::NumImplicitDestructors;
+    
+    // If we have a dynamic class, then the destructor may be virtual, so we 
+    // have to declare the destructor immediately. This ensures that, e.g., it
+    // shows up in the right place in the vtable and that we diagnose problems
+    // with the implicit exception specification.
+    if (ClassDecl->isDynamicClass())
+      DeclareImplicitDestructor(ClassDecl);
+  }
+}
+
+void Sema::ActOnReenterDeclaratorTemplateScope(Scope *S, DeclaratorDecl *D) {
+  if (!D)
+    return;
+
+  int NumParamList = D->getNumTemplateParameterLists();
+  for (int i = 0; i < NumParamList; i++) {
+    TemplateParameterList* Params = D->getTemplateParameterList(i);
+    for (TemplateParameterList::iterator Param = Params->begin(),
+                                      ParamEnd = Params->end();
+          Param != ParamEnd; ++Param) {
+      NamedDecl *Named = cast<NamedDecl>(*Param);
+      if (Named->getDeclName()) {
+        S->AddDecl(Named);
+        IdResolver.AddDecl(Named);
+      }
+    }
+  }
+}
+
+void Sema::ActOnReenterTemplateScope(Scope *S, Decl *D) {
+  if (!D)
+    return;
+  
+  TemplateParameterList *Params = 0;
+  if (TemplateDecl *Template = dyn_cast<TemplateDecl>(D))
+    Params = Template->getTemplateParameters();
+  else if (ClassTemplatePartialSpecializationDecl *PartialSpec
+           = dyn_cast<ClassTemplatePartialSpecializationDecl>(D))
+    Params = PartialSpec->getTemplateParameters();
+  else
+    return;
+
+  for (TemplateParameterList::iterator Param = Params->begin(),
+                                    ParamEnd = Params->end();
+       Param != ParamEnd; ++Param) {
+    NamedDecl *Named = cast<NamedDecl>(*Param);
+    if (Named->getDeclName()) {
+      S->AddDecl(Named);
+      IdResolver.AddDecl(Named);
+    }
+  }
+}
+
+void Sema::ActOnStartDelayedMemberDeclarations(Scope *S, Decl *RecordD) {
+  if (!RecordD) return;
+  AdjustDeclIfTemplate(RecordD);
+  CXXRecordDecl *Record = cast<CXXRecordDecl>(RecordD);
+  PushDeclContext(S, Record);
+}
+
+void Sema::ActOnFinishDelayedMemberDeclarations(Scope *S, Decl *RecordD) {
+  if (!RecordD) return;
+  PopDeclContext();
+}
+
+/// ActOnStartDelayedCXXMethodDeclaration - We have completed
+/// parsing a top-level (non-nested) C++ class, and we are now
+/// parsing those parts of the given Method declaration that could
+/// not be parsed earlier (C++ [class.mem]p2), such as default
+/// arguments. This action should enter the scope of the given
+/// Method declaration as if we had just parsed the qualified method
+/// name. However, it should not bring the parameters into scope;
+/// that will be performed by ActOnDelayedCXXMethodParameter.
+void Sema::ActOnStartDelayedCXXMethodDeclaration(Scope *S, Decl *MethodD) {
+}
+
+/// ActOnDelayedCXXMethodParameter - We've already started a delayed
+/// C++ method declaration. We're (re-)introducing the given
+/// function parameter into scope for use in parsing later parts of
+/// the method declaration. For example, we could see an
+/// ActOnParamDefaultArgument event for this parameter.
+void Sema::ActOnDelayedCXXMethodParameter(Scope *S, Decl *ParamD) {
+  if (!ParamD)
+    return;
+
+  ParmVarDecl *Param = cast<ParmVarDecl>(ParamD);
+
+  // If this parameter has an unparsed default argument, clear it out
+  // to make way for the parsed default argument.
+  if (Param->hasUnparsedDefaultArg())
+    Param->setDefaultArg(0);
+
+  S->AddDecl(Param);
+  if (Param->getDeclName())
+    IdResolver.AddDecl(Param);
+}
+
+/// ActOnFinishDelayedCXXMethodDeclaration - We have finished
+/// processing the delayed method declaration for Method. The method
+/// declaration is now considered finished. There may be a separate
+/// ActOnStartOfFunctionDef action later (not necessarily
+/// immediately!) for this method, if it was also defined inside the
+/// class body.
+void Sema::ActOnFinishDelayedCXXMethodDeclaration(Scope *S, Decl *MethodD) {
+  if (!MethodD)
+    return;
+
+  AdjustDeclIfTemplate(MethodD);
+
+  FunctionDecl *Method = cast<FunctionDecl>(MethodD);
+
+  // Now that we have our default arguments, check the constructor
+  // again. It could produce additional diagnostics or affect whether
+  // the class has implicitly-declared destructors, among other
+  // things.
+  if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(Method))
+    CheckConstructor(Constructor);
+
+  // Check the default arguments, which we may have added.
+  if (!Method->isInvalidDecl())
+    CheckCXXDefaultArguments(Method);
+}
+
+/// CheckConstructorDeclarator - Called by ActOnDeclarator to check
+/// the well-formedness of the constructor declarator @p D with type @p
+/// R. If there are any errors in the declarator, this routine will
+/// emit diagnostics and set the invalid bit to true.  In any case, the type
+/// will be updated to reflect a well-formed type for the constructor and
+/// returned.
+QualType Sema::CheckConstructorDeclarator(Declarator &D, QualType R,
+                                          StorageClass &SC) {
+  bool isVirtual = D.getDeclSpec().isVirtualSpecified();
+
+  // C++ [class.ctor]p3:
+  //   A constructor shall not be virtual (10.3) or static (9.4). A
+  //   constructor can be invoked for a const, volatile or const
+  //   volatile object. A constructor shall not be declared const,
+  //   volatile, or const volatile (9.3.2).
+  if (isVirtual) {
+    if (!D.isInvalidType())
+      Diag(D.getIdentifierLoc(), diag::err_constructor_cannot_be)
+        << "virtual" << SourceRange(D.getDeclSpec().getVirtualSpecLoc())
+        << SourceRange(D.getIdentifierLoc());
+    D.setInvalidType();
+  }
+  if (SC == SC_Static) {
+    if (!D.isInvalidType())
+      Diag(D.getIdentifierLoc(), diag::err_constructor_cannot_be)
+        << "static" << SourceRange(D.getDeclSpec().getStorageClassSpecLoc())
+        << SourceRange(D.getIdentifierLoc());
+    D.setInvalidType();
+    SC = SC_None;
+  }
+
+  DeclaratorChunk::FunctionTypeInfo &FTI = D.getFunctionTypeInfo();
+  if (FTI.TypeQuals != 0) {
+    if (FTI.TypeQuals & Qualifiers::Const)
+      Diag(D.getIdentifierLoc(), diag::err_invalid_qualified_constructor)
+        << "const" << SourceRange(D.getIdentifierLoc());
+    if (FTI.TypeQuals & Qualifiers::Volatile)
+      Diag(D.getIdentifierLoc(), diag::err_invalid_qualified_constructor)
+        << "volatile" << SourceRange(D.getIdentifierLoc());
+    if (FTI.TypeQuals & Qualifiers::Restrict)
+      Diag(D.getIdentifierLoc(), diag::err_invalid_qualified_constructor)
+        << "restrict" << SourceRange(D.getIdentifierLoc());
+    D.setInvalidType();
+  }
+
+  // C++0x [class.ctor]p4:
+  //   A constructor shall not be declared with a ref-qualifier.
+  if (FTI.hasRefQualifier()) {
+    Diag(FTI.getRefQualifierLoc(), diag::err_ref_qualifier_constructor)
+      << FTI.RefQualifierIsLValueRef 
+      << FixItHint::CreateRemoval(FTI.getRefQualifierLoc());
+    D.setInvalidType();
+  }
+  
+  // Rebuild the function type "R" without any type qualifiers (in
+  // case any of the errors above fired) and with "void" as the
+  // return type, since constructors don't have return types.
+  const FunctionProtoType *Proto = R->getAs<FunctionProtoType>();
+  if (Proto->getResultType() == Context.VoidTy && !D.isInvalidType())
+    return R;
+
+  FunctionProtoType::ExtProtoInfo EPI = Proto->getExtProtoInfo();
+  EPI.TypeQuals = 0;
+  EPI.RefQualifier = RQ_None;
+  
+  return Context.getFunctionType(Context.VoidTy, Proto->arg_type_begin(),
+                                 Proto->getNumArgs(), EPI);
+}
+
+/// CheckConstructor - Checks a fully-formed constructor for
+/// well-formedness, issuing any diagnostics required. Returns true if
+/// the constructor declarator is invalid.
+void Sema::CheckConstructor(CXXConstructorDecl *Constructor) {
+  CXXRecordDecl *ClassDecl
+    = dyn_cast<CXXRecordDecl>(Constructor->getDeclContext());
+  if (!ClassDecl)
+    return Constructor->setInvalidDecl();
+
+  // C++ [class.copy]p3:
+  //   A declaration of a constructor for a class X is ill-formed if
+  //   its first parameter is of type (optionally cv-qualified) X and
+  //   either there are no other parameters or else all other
+  //   parameters have default arguments.
+  if (!Constructor->isInvalidDecl() &&
+      ((Constructor->getNumParams() == 1) ||
+       (Constructor->getNumParams() > 1 &&
+        Constructor->getParamDecl(1)->hasDefaultArg())) &&
+      Constructor->getTemplateSpecializationKind()
+                                              != TSK_ImplicitInstantiation) {
+    QualType ParamType = Constructor->getParamDecl(0)->getType();
+    QualType ClassTy = Context.getTagDeclType(ClassDecl);
+    if (Context.getCanonicalType(ParamType).getUnqualifiedType() == ClassTy) {
+      SourceLocation ParamLoc = Constructor->getParamDecl(0)->getLocation();
+      const char *ConstRef 
+        = Constructor->getParamDecl(0)->getIdentifier() ? "const &" 
+                                                        : " const &";
+      Diag(ParamLoc, diag::err_constructor_byvalue_arg)
+        << FixItHint::CreateInsertion(ParamLoc, ConstRef);
+
+      // FIXME: Rather that making the constructor invalid, we should endeavor
+      // to fix the type.
+      Constructor->setInvalidDecl();
+    }
+  }
+}
+
+/// CheckDestructor - Checks a fully-formed destructor definition for
+/// well-formedness, issuing any diagnostics required.  Returns true
+/// on error.
+bool Sema::CheckDestructor(CXXDestructorDecl *Destructor) {
+  CXXRecordDecl *RD = Destructor->getParent();
+  
+  if (Destructor->isVirtual()) {
+    SourceLocation Loc;
+    
+    if (!Destructor->isImplicit())
+      Loc = Destructor->getLocation();
+    else
+      Loc = RD->getLocation();
+    
+    // If we have a virtual destructor, look up the deallocation function
+    FunctionDecl *OperatorDelete = 0;
+    DeclarationName Name = 
+    Context.DeclarationNames.getCXXOperatorName(OO_Delete);
+    if (FindDeallocationFunction(Loc, RD, Name, OperatorDelete))
+      return true;
+
+    MarkFunctionReferenced(Loc, OperatorDelete);
+    
+    Destructor->setOperatorDelete(OperatorDelete);
+  }
+  
+  return false;
+}
+
+static inline bool
+FTIHasSingleVoidArgument(DeclaratorChunk::FunctionTypeInfo &FTI) {
+  return (FTI.NumArgs == 1 && !FTI.isVariadic && FTI.ArgInfo[0].Ident == 0 &&
+          FTI.ArgInfo[0].Param &&
+          cast<ParmVarDecl>(FTI.ArgInfo[0].Param)->getType()->isVoidType());
+}
+
+/// CheckDestructorDeclarator - Called by ActOnDeclarator to check
+/// the well-formednes of the destructor declarator @p D with type @p
+/// R. If there are any errors in the declarator, this routine will
+/// emit diagnostics and set the declarator to invalid.  Even if this happens,
+/// will be updated to reflect a well-formed type for the destructor and
+/// returned.
+QualType Sema::CheckDestructorDeclarator(Declarator &D, QualType R,
+                                         StorageClass& SC) {
+  // C++ [class.dtor]p1:
+  //   [...] A typedef-name that names a class is a class-name
+  //   (7.1.3); however, a typedef-name that names a class shall not
+  //   be used as the identifier in the declarator for a destructor
+  //   declaration.
+  QualType DeclaratorType = GetTypeFromParser(D.getName().DestructorName);
+  if (const TypedefType *TT = DeclaratorType->getAs<TypedefType>())
+    Diag(D.getIdentifierLoc(), diag::err_destructor_typedef_name)
+      << DeclaratorType << isa<TypeAliasDecl>(TT->getDecl());
+  else if (const TemplateSpecializationType *TST =
+             DeclaratorType->getAs<TemplateSpecializationType>())
+    if (TST->isTypeAlias())
+      Diag(D.getIdentifierLoc(), diag::err_destructor_typedef_name)
+        << DeclaratorType << 1;
+
+  // C++ [class.dtor]p2:
+  //   A destructor is used to destroy objects of its class type. A
+  //   destructor takes no parameters, and no return type can be
+  //   specified for it (not even void). The address of a destructor
+  //   shall not be taken. A destructor shall not be static. A
+  //   destructor can be invoked for a const, volatile or const
+  //   volatile object. A destructor shall not be declared const,
+  //   volatile or const volatile (9.3.2).
+  if (SC == SC_Static) {
+    if (!D.isInvalidType())
+      Diag(D.getIdentifierLoc(), diag::err_destructor_cannot_be)
+        << "static" << SourceRange(D.getDeclSpec().getStorageClassSpecLoc())
+        << SourceRange(D.getIdentifierLoc())
+        << FixItHint::CreateRemoval(D.getDeclSpec().getStorageClassSpecLoc());
+    
+    SC = SC_None;
+  }
+  if (D.getDeclSpec().hasTypeSpecifier() && !D.isInvalidType()) {
+    // Destructors don't have return types, but the parser will
+    // happily parse something like:
+    //
+    //   class X {
+    //     float ~X();
+    //   };
+    //
+    // The return type will be eliminated later.
+    Diag(D.getIdentifierLoc(), diag::err_destructor_return_type)
+      << SourceRange(D.getDeclSpec().getTypeSpecTypeLoc())
+      << SourceRange(D.getIdentifierLoc());
+  }
+
+  DeclaratorChunk::FunctionTypeInfo &FTI = D.getFunctionTypeInfo();
+  if (FTI.TypeQuals != 0 && !D.isInvalidType()) {
+    if (FTI.TypeQuals & Qualifiers::Const)
+      Diag(D.getIdentifierLoc(), diag::err_invalid_qualified_destructor)
+        << "const" << SourceRange(D.getIdentifierLoc());
+    if (FTI.TypeQuals & Qualifiers::Volatile)
+      Diag(D.getIdentifierLoc(), diag::err_invalid_qualified_destructor)
+        << "volatile" << SourceRange(D.getIdentifierLoc());
+    if (FTI.TypeQuals & Qualifiers::Restrict)
+      Diag(D.getIdentifierLoc(), diag::err_invalid_qualified_destructor)
+        << "restrict" << SourceRange(D.getIdentifierLoc());
+    D.setInvalidType();
+  }
+
+  // C++0x [class.dtor]p2:
+  //   A destructor shall not be declared with a ref-qualifier.
+  if (FTI.hasRefQualifier()) {
+    Diag(FTI.getRefQualifierLoc(), diag::err_ref_qualifier_destructor)
+      << FTI.RefQualifierIsLValueRef
+      << FixItHint::CreateRemoval(FTI.getRefQualifierLoc());
+    D.setInvalidType();
+  }
+  
+  // Make sure we don't have any parameters.
+  if (FTI.NumArgs > 0 && !FTIHasSingleVoidArgument(FTI)) {
+    Diag(D.getIdentifierLoc(), diag::err_destructor_with_params);
+
+    // Delete the parameters.
+    FTI.freeArgs();
+    D.setInvalidType();
+  }
+
+  // Make sure the destructor isn't variadic.
+  if (FTI.isVariadic) {
+    Diag(D.getIdentifierLoc(), diag::err_destructor_variadic);
+    D.setInvalidType();
+  }
+
+  // Rebuild the function type "R" without any type qualifiers or
+  // parameters (in case any of the errors above fired) and with
+  // "void" as the return type, since destructors don't have return
+  // types. 
+  if (!D.isInvalidType())
+    return R;
+
+  const FunctionProtoType *Proto = R->getAs<FunctionProtoType>();
+  FunctionProtoType::ExtProtoInfo EPI = Proto->getExtProtoInfo();
+  EPI.Variadic = false;
+  EPI.TypeQuals = 0;
+  EPI.RefQualifier = RQ_None;
+  return Context.getFunctionType(Context.VoidTy, 0, 0, EPI);
+}
+
+/// CheckConversionDeclarator - Called by ActOnDeclarator to check the
+/// well-formednes of the conversion function declarator @p D with
+/// type @p R. If there are any errors in the declarator, this routine
+/// will emit diagnostics and return true. Otherwise, it will return
+/// false. Either way, the type @p R will be updated to reflect a
+/// well-formed type for the conversion operator.
+void Sema::CheckConversionDeclarator(Declarator &D, QualType &R,
+                                     StorageClass& SC) {
+  // C++ [class.conv.fct]p1:
+  //   Neither parameter types nor return type can be specified. The
+  //   type of a conversion function (8.3.5) is "function taking no
+  //   parameter returning conversion-type-id."
+  if (SC == SC_Static) {
+    if (!D.isInvalidType())
+      Diag(D.getIdentifierLoc(), diag::err_conv_function_not_member)
+        << "static" << SourceRange(D.getDeclSpec().getStorageClassSpecLoc())
+        << SourceRange(D.getIdentifierLoc());
+    D.setInvalidType();
+    SC = SC_None;
+  }
+
+  QualType ConvType = GetTypeFromParser(D.getName().ConversionFunctionId);
+
+  if (D.getDeclSpec().hasTypeSpecifier() && !D.isInvalidType()) {
+    // Conversion functions don't have return types, but the parser will
+    // happily parse something like:
+    //
+    //   class X {
+    //     float operator bool();
+    //   };
+    //
+    // The return type will be changed later anyway.
+    Diag(D.getIdentifierLoc(), diag::err_conv_function_return_type)
+      << SourceRange(D.getDeclSpec().getTypeSpecTypeLoc())
+      << SourceRange(D.getIdentifierLoc());
+    D.setInvalidType();
+  }
+
+  const FunctionProtoType *Proto = R->getAs<FunctionProtoType>();
+
+  // Make sure we don't have any parameters.
+  if (Proto->getNumArgs() > 0) {
+    Diag(D.getIdentifierLoc(), diag::err_conv_function_with_params);
+
+    // Delete the parameters.
+    D.getFunctionTypeInfo().freeArgs();
+    D.setInvalidType();
+  } else if (Proto->isVariadic()) {
+    Diag(D.getIdentifierLoc(), diag::err_conv_function_variadic);
+    D.setInvalidType();
+  }
+
+  // Diagnose "&operator bool()" and other such nonsense.  This
+  // is actually a gcc extension which we don't support.
+  if (Proto->getResultType() != ConvType) {
+    Diag(D.getIdentifierLoc(), diag::err_conv_function_with_complex_decl)
+      << Proto->getResultType();
+    D.setInvalidType();
+    ConvType = Proto->getResultType();
+  }
+
+  // C++ [class.conv.fct]p4:
+  //   The conversion-type-id shall not represent a function type nor
+  //   an array type.
+  if (ConvType->isArrayType()) {
+    Diag(D.getIdentifierLoc(), diag::err_conv_function_to_array);
+    ConvType = Context.getPointerType(ConvType);
+    D.setInvalidType();
+  } else if (ConvType->isFunctionType()) {
+    Diag(D.getIdentifierLoc(), diag::err_conv_function_to_function);
+    ConvType = Context.getPointerType(ConvType);
+    D.setInvalidType();
+  }
+
+  // Rebuild the function type "R" without any parameters (in case any
+  // of the errors above fired) and with the conversion type as the
+  // return type.
+  if (D.isInvalidType())
+    R = Context.getFunctionType(ConvType, 0, 0, Proto->getExtProtoInfo());
+
+  // C++0x explicit conversion operators.
+  if (D.getDeclSpec().isExplicitSpecified())
+    Diag(D.getDeclSpec().getExplicitSpecLoc(),
+         getLangOpts().CPlusPlus0x ?
+           diag::warn_cxx98_compat_explicit_conversion_functions :
+           diag::ext_explicit_conversion_functions)
+      << SourceRange(D.getDeclSpec().getExplicitSpecLoc());
+}
+
+/// ActOnConversionDeclarator - Called by ActOnDeclarator to complete
+/// the declaration of the given C++ conversion function. This routine
+/// is responsible for recording the conversion function in the C++
+/// class, if possible.
+Decl *Sema::ActOnConversionDeclarator(CXXConversionDecl *Conversion) {
+  assert(Conversion && "Expected to receive a conversion function declaration");
+
+  CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(Conversion->getDeclContext());
+
+  // Make sure we aren't redeclaring the conversion function.
+  QualType ConvType = Context.getCanonicalType(Conversion->getConversionType());
+
+  // C++ [class.conv.fct]p1:
+  //   [...] A conversion function is never used to convert a
+  //   (possibly cv-qualified) object to the (possibly cv-qualified)
+  //   same object type (or a reference to it), to a (possibly
+  //   cv-qualified) base class of that type (or a reference to it),
+  //   or to (possibly cv-qualified) void.
+  // FIXME: Suppress this warning if the conversion function ends up being a
+  // virtual function that overrides a virtual function in a base class.
+  QualType ClassType
+    = Context.getCanonicalType(Context.getTypeDeclType(ClassDecl));
+  if (const ReferenceType *ConvTypeRef = ConvType->getAs<ReferenceType>())
+    ConvType = ConvTypeRef->getPointeeType();
+  if (Conversion->getTemplateSpecializationKind() != TSK_Undeclared &&
+      Conversion->getTemplateSpecializationKind() != TSK_ExplicitSpecialization)
+    /* Suppress diagnostics for instantiations. */;
+  else if (ConvType->isRecordType()) {
+    ConvType = Context.getCanonicalType(ConvType).getUnqualifiedType();
+    if (ConvType == ClassType)
+      Diag(Conversion->getLocation(), diag::warn_conv_to_self_not_used)
+        << ClassType;
+    else if (IsDerivedFrom(ClassType, ConvType))
+      Diag(Conversion->getLocation(), diag::warn_conv_to_base_not_used)
+        <<  ClassType << ConvType;
+  } else if (ConvType->isVoidType()) {
+    Diag(Conversion->getLocation(), diag::warn_conv_to_void_not_used)
+      << ClassType << ConvType;
+  }
+
+  if (FunctionTemplateDecl *ConversionTemplate
+                                = Conversion->getDescribedFunctionTemplate())
+    return ConversionTemplate;
+  
+  return Conversion;
+}
+
+//===----------------------------------------------------------------------===//
+// Namespace Handling
+//===----------------------------------------------------------------------===//
+
+
+
+/// ActOnStartNamespaceDef - This is called at the start of a namespace
+/// definition.
+Decl *Sema::ActOnStartNamespaceDef(Scope *NamespcScope,
+                                   SourceLocation InlineLoc,
+                                   SourceLocation NamespaceLoc,
+                                   SourceLocation IdentLoc,
+                                   IdentifierInfo *II,
+                                   SourceLocation LBrace,
+                                   AttributeList *AttrList) {
+  SourceLocation StartLoc = InlineLoc.isValid() ? InlineLoc : NamespaceLoc;
+  // For anonymous namespace, take the location of the left brace.
+  SourceLocation Loc = II ? IdentLoc : LBrace;
+  bool IsInline = InlineLoc.isValid();
+  bool IsInvalid = false;
+  bool IsStd = false;
+  bool AddToKnown = false;
+  Scope *DeclRegionScope = NamespcScope->getParent();
+
+  NamespaceDecl *PrevNS = 0;
+  if (II) {
+    // C++ [namespace.def]p2:
+    //   The identifier in an original-namespace-definition shall not
+    //   have been previously defined in the declarative region in
+    //   which the original-namespace-definition appears. The
+    //   identifier in an original-namespace-definition is the name of
+    //   the namespace. Subsequently in that declarative region, it is
+    //   treated as an original-namespace-name.
+    //
+    // Since namespace names are unique in their scope, and we don't
+    // look through using directives, just look for any ordinary names.
+    
+    const unsigned IDNS = Decl::IDNS_Ordinary | Decl::IDNS_Member | 
+    Decl::IDNS_Type | Decl::IDNS_Using | Decl::IDNS_Tag | 
+    Decl::IDNS_Namespace;
+    NamedDecl *PrevDecl = 0;
+    for (DeclContext::lookup_result R 
+         = CurContext->getRedeclContext()->lookup(II);
+         R.first != R.second; ++R.first) {
+      if ((*R.first)->getIdentifierNamespace() & IDNS) {
+        PrevDecl = *R.first;
+        break;
+      }
+    }
+    
+    PrevNS = dyn_cast_or_null<NamespaceDecl>(PrevDecl);
+    
+    if (PrevNS) {
+      // This is an extended namespace definition.
+      if (IsInline != PrevNS->isInline()) {
+        // inline-ness must match
+        if (PrevNS->isInline()) {
+          // The user probably just forgot the 'inline', so suggest that it
+          // be added back.
+          Diag(Loc, diag::warn_inline_namespace_reopened_noninline)
+            << FixItHint::CreateInsertion(NamespaceLoc, "inline ");
+        } else {
+          Diag(Loc, diag::err_inline_namespace_mismatch)
+            << IsInline;
+        }
+        Diag(PrevNS->getLocation(), diag::note_previous_definition);
+        
+        IsInline = PrevNS->isInline();
+      }      
+    } else if (PrevDecl) {
+      // This is an invalid name redefinition.
+      Diag(Loc, diag::err_redefinition_different_kind)
+        << II;
+      Diag(PrevDecl->getLocation(), diag::note_previous_definition);
+      IsInvalid = true;
+      // Continue on to push Namespc as current DeclContext and return it.
+    } else if (II->isStr("std") &&
+               CurContext->getRedeclContext()->isTranslationUnit()) {
+      // This is the first "real" definition of the namespace "std", so update
+      // our cache of the "std" namespace to point at this definition.
+      PrevNS = getStdNamespace();
+      IsStd = true;
+      AddToKnown = !IsInline;
+    } else {
+      // We've seen this namespace for the first time.
+      AddToKnown = !IsInline;
+    }
+  } else {
+    // Anonymous namespaces.
+    
+    // Determine whether the parent already has an anonymous namespace.
+    DeclContext *Parent = CurContext->getRedeclContext();
+    if (TranslationUnitDecl *TU = dyn_cast<TranslationUnitDecl>(Parent)) {
+      PrevNS = TU->getAnonymousNamespace();
+    } else {
+      NamespaceDecl *ND = cast<NamespaceDecl>(Parent);
+      PrevNS = ND->getAnonymousNamespace();
+    }
+
+    if (PrevNS && IsInline != PrevNS->isInline()) {
+      // inline-ness must match
+      Diag(Loc, diag::err_inline_namespace_mismatch)
+        << IsInline;
+      Diag(PrevNS->getLocation(), diag::note_previous_definition);
+      
+      // Recover by ignoring the new namespace's inline status.
+      IsInline = PrevNS->isInline();
+    }
+  }
+  
+  NamespaceDecl *Namespc = NamespaceDecl::Create(Context, CurContext, IsInline,
+                                                 StartLoc, Loc, II, PrevNS);
+  if (IsInvalid)
+    Namespc->setInvalidDecl();
+  
+  ProcessDeclAttributeList(DeclRegionScope, Namespc, AttrList);
+
+  // FIXME: Should we be merging attributes?
+  if (const VisibilityAttr *Attr = Namespc->getAttr<VisibilityAttr>())
+    PushNamespaceVisibilityAttr(Attr, Loc);
+
+  if (IsStd)
+    StdNamespace = Namespc;
+  if (AddToKnown)
+    KnownNamespaces[Namespc] = false;
+  
+  if (II) {
+    PushOnScopeChains(Namespc, DeclRegionScope);
+  } else {
+    // Link the anonymous namespace into its parent.
+    DeclContext *Parent = CurContext->getRedeclContext();
+    if (TranslationUnitDecl *TU = dyn_cast<TranslationUnitDecl>(Parent)) {
+      TU->setAnonymousNamespace(Namespc);
+    } else {
+      cast<NamespaceDecl>(Parent)->setAnonymousNamespace(Namespc);
+    }
+
+    CurContext->addDecl(Namespc);
+
+    // C++ [namespace.unnamed]p1.  An unnamed-namespace-definition
+    //   behaves as if it were replaced by
+    //     namespace unique { /* empty body */ }
+    //     using namespace unique;
+    //     namespace unique { namespace-body }
+    //   where all occurrences of 'unique' in a translation unit are
+    //   replaced by the same identifier and this identifier differs
+    //   from all other identifiers in the entire program.
+
+    // We just create the namespace with an empty name and then add an
+    // implicit using declaration, just like the standard suggests.
+    //
+    // CodeGen enforces the "universally unique" aspect by giving all
+    // declarations semantically contained within an anonymous
+    // namespace internal linkage.
+
+    if (!PrevNS) {
+      UsingDirectiveDecl* UD
+        = UsingDirectiveDecl::Create(Context, CurContext,
+                                     /* 'using' */ LBrace,
+                                     /* 'namespace' */ SourceLocation(),
+                                     /* qualifier */ NestedNameSpecifierLoc(),
+                                     /* identifier */ SourceLocation(),
+                                     Namespc,
+                                     /* Ancestor */ CurContext);
+      UD->setImplicit();
+      CurContext->addDecl(UD);
+    }
+  }
+
+  // Although we could have an invalid decl (i.e. the namespace name is a
+  // redefinition), push it as current DeclContext and try to continue parsing.
+  // FIXME: We should be able to push Namespc here, so that the each DeclContext
+  // for the namespace has the declarations that showed up in that particular
+  // namespace definition.
+  PushDeclContext(NamespcScope, Namespc);
+  return Namespc;
+}
+
+/// getNamespaceDecl - Returns the namespace a decl represents. If the decl
+/// is a namespace alias, returns the namespace it points to.
+static inline NamespaceDecl *getNamespaceDecl(NamedDecl *D) {
+  if (NamespaceAliasDecl *AD = dyn_cast_or_null<NamespaceAliasDecl>(D))
+    return AD->getNamespace();
+  return dyn_cast_or_null<NamespaceDecl>(D);
+}
+
+/// ActOnFinishNamespaceDef - This callback is called after a namespace is
+/// exited. Decl is the DeclTy returned by ActOnStartNamespaceDef.
+void Sema::ActOnFinishNamespaceDef(Decl *Dcl, SourceLocation RBrace) {
+  NamespaceDecl *Namespc = dyn_cast_or_null<NamespaceDecl>(Dcl);
+  assert(Namespc && "Invalid parameter, expected NamespaceDecl");
+  Namespc->setRBraceLoc(RBrace);
+  PopDeclContext();
+  if (Namespc->hasAttr<VisibilityAttr>())
+    PopPragmaVisibility(true, RBrace);
+}
+
+CXXRecordDecl *Sema::getStdBadAlloc() const {
+  return cast_or_null<CXXRecordDecl>(
+                                  StdBadAlloc.get(Context.getExternalSource()));
+}
+
+NamespaceDecl *Sema::getStdNamespace() const {
+  return cast_or_null<NamespaceDecl>(
+                                 StdNamespace.get(Context.getExternalSource()));
+}
+
+/// \brief Retrieve the special "std" namespace, which may require us to 
+/// implicitly define the namespace.
+NamespaceDecl *Sema::getOrCreateStdNamespace() {
+  if (!StdNamespace) {
+    // The "std" namespace has not yet been defined, so build one implicitly.
+    StdNamespace = NamespaceDecl::Create(Context, 
+                                         Context.getTranslationUnitDecl(),
+                                         /*Inline=*/false,
+                                         SourceLocation(), SourceLocation(),
+                                         &PP.getIdentifierTable().get("std"),
+                                         /*PrevDecl=*/0);
+    getStdNamespace()->setImplicit(true);
+  }
+  
+  return getStdNamespace();
+}
+
+bool Sema::isStdInitializerList(QualType Ty, QualType *Element) {
+  assert(getLangOpts().CPlusPlus &&
+         "Looking for std::initializer_list outside of C++.");
+
+  // We're looking for implicit instantiations of
+  // template <typename E> class std::initializer_list.
+
+  if (!StdNamespace) // If we haven't seen namespace std yet, this can't be it.
+    return false;
+
+  ClassTemplateDecl *Template = 0;
+  const TemplateArgument *Arguments = 0;
+
+  if (const RecordType *RT = Ty->getAs<RecordType>()) {
+
+    ClassTemplateSpecializationDecl *Specialization =
+        dyn_cast<ClassTemplateSpecializationDecl>(RT->getDecl());
+    if (!Specialization)
+      return false;
+
+    Template = Specialization->getSpecializedTemplate();
+    Arguments = Specialization->getTemplateArgs().data();
+  } else if (const TemplateSpecializationType *TST =
+                 Ty->getAs<TemplateSpecializationType>()) {
+    Template = dyn_cast_or_null<ClassTemplateDecl>(
+        TST->getTemplateName().getAsTemplateDecl());
+    Arguments = TST->getArgs();
+  }
+  if (!Template)
+    return false;
+
+  if (!StdInitializerList) {
+    // Haven't recognized std::initializer_list yet, maybe this is it.
+    CXXRecordDecl *TemplateClass = Template->getTemplatedDecl();
+    if (TemplateClass->getIdentifier() !=
+            &PP.getIdentifierTable().get("initializer_list") ||
+        !getStdNamespace()->InEnclosingNamespaceSetOf(
+            TemplateClass->getDeclContext()))
+      return false;
+    // This is a template called std::initializer_list, but is it the right
+    // template?
+    TemplateParameterList *Params = Template->getTemplateParameters();
+    if (Params->getMinRequiredArguments() != 1)
+      return false;
+    if (!isa<TemplateTypeParmDecl>(Params->getParam(0)))
+      return false;
+
+    // It's the right template.
+    StdInitializerList = Template;
+  }
+
+  if (Template != StdInitializerList)
+    return false;
+
+  // This is an instance of std::initializer_list. Find the argument type.
+  if (Element)
+    *Element = Arguments[0].getAsType();
+  return true;
+}
+
+static ClassTemplateDecl *LookupStdInitializerList(Sema &S, SourceLocation Loc){
+  NamespaceDecl *Std = S.getStdNamespace();
+  if (!Std) {
+    S.Diag(Loc, diag::err_implied_std_initializer_list_not_found);
+    return 0;
+  }
+
+  LookupResult Result(S, &S.PP.getIdentifierTable().get("initializer_list"),
+                      Loc, Sema::LookupOrdinaryName);
+  if (!S.LookupQualifiedName(Result, Std)) {
+    S.Diag(Loc, diag::err_implied_std_initializer_list_not_found);
+    return 0;
+  }
+  ClassTemplateDecl *Template = Result.getAsSingle<ClassTemplateDecl>();
+  if (!Template) {
+    Result.suppressDiagnostics();
+    // We found something weird. Complain about the first thing we found.
+    NamedDecl *Found = *Result.begin();
+    S.Diag(Found->getLocation(), diag::err_malformed_std_initializer_list);
+    return 0;
+  }
+
+  // We found some template called std::initializer_list. Now verify that it's
+  // correct.
+  TemplateParameterList *Params = Template->getTemplateParameters();
+  if (Params->getMinRequiredArguments() != 1 ||
+      !isa<TemplateTypeParmDecl>(Params->getParam(0))) {
+    S.Diag(Template->getLocation(), diag::err_malformed_std_initializer_list);
+    return 0;
+  }
+
+  return Template;
+}
+
+QualType Sema::BuildStdInitializerList(QualType Element, SourceLocation Loc) {
+  if (!StdInitializerList) {
+    StdInitializerList = LookupStdInitializerList(*this, Loc);
+    if (!StdInitializerList)
+      return QualType();
+  }
+
+  TemplateArgumentListInfo Args(Loc, Loc);
+  Args.addArgument(TemplateArgumentLoc(TemplateArgument(Element),
+                                       Context.getTrivialTypeSourceInfo(Element,
+                                                                        Loc)));
+  return Context.getCanonicalType(
+      CheckTemplateIdType(TemplateName(StdInitializerList), Loc, Args));
+}
+
+bool Sema::isInitListConstructor(const CXXConstructorDecl* Ctor) {
+  // C++ [dcl.init.list]p2:
+  //   A constructor is an initializer-list constructor if its first parameter
+  //   is of type std::initializer_list<E> or reference to possibly cv-qualified
+  //   std::initializer_list<E> for some type E, and either there are no other
+  //   parameters or else all other parameters have default arguments.
+  if (Ctor->getNumParams() < 1 ||
+      (Ctor->getNumParams() > 1 && !Ctor->getParamDecl(1)->hasDefaultArg()))
+    return false;
+
+  QualType ArgType = Ctor->getParamDecl(0)->getType();
+  if (const ReferenceType *RT = ArgType->getAs<ReferenceType>())
+    ArgType = RT->getPointeeType().getUnqualifiedType();
+
+  return isStdInitializerList(ArgType, 0);
+}
+
+/// \brief Determine whether a using statement is in a context where it will be
+/// apply in all contexts.
+static bool IsUsingDirectiveInToplevelContext(DeclContext *CurContext) {
+  switch (CurContext->getDeclKind()) {
+    case Decl::TranslationUnit:
+      return true;
+    case Decl::LinkageSpec:
+      return IsUsingDirectiveInToplevelContext(CurContext->getParent());
+    default:
+      return false;
+  }
+}
+
+namespace {
+
+// Callback to only accept typo corrections that are namespaces.
+class NamespaceValidatorCCC : public CorrectionCandidateCallback {
+ public:
+  virtual bool ValidateCandidate(const TypoCorrection &candidate) {
+    if (NamedDecl *ND = candidate.getCorrectionDecl()) {
+      return isa<NamespaceDecl>(ND) || isa<NamespaceAliasDecl>(ND);
+    }
+    return false;
+  }
+};
+
+}
+
+static bool TryNamespaceTypoCorrection(Sema &S, LookupResult &R, Scope *Sc,
+                                       CXXScopeSpec &SS,
+                                       SourceLocation IdentLoc,
+                                       IdentifierInfo *Ident) {
+  NamespaceValidatorCCC Validator;
+  R.clear();
+  if (TypoCorrection Corrected = S.CorrectTypo(R.getLookupNameInfo(),
+                                               R.getLookupKind(), Sc, &SS,
+                                               Validator)) {
+    std::string CorrectedStr(Corrected.getAsString(S.getLangOpts()));
+    std::string CorrectedQuotedStr(Corrected.getQuoted(S.getLangOpts()));
+    if (DeclContext *DC = S.computeDeclContext(SS, false))
+      S.Diag(IdentLoc, diag::err_using_directive_member_suggest)
+        << Ident << DC << CorrectedQuotedStr << SS.getRange()
+        << FixItHint::CreateReplacement(IdentLoc, CorrectedStr);
+    else
+      S.Diag(IdentLoc, diag::err_using_directive_suggest)
+        << Ident << CorrectedQuotedStr
+        << FixItHint::CreateReplacement(IdentLoc, CorrectedStr);
+
+    S.Diag(Corrected.getCorrectionDecl()->getLocation(),
+         diag::note_namespace_defined_here) << CorrectedQuotedStr;
+
+    R.addDecl(Corrected.getCorrectionDecl());
+    return true;
+  }
+  return false;
+}
+
+Decl *Sema::ActOnUsingDirective(Scope *S,
+                                          SourceLocation UsingLoc,
+                                          SourceLocation NamespcLoc,
+                                          CXXScopeSpec &SS,
+                                          SourceLocation IdentLoc,
+                                          IdentifierInfo *NamespcName,
+                                          AttributeList *AttrList) {
+  assert(!SS.isInvalid() && "Invalid CXXScopeSpec.");
+  assert(NamespcName && "Invalid NamespcName.");
+  assert(IdentLoc.isValid() && "Invalid NamespceName location.");
+
+  // This can only happen along a recovery path.
+  while (S->getFlags() & Scope::TemplateParamScope)
+    S = S->getParent();
+  assert(S->getFlags() & Scope::DeclScope && "Invalid Scope.");
+
+  UsingDirectiveDecl *UDir = 0;
+  NestedNameSpecifier *Qualifier = 0;
+  if (SS.isSet())
+    Qualifier = static_cast<NestedNameSpecifier *>(SS.getScopeRep());
+  
+  // Lookup namespace name.
+  LookupResult R(*this, NamespcName, IdentLoc, LookupNamespaceName);
+  LookupParsedName(R, S, &SS);
+  if (R.isAmbiguous())
+    return 0;
+
+  if (R.empty()) {
+    R.clear();
+    // Allow "using namespace std;" or "using namespace ::std;" even if 
+    // "std" hasn't been defined yet, for GCC compatibility.
+    if ((!Qualifier || Qualifier->getKind() == NestedNameSpecifier::Global) &&
+        NamespcName->isStr("std")) {
+      Diag(IdentLoc, diag::ext_using_undefined_std);
+      R.addDecl(getOrCreateStdNamespace());
+      R.resolveKind();
+    } 
+    // Otherwise, attempt typo correction.
+    else TryNamespaceTypoCorrection(*this, R, S, SS, IdentLoc, NamespcName);
+  }
+  
+  if (!R.empty()) {
+    NamedDecl *Named = R.getFoundDecl();
+    assert((isa<NamespaceDecl>(Named) || isa<NamespaceAliasDecl>(Named))
+        && "expected namespace decl");
+    // C++ [namespace.udir]p1:
+    //   A using-directive specifies that the names in the nominated
+    //   namespace can be used in the scope in which the
+    //   using-directive appears after the using-directive. During
+    //   unqualified name lookup (3.4.1), the names appear as if they
+    //   were declared in the nearest enclosing namespace which
+    //   contains both the using-directive and the nominated
+    //   namespace. [Note: in this context, "contains" means "contains
+    //   directly or indirectly". ]
+
+    // Find enclosing context containing both using-directive and
+    // nominated namespace.
+    NamespaceDecl *NS = getNamespaceDecl(Named);
+    DeclContext *CommonAncestor = cast<DeclContext>(NS);
+    while (CommonAncestor && !CommonAncestor->Encloses(CurContext))
+      CommonAncestor = CommonAncestor->getParent();
+
+    UDir = UsingDirectiveDecl::Create(Context, CurContext, UsingLoc, NamespcLoc,
+                                      SS.getWithLocInContext(Context),
+                                      IdentLoc, Named, CommonAncestor);
+
+    if (IsUsingDirectiveInToplevelContext(CurContext) &&
+        !SourceMgr.isFromMainFile(SourceMgr.getExpansionLoc(IdentLoc))) {
+      Diag(IdentLoc, diag::warn_using_directive_in_header);
+    }
+
+    PushUsingDirective(S, UDir);
+  } else {
+    Diag(IdentLoc, diag::err_expected_namespace_name) << SS.getRange();
+  }
+
+  // FIXME: We ignore attributes for now.
+  return UDir;
+}
+
+void Sema::PushUsingDirective(Scope *S, UsingDirectiveDecl *UDir) {
+  // If the scope has an associated entity and the using directive is at
+  // namespace or translation unit scope, add the UsingDirectiveDecl into
+  // its lookup structure so qualified name lookup can find it.
+  DeclContext *Ctx = static_cast<DeclContext*>(S->getEntity());
+  if (Ctx && !Ctx->isFunctionOrMethod())
+    Ctx->addDecl(UDir);
+  else
+    // Otherwise, it is at block sope. The using-directives will affect lookup
+    // only to the end of the scope.
+    S->PushUsingDirective(UDir);
+}
+
+
+Decl *Sema::ActOnUsingDeclaration(Scope *S,
+                                  AccessSpecifier AS,
+                                  bool HasUsingKeyword,
+                                  SourceLocation UsingLoc,
+                                  CXXScopeSpec &SS,
+                                  UnqualifiedId &Name,
+                                  AttributeList *AttrList,
+                                  bool IsTypeName,
+                                  SourceLocation TypenameLoc) {
+  assert(S->getFlags() & Scope::DeclScope && "Invalid Scope.");
+
+  switch (Name.getKind()) {
+  case UnqualifiedId::IK_ImplicitSelfParam:
+  case UnqualifiedId::IK_Identifier:
+  case UnqualifiedId::IK_OperatorFunctionId:
+  case UnqualifiedId::IK_LiteralOperatorId:
+  case UnqualifiedId::IK_ConversionFunctionId:
+    break;
+      
+  case UnqualifiedId::IK_ConstructorName:
+  case UnqualifiedId::IK_ConstructorTemplateId:
+    // C++11 inheriting constructors.
+    Diag(Name.getLocStart(),
+         getLangOpts().CPlusPlus0x ?
+           // FIXME: Produce warn_cxx98_compat_using_decl_constructor
+           //        instead once inheriting constructors work.
+           diag::err_using_decl_constructor_unsupported :
+           diag::err_using_decl_constructor)
+      << SS.getRange();
+
+    if (getLangOpts().CPlusPlus0x) break;
+
+    return 0;
+      
+  case UnqualifiedId::IK_DestructorName:
+    Diag(Name.getLocStart(), diag::err_using_decl_destructor)
+      << SS.getRange();
+    return 0;
+      
+  case UnqualifiedId::IK_TemplateId:
+    Diag(Name.getLocStart(), diag::err_using_decl_template_id)
+      << SourceRange(Name.TemplateId->LAngleLoc, Name.TemplateId->RAngleLoc);
+    return 0;
+  }
+
+  DeclarationNameInfo TargetNameInfo = GetNameFromUnqualifiedId(Name);
+  DeclarationName TargetName = TargetNameInfo.getName();
+  if (!TargetName)
+    return 0;
+
+  // Warn about using declarations.
+  // TODO: store that the declaration was written without 'using' and
+  // talk about access decls instead of using decls in the
+  // diagnostics.
+  if (!HasUsingKeyword) {
+    UsingLoc = Name.getLocStart();
+    
+    Diag(UsingLoc, diag::warn_access_decl_deprecated)
+      << FixItHint::CreateInsertion(SS.getRange().getBegin(), "using ");
+  }
+
+  if (DiagnoseUnexpandedParameterPack(SS, UPPC_UsingDeclaration) ||
+      DiagnoseUnexpandedParameterPack(TargetNameInfo, UPPC_UsingDeclaration))
+    return 0;
+
+  NamedDecl *UD = BuildUsingDeclaration(S, AS, UsingLoc, SS,
+                                        TargetNameInfo, AttrList,
+                                        /* IsInstantiation */ false,
+                                        IsTypeName, TypenameLoc);
+  if (UD)
+    PushOnScopeChains(UD, S, /*AddToContext*/ false);
+
+  return UD;
+}
+
+/// \brief Determine whether a using declaration considers the given
+/// declarations as "equivalent", e.g., if they are redeclarations of
+/// the same entity or are both typedefs of the same type.
+static bool 
+IsEquivalentForUsingDecl(ASTContext &Context, NamedDecl *D1, NamedDecl *D2,
+                         bool &SuppressRedeclaration) {
+  if (D1->getCanonicalDecl() == D2->getCanonicalDecl()) {
+    SuppressRedeclaration = false;
+    return true;
+  }
+
+  if (TypedefNameDecl *TD1 = dyn_cast<TypedefNameDecl>(D1))
+    if (TypedefNameDecl *TD2 = dyn_cast<TypedefNameDecl>(D2)) {
+      SuppressRedeclaration = true;
+      return Context.hasSameType(TD1->getUnderlyingType(),
+                                 TD2->getUnderlyingType());
+    }
+
+  return false;
+}
+
+
+/// Determines whether to create a using shadow decl for a particular
+/// decl, given the set of decls existing prior to this using lookup.
+bool Sema::CheckUsingShadowDecl(UsingDecl *Using, NamedDecl *Orig,
+                                const LookupResult &Previous) {
+  // Diagnose finding a decl which is not from a base class of the
+  // current class.  We do this now because there are cases where this
+  // function will silently decide not to build a shadow decl, which
+  // will pre-empt further diagnostics.
+  //
+  // We don't need to do this in C++0x because we do the check once on
+  // the qualifier.
+  //
+  // FIXME: diagnose the following if we care enough:
+  //   struct A { int foo; };
+  //   struct B : A { using A::foo; };
+  //   template <class T> struct C : A {};
+  //   template <class T> struct D : C<T> { using B::foo; } // <---
+  // This is invalid (during instantiation) in C++03 because B::foo
+  // resolves to the using decl in B, which is not a base class of D<T>.
+  // We can't diagnose it immediately because C<T> is an unknown
+  // specialization.  The UsingShadowDecl in D<T> then points directly
+  // to A::foo, which will look well-formed when we instantiate.
+  // The right solution is to not collapse the shadow-decl chain.
+  if (!getLangOpts().CPlusPlus0x && CurContext->isRecord()) {
+    DeclContext *OrigDC = Orig->getDeclContext();
+
+    // Handle enums and anonymous structs.
+    if (isa<EnumDecl>(OrigDC)) OrigDC = OrigDC->getParent();
+    CXXRecordDecl *OrigRec = cast<CXXRecordDecl>(OrigDC);
+    while (OrigRec->isAnonymousStructOrUnion())
+      OrigRec = cast<CXXRecordDecl>(OrigRec->getDeclContext());
+
+    if (cast<CXXRecordDecl>(CurContext)->isProvablyNotDerivedFrom(OrigRec)) {
+      if (OrigDC == CurContext) {
+        Diag(Using->getLocation(),
+             diag::err_using_decl_nested_name_specifier_is_current_class)
+          << Using->getQualifierLoc().getSourceRange();
+        Diag(Orig->getLocation(), diag::note_using_decl_target);
+        return true;
+      }
+
+      Diag(Using->getQualifierLoc().getBeginLoc(),
+           diag::err_using_decl_nested_name_specifier_is_not_base_class)
+        << Using->getQualifier()
+        << cast<CXXRecordDecl>(CurContext)
+        << Using->getQualifierLoc().getSourceRange();
+      Diag(Orig->getLocation(), diag::note_using_decl_target);
+      return true;
+    }
+  }
+
+  if (Previous.empty()) return false;
+
+  NamedDecl *Target = Orig;
+  if (isa<UsingShadowDecl>(Target))
+    Target = cast<UsingShadowDecl>(Target)->getTargetDecl();
+
+  // If the target happens to be one of the previous declarations, we
+  // don't have a conflict.
+  // 
+  // FIXME: but we might be increasing its access, in which case we
+  // should redeclare it.
+  NamedDecl *NonTag = 0, *Tag = 0;
+  for (LookupResult::iterator I = Previous.begin(), E = Previous.end();
+         I != E; ++I) {
+    NamedDecl *D = (*I)->getUnderlyingDecl();
+    bool Result;
+    if (IsEquivalentForUsingDecl(Context, D, Target, Result))
+      return Result;
+
+    (isa<TagDecl>(D) ? Tag : NonTag) = D;
+  }
+
+  if (Target->isFunctionOrFunctionTemplate()) {
+    FunctionDecl *FD;
+    if (isa<FunctionTemplateDecl>(Target))
+      FD = cast<FunctionTemplateDecl>(Target)->getTemplatedDecl();
+    else
+      FD = cast<FunctionDecl>(Target);
+
+    NamedDecl *OldDecl = 0;
+    switch (CheckOverload(0, FD, Previous, OldDecl, /*IsForUsingDecl*/ true)) {
+    case Ovl_Overload:
+      return false;
+
+    case Ovl_NonFunction:
+      Diag(Using->getLocation(), diag::err_using_decl_conflict);
+      break;
+      
+    // We found a decl with the exact signature.
+    case Ovl_Match:
+      // If we're in a record, we want to hide the target, so we
+      // return true (without a diagnostic) to tell the caller not to
+      // build a shadow decl.
+      if (CurContext->isRecord())
+        return true;
+
+      // If we're not in a record, this is an error.
+      Diag(Using->getLocation(), diag::err_using_decl_conflict);
+      break;
+    }
+
+    Diag(Target->getLocation(), diag::note_using_decl_target);
+    Diag(OldDecl->getLocation(), diag::note_using_decl_conflict);
+    return true;
+  }
+
+  // Target is not a function.
+
+  if (isa<TagDecl>(Target)) {
+    // No conflict between a tag and a non-tag.
+    if (!Tag) return false;
+
+    Diag(Using->getLocation(), diag::err_using_decl_conflict);
+    Diag(Target->getLocation(), diag::note_using_decl_target);
+    Diag(Tag->getLocation(), diag::note_using_decl_conflict);
+    return true;
+  }
+
+  // No conflict between a tag and a non-tag.
+  if (!NonTag) return false;
+
+  Diag(Using->getLocation(), diag::err_using_decl_conflict);
+  Diag(Target->getLocation(), diag::note_using_decl_target);
+  Diag(NonTag->getLocation(), diag::note_using_decl_conflict);
+  return true;
+}
+
+/// Builds a shadow declaration corresponding to a 'using' declaration.
+UsingShadowDecl *Sema::BuildUsingShadowDecl(Scope *S,
+                                            UsingDecl *UD,
+                                            NamedDecl *Orig) {
+
+  // If we resolved to another shadow declaration, just coalesce them.
+  NamedDecl *Target = Orig;
+  if (isa<UsingShadowDecl>(Target)) {
+    Target = cast<UsingShadowDecl>(Target)->getTargetDecl();
+    assert(!isa<UsingShadowDecl>(Target) && "nested shadow declaration");
+  }
+  
+  UsingShadowDecl *Shadow
+    = UsingShadowDecl::Create(Context, CurContext,
+                              UD->getLocation(), UD, Target);
+  UD->addShadowDecl(Shadow);
+  
+  Shadow->setAccess(UD->getAccess());
+  if (Orig->isInvalidDecl() || UD->isInvalidDecl())
+    Shadow->setInvalidDecl();
+  
+  if (S)
+    PushOnScopeChains(Shadow, S);
+  else
+    CurContext->addDecl(Shadow);
+
+
+  return Shadow;
+}
+
+/// Hides a using shadow declaration.  This is required by the current
+/// using-decl implementation when a resolvable using declaration in a
+/// class is followed by a declaration which would hide or override
+/// one or more of the using decl's targets; for example:
+///
+///   struct Base { void foo(int); };
+///   struct Derived : Base {
+///     using Base::foo;
+///     void foo(int);
+///   };
+///
+/// The governing language is C++03 [namespace.udecl]p12:
+///
+///   When a using-declaration brings names from a base class into a
+///   derived class scope, member functions in the derived class
+///   override and/or hide member functions with the same name and
+///   parameter types in a base class (rather than conflicting).
+///
+/// There are two ways to implement this:
+///   (1) optimistically create shadow decls when they're not hidden
+///       by existing declarations, or
+///   (2) don't create any shadow decls (or at least don't make them
+///       visible) until we've fully parsed/instantiated the class.
+/// The problem with (1) is that we might have to retroactively remove
+/// a shadow decl, which requires several O(n) operations because the
+/// decl structures are (very reasonably) not designed for removal.
+/// (2) avoids this but is very fiddly and phase-dependent.
+void Sema::HideUsingShadowDecl(Scope *S, UsingShadowDecl *Shadow) {
+  if (Shadow->getDeclName().getNameKind() ==
+        DeclarationName::CXXConversionFunctionName)
+    cast<CXXRecordDecl>(Shadow->getDeclContext())->removeConversion(Shadow);
+
+  // Remove it from the DeclContext...
+  Shadow->getDeclContext()->removeDecl(Shadow);
+
+  // ...and the scope, if applicable...
+  if (S) {
+    S->RemoveDecl(Shadow);
+    IdResolver.RemoveDecl(Shadow);
+  }
+
+  // ...and the using decl.
+  Shadow->getUsingDecl()->removeShadowDecl(Shadow);
+
+  // TODO: complain somehow if Shadow was used.  It shouldn't
+  // be possible for this to happen, because...?
+}
+
+/// Builds a using declaration.
+///
+/// \param IsInstantiation - Whether this call arises from an
+///   instantiation of an unresolved using declaration.  We treat
+///   the lookup differently for these declarations.
+NamedDecl *Sema::BuildUsingDeclaration(Scope *S, AccessSpecifier AS,
+                                       SourceLocation UsingLoc,
+                                       CXXScopeSpec &SS,
+                                       const DeclarationNameInfo &NameInfo,
+                                       AttributeList *AttrList,
+                                       bool IsInstantiation,
+                                       bool IsTypeName,
+                                       SourceLocation TypenameLoc) {
+  assert(!SS.isInvalid() && "Invalid CXXScopeSpec.");
+  SourceLocation IdentLoc = NameInfo.getLoc();
+  assert(IdentLoc.isValid() && "Invalid TargetName location.");
+
+  // FIXME: We ignore attributes for now.
+
+  if (SS.isEmpty()) {
+    Diag(IdentLoc, diag::err_using_requires_qualname);
+    return 0;
+  }
+
+  // Do the redeclaration lookup in the current scope.
+  LookupResult Previous(*this, NameInfo, LookupUsingDeclName,
+                        ForRedeclaration);
+  Previous.setHideTags(false);
+  if (S) {
+    LookupName(Previous, S);
+
+    // It is really dumb that we have to do this.
+    LookupResult::Filter F = Previous.makeFilter();
+    while (F.hasNext()) {
+      NamedDecl *D = F.next();
+      if (!isDeclInScope(D, CurContext, S))
+        F.erase();
+    }
+    F.done();
+  } else {
+    assert(IsInstantiation && "no scope in non-instantiation");
+    assert(CurContext->isRecord() && "scope not record in instantiation");
+    LookupQualifiedName(Previous, CurContext);
+  }
+
+  // Check for invalid redeclarations.
+  if (CheckUsingDeclRedeclaration(UsingLoc, IsTypeName, SS, IdentLoc, Previous))
+    return 0;
+
+  // Check for bad qualifiers.
+  if (CheckUsingDeclQualifier(UsingLoc, SS, IdentLoc))
+    return 0;
+
+  DeclContext *LookupContext = computeDeclContext(SS);
+  NamedDecl *D;
+  NestedNameSpecifierLoc QualifierLoc = SS.getWithLocInContext(Context);
+  if (!LookupContext) {
+    if (IsTypeName) {
+      // FIXME: not all declaration name kinds are legal here
+      D = UnresolvedUsingTypenameDecl::Create(Context, CurContext,
+                                              UsingLoc, TypenameLoc,
+                                              QualifierLoc,
+                                              IdentLoc, NameInfo.getName());
+    } else {
+      D = UnresolvedUsingValueDecl::Create(Context, CurContext, UsingLoc, 
+                                           QualifierLoc, NameInfo);
+    }
+  } else {
+    D = UsingDecl::Create(Context, CurContext, UsingLoc, QualifierLoc,
+                          NameInfo, IsTypeName);
+  }
+  D->setAccess(AS);
+  CurContext->addDecl(D);
+
+  if (!LookupContext) return D;
+  UsingDecl *UD = cast<UsingDecl>(D);
+
+  if (RequireCompleteDeclContext(SS, LookupContext)) {
+    UD->setInvalidDecl();
+    return UD;
+  }
+
+  // The normal rules do not apply to inheriting constructor declarations.
+  if (NameInfo.getName().getNameKind() == DeclarationName::CXXConstructorName) {
+    if (CheckInheritingConstructorUsingDecl(UD))
+      UD->setInvalidDecl();
+    return UD;
+  }
+
+  // Otherwise, look up the target name.
+
+  LookupResult R(*this, NameInfo, LookupOrdinaryName);
+
+  // Unlike most lookups, we don't always want to hide tag
+  // declarations: tag names are visible through the using declaration
+  // even if hidden by ordinary names, *except* in a dependent context
+  // where it's important for the sanity of two-phase lookup.
+  if (!IsInstantiation)
+    R.setHideTags(false);
+
+  // For the purposes of this lookup, we have a base object type
+  // equal to that of the current context.
+  if (CurContext->isRecord()) {
+    R.setBaseObjectType(
+                   Context.getTypeDeclType(cast<CXXRecordDecl>(CurContext)));
+  }
+
+  LookupQualifiedName(R, LookupContext);
+
+  if (R.empty()) {
+    Diag(IdentLoc, diag::err_no_member) 
+      << NameInfo.getName() << LookupContext << SS.getRange();
+    UD->setInvalidDecl();
+    return UD;
+  }
+
+  if (R.isAmbiguous()) {
+    UD->setInvalidDecl();
+    return UD;
+  }
+
+  if (IsTypeName) {
+    // If we asked for a typename and got a non-type decl, error out.
+    if (!R.getAsSingle<TypeDecl>()) {
+      Diag(IdentLoc, diag::err_using_typename_non_type);
+      for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I)
+        Diag((*I)->getUnderlyingDecl()->getLocation(),
+             diag::note_using_decl_target);
+      UD->setInvalidDecl();
+      return UD;
+    }
+  } else {
+    // If we asked for a non-typename and we got a type, error out,
+    // but only if this is an instantiation of an unresolved using
+    // decl.  Otherwise just silently find the type name.
+    if (IsInstantiation && R.getAsSingle<TypeDecl>()) {
+      Diag(IdentLoc, diag::err_using_dependent_value_is_type);
+      Diag(R.getFoundDecl()->getLocation(), diag::note_using_decl_target);
+      UD->setInvalidDecl();
+      return UD;
+    }
+  }
+
+  // C++0x N2914 [namespace.udecl]p6:
+  // A using-declaration shall not name a namespace.
+  if (R.getAsSingle<NamespaceDecl>()) {
+    Diag(IdentLoc, diag::err_using_decl_can_not_refer_to_namespace)
+      << SS.getRange();
+    UD->setInvalidDecl();
+    return UD;
+  }
+
+  for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I) {
+    if (!CheckUsingShadowDecl(UD, *I, Previous))
+      BuildUsingShadowDecl(S, UD, *I);
+  }
+
+  return UD;
+}
+
+/// Additional checks for a using declaration referring to a constructor name.
+bool Sema::CheckInheritingConstructorUsingDecl(UsingDecl *UD) {
+  assert(!UD->isTypeName() && "expecting a constructor name");
+
+  const Type *SourceType = UD->getQualifier()->getAsType();
+  assert(SourceType &&
+         "Using decl naming constructor doesn't have type in scope spec.");
+  CXXRecordDecl *TargetClass = cast<CXXRecordDecl>(CurContext);
+
+  // Check whether the named type is a direct base class.
+  CanQualType CanonicalSourceType = SourceType->getCanonicalTypeUnqualified();
+  CXXRecordDecl::base_class_iterator BaseIt, BaseE;
+  for (BaseIt = TargetClass->bases_begin(), BaseE = TargetClass->bases_end();
+       BaseIt != BaseE; ++BaseIt) {
+    CanQualType BaseType = BaseIt->getType()->getCanonicalTypeUnqualified();
+    if (CanonicalSourceType == BaseType)
+      break;
+    if (BaseIt->getType()->isDependentType())
+      break;
+  }
+
+  if (BaseIt == BaseE) {
+    // Did not find SourceType in the bases.
+    Diag(UD->getUsingLocation(),
+         diag::err_using_decl_constructor_not_in_direct_base)
+      << UD->getNameInfo().getSourceRange()
+      << QualType(SourceType, 0) << TargetClass;
+    return true;
+  }
+
+  if (!CurContext->isDependentContext())
+    BaseIt->setInheritConstructors();
+
+  return false;
+}
+
+/// Checks that the given using declaration is not an invalid
+/// redeclaration.  Note that this is checking only for the using decl
+/// itself, not for any ill-formedness among the UsingShadowDecls.
+bool Sema::CheckUsingDeclRedeclaration(SourceLocation UsingLoc,
+                                       bool isTypeName,
+                                       const CXXScopeSpec &SS,
+                                       SourceLocation NameLoc,
+                                       const LookupResult &Prev) {
+  // C++03 [namespace.udecl]p8:
+  // C++0x [namespace.udecl]p10:
+  //   A using-declaration is a declaration and can therefore be used
+  //   repeatedly where (and only where) multiple declarations are
+  //   allowed.
+  //
+  // That's in non-member contexts.
+  if (!CurContext->getRedeclContext()->isRecord())
+    return false;
+
+  NestedNameSpecifier *Qual
+    = static_cast<NestedNameSpecifier*>(SS.getScopeRep());
+
+  for (LookupResult::iterator I = Prev.begin(), E = Prev.end(); I != E; ++I) {
+    NamedDecl *D = *I;
+
+    bool DTypename;
+    NestedNameSpecifier *DQual;
+    if (UsingDecl *UD = dyn_cast<UsingDecl>(D)) {
+      DTypename = UD->isTypeName();
+      DQual = UD->getQualifier();
+    } else if (UnresolvedUsingValueDecl *UD
+                 = dyn_cast<UnresolvedUsingValueDecl>(D)) {
+      DTypename = false;
+      DQual = UD->getQualifier();
+    } else if (UnresolvedUsingTypenameDecl *UD
+                 = dyn_cast<UnresolvedUsingTypenameDecl>(D)) {
+      DTypename = true;
+      DQual = UD->getQualifier();
+    } else continue;
+
+    // using decls differ if one says 'typename' and the other doesn't.
+    // FIXME: non-dependent using decls?
+    if (isTypeName != DTypename) continue;
+
+    // using decls differ if they name different scopes (but note that
+    // template instantiation can cause this check to trigger when it
+    // didn't before instantiation).
+    if (Context.getCanonicalNestedNameSpecifier(Qual) !=
+        Context.getCanonicalNestedNameSpecifier(DQual))
+      continue;
+
+    Diag(NameLoc, diag::err_using_decl_redeclaration) << SS.getRange();
+    Diag(D->getLocation(), diag::note_using_decl) << 1;
+    return true;
+  }
+
+  return false;
+}
+
+
+/// Checks that the given nested-name qualifier used in a using decl
+/// in the current context is appropriately related to the current
+/// scope.  If an error is found, diagnoses it and returns true.
+bool Sema::CheckUsingDeclQualifier(SourceLocation UsingLoc,
+                                   const CXXScopeSpec &SS,
+                                   SourceLocation NameLoc) {
+  DeclContext *NamedContext = computeDeclContext(SS);
+
+  if (!CurContext->isRecord()) {
+    // C++03 [namespace.udecl]p3:
+    // C++0x [namespace.udecl]p8:
+    //   A using-declaration for a class member shall be a member-declaration.
+
+    // If we weren't able to compute a valid scope, it must be a
+    // dependent class scope.
+    if (!NamedContext || NamedContext->isRecord()) {
+      Diag(NameLoc, diag::err_using_decl_can_not_refer_to_class_member)
+        << SS.getRange();
+      return true;
+    }
+
+    // Otherwise, everything is known to be fine.
+    return false;
+  }
+
+  // The current scope is a record.
+
+  // If the named context is dependent, we can't decide much.
+  if (!NamedContext) {
+    // FIXME: in C++0x, we can diagnose if we can prove that the
+    // nested-name-specifier does not refer to a base class, which is
+    // still possible in some cases.
+
+    // Otherwise we have to conservatively report that things might be
+    // okay.
+    return false;
+  }
+
+  if (!NamedContext->isRecord()) {
+    // Ideally this would point at the last name in the specifier,
+    // but we don't have that level of source info.
+    Diag(SS.getRange().getBegin(),
+         diag::err_using_decl_nested_name_specifier_is_not_class)
+      << (NestedNameSpecifier*) SS.getScopeRep() << SS.getRange();
+    return true;
+  }
+
+  if (!NamedContext->isDependentContext() &&
+      RequireCompleteDeclContext(const_cast<CXXScopeSpec&>(SS), NamedContext))
+    return true;
+
+  if (getLangOpts().CPlusPlus0x) {
+    // C++0x [namespace.udecl]p3:
+    //   In a using-declaration used as a member-declaration, the
+    //   nested-name-specifier shall name a base class of the class
+    //   being defined.
+
+    if (cast<CXXRecordDecl>(CurContext)->isProvablyNotDerivedFrom(
+                                 cast<CXXRecordDecl>(NamedContext))) {
+      if (CurContext == NamedContext) {
+        Diag(NameLoc,
+             diag::err_using_decl_nested_name_specifier_is_current_class)
+          << SS.getRange();
+        return true;
+      }
+
+      Diag(SS.getRange().getBegin(),
+           diag::err_using_decl_nested_name_specifier_is_not_base_class)
+        << (NestedNameSpecifier*) SS.getScopeRep()
+        << cast<CXXRecordDecl>(CurContext)
+        << SS.getRange();
+      return true;
+    }
+
+    return false;
+  }
+
+  // C++03 [namespace.udecl]p4:
+  //   A using-declaration used as a member-declaration shall refer
+  //   to a member of a base class of the class being defined [etc.].
+
+  // Salient point: SS doesn't have to name a base class as long as
+  // lookup only finds members from base classes.  Therefore we can
+  // diagnose here only if we can prove that that can't happen,
+  // i.e. if the class hierarchies provably don't intersect.
+
+  // TODO: it would be nice if "definitely valid" results were cached
+  // in the UsingDecl and UsingShadowDecl so that these checks didn't
+  // need to be repeated.
+
+  struct UserData {
+    llvm::SmallPtrSet<const CXXRecordDecl*, 4> Bases;
+
+    static bool collect(const CXXRecordDecl *Base, void *OpaqueData) {
+      UserData *Data = reinterpret_cast<UserData*>(OpaqueData);
+      Data->Bases.insert(Base);
+      return true;
+    }
+
+    bool hasDependentBases(const CXXRecordDecl *Class) {
+      return !Class->forallBases(collect, this);
+    }
+
+    /// Returns true if the base is dependent or is one of the
+    /// accumulated base classes.
+    static bool doesNotContain(const CXXRecordDecl *Base, void *OpaqueData) {
+      UserData *Data = reinterpret_cast<UserData*>(OpaqueData);
+      return !Data->Bases.count(Base);
+    }
+
+    bool mightShareBases(const CXXRecordDecl *Class) {
+      return Bases.count(Class) || !Class->forallBases(doesNotContain, this);
+    }
+  };
+
+  UserData Data;
+
+  // Returns false if we find a dependent base.
+  if (Data.hasDependentBases(cast<CXXRecordDecl>(CurContext)))
+    return false;
+
+  // Returns false if the class has a dependent base or if it or one
+  // of its bases is present in the base set of the current context.
+  if (Data.mightShareBases(cast<CXXRecordDecl>(NamedContext)))
+    return false;
+
+  Diag(SS.getRange().getBegin(),
+       diag::err_using_decl_nested_name_specifier_is_not_base_class)
+    << (NestedNameSpecifier*) SS.getScopeRep()
+    << cast<CXXRecordDecl>(CurContext)
+    << SS.getRange();
+
+  return true;
+}
+
+Decl *Sema::ActOnAliasDeclaration(Scope *S,
+                                  AccessSpecifier AS,
+                                  MultiTemplateParamsArg TemplateParamLists,
+                                  SourceLocation UsingLoc,
+                                  UnqualifiedId &Name,
+                                  TypeResult Type) {
+  // Skip up to the relevant declaration scope.
+  while (S->getFlags() & Scope::TemplateParamScope)
+    S = S->getParent();
+  assert((S->getFlags() & Scope::DeclScope) &&
+         "got alias-declaration outside of declaration scope");
+
+  if (Type.isInvalid())
+    return 0;
+
+  bool Invalid = false;
+  DeclarationNameInfo NameInfo = GetNameFromUnqualifiedId(Name);
+  TypeSourceInfo *TInfo = 0;
+  GetTypeFromParser(Type.get(), &TInfo);
+
+  if (DiagnoseClassNameShadow(CurContext, NameInfo))
+    return 0;
+
+  if (DiagnoseUnexpandedParameterPack(Name.StartLocation, TInfo,
+                                      UPPC_DeclarationType)) {
+    Invalid = true;
+    TInfo = Context.getTrivialTypeSourceInfo(Context.IntTy, 
+                                             TInfo->getTypeLoc().getBeginLoc());
+  }
+
+  LookupResult Previous(*this, NameInfo, LookupOrdinaryName, ForRedeclaration);
+  LookupName(Previous, S);
+
+  // Warn about shadowing the name of a template parameter.
+  if (Previous.isSingleResult() &&
+      Previous.getFoundDecl()->isTemplateParameter()) {
+    DiagnoseTemplateParameterShadow(Name.StartLocation,Previous.getFoundDecl());
+    Previous.clear();
+  }
+
+  assert(Name.Kind == UnqualifiedId::IK_Identifier &&
+         "name in alias declaration must be an identifier");
+  TypeAliasDecl *NewTD = TypeAliasDecl::Create(Context, CurContext, UsingLoc,
+                                               Name.StartLocation,
+                                               Name.Identifier, TInfo);
+
+  NewTD->setAccess(AS);
+
+  if (Invalid)
+    NewTD->setInvalidDecl();
+
+  CheckTypedefForVariablyModifiedType(S, NewTD);
+  Invalid |= NewTD->isInvalidDecl();
+
+  bool Redeclaration = false;
+
+  NamedDecl *NewND;
+  if (TemplateParamLists.size()) {
+    TypeAliasTemplateDecl *OldDecl = 0;
+    TemplateParameterList *OldTemplateParams = 0;
+
+    if (TemplateParamLists.size() != 1) {
+      Diag(UsingLoc, diag::err_alias_template_extra_headers)
+        << SourceRange(TemplateParamLists.get()[1]->getTemplateLoc(),
+         TemplateParamLists.get()[TemplateParamLists.size()-1]->getRAngleLoc());
+    }
+    TemplateParameterList *TemplateParams = TemplateParamLists.get()[0];
+
+    // Only consider previous declarations in the same scope.
+    FilterLookupForScope(Previous, CurContext, S, /*ConsiderLinkage*/false,
+                         /*ExplicitInstantiationOrSpecialization*/false);
+    if (!Previous.empty()) {
+      Redeclaration = true;
+
+      OldDecl = Previous.getAsSingle<TypeAliasTemplateDecl>();
+      if (!OldDecl && !Invalid) {
+        Diag(UsingLoc, diag::err_redefinition_different_kind)
+          << Name.Identifier;
+
+        NamedDecl *OldD = Previous.getRepresentativeDecl();
+        if (OldD->getLocation().isValid())
+          Diag(OldD->getLocation(), diag::note_previous_definition);
+
+        Invalid = true;
+      }
+
+      if (!Invalid && OldDecl && !OldDecl->isInvalidDecl()) {
+        if (TemplateParameterListsAreEqual(TemplateParams,
+                                           OldDecl->getTemplateParameters(),
+                                           /*Complain=*/true,
+                                           TPL_TemplateMatch))
+          OldTemplateParams = OldDecl->getTemplateParameters();
+        else
+          Invalid = true;
+
+        TypeAliasDecl *OldTD = OldDecl->getTemplatedDecl();
+        if (!Invalid &&
+            !Context.hasSameType(OldTD->getUnderlyingType(),
+                                 NewTD->getUnderlyingType())) {
+          // FIXME: The C++0x standard does not clearly say this is ill-formed,
+          // but we can't reasonably accept it.
+          Diag(NewTD->getLocation(), diag::err_redefinition_different_typedef)
+            << 2 << NewTD->getUnderlyingType() << OldTD->getUnderlyingType();
+          if (OldTD->getLocation().isValid())
+            Diag(OldTD->getLocation(), diag::note_previous_definition);
+          Invalid = true;
+        }
+      }
+    }
+
+    // Merge any previous default template arguments into our parameters,
+    // and check the parameter list.
+    if (CheckTemplateParameterList(TemplateParams, OldTemplateParams,
+                                   TPC_TypeAliasTemplate))
+      return 0;
+
+    TypeAliasTemplateDecl *NewDecl =
+      TypeAliasTemplateDecl::Create(Context, CurContext, UsingLoc,
+                                    Name.Identifier, TemplateParams,
+                                    NewTD);
+
+    NewDecl->setAccess(AS);
+
+    if (Invalid)
+      NewDecl->setInvalidDecl();
+    else if (OldDecl)
+      NewDecl->setPreviousDeclaration(OldDecl);
+
+    NewND = NewDecl;
+  } else {
+    ActOnTypedefNameDecl(S, CurContext, NewTD, Previous, Redeclaration);
+    NewND = NewTD;
+  }
+
+  if (!Redeclaration)
+    PushOnScopeChains(NewND, S);
+
+  return NewND;
+}
+
+Decl *Sema::ActOnNamespaceAliasDef(Scope *S,
+                                             SourceLocation NamespaceLoc,
+                                             SourceLocation AliasLoc,
+                                             IdentifierInfo *Alias,
+                                             CXXScopeSpec &SS,
+                                             SourceLocation IdentLoc,
+                                             IdentifierInfo *Ident) {
+
+  // Lookup the namespace name.
+  LookupResult R(*this, Ident, IdentLoc, LookupNamespaceName);
+  LookupParsedName(R, S, &SS);
+
+  // Check if we have a previous declaration with the same name.
+  NamedDecl *PrevDecl
+    = LookupSingleName(S, Alias, AliasLoc, LookupOrdinaryName, 
+                       ForRedeclaration);
+  if (PrevDecl && !isDeclInScope(PrevDecl, CurContext, S))
+    PrevDecl = 0;
+
+  if (PrevDecl) {
+    if (NamespaceAliasDecl *AD = dyn_cast<NamespaceAliasDecl>(PrevDecl)) {
+      // We already have an alias with the same name that points to the same
+      // namespace, so don't create a new one.
+      // FIXME: At some point, we'll want to create the (redundant)
+      // declaration to maintain better source information.
+      if (!R.isAmbiguous() && !R.empty() &&
+          AD->getNamespace()->Equals(getNamespaceDecl(R.getFoundDecl())))
+        return 0;
+    }
+
+    unsigned DiagID = isa<NamespaceDecl>(PrevDecl) ? diag::err_redefinition :
+      diag::err_redefinition_different_kind;
+    Diag(AliasLoc, DiagID) << Alias;
+    Diag(PrevDecl->getLocation(), diag::note_previous_definition);
+    return 0;
+  }
+
+  if (R.isAmbiguous())
+    return 0;
+
+  if (R.empty()) {
+    if (!TryNamespaceTypoCorrection(*this, R, S, SS, IdentLoc, Ident)) {
+      Diag(IdentLoc, diag::err_expected_namespace_name) << SS.getRange();
+      return 0;
+    }
+  }
+
+  NamespaceAliasDecl *AliasDecl =
+    NamespaceAliasDecl::Create(Context, CurContext, NamespaceLoc, AliasLoc,
+                               Alias, SS.getWithLocInContext(Context),
+                               IdentLoc, R.getFoundDecl());
+
+  PushOnScopeChains(AliasDecl, S);
+  return AliasDecl;
+}
+
+namespace {
+  /// \brief Scoped object used to handle the state changes required in Sema
+  /// to implicitly define the body of a C++ member function;
+  class ImplicitlyDefinedFunctionScope {
+    Sema &S;
+    Sema::ContextRAII SavedContext;
+    
+  public:
+    ImplicitlyDefinedFunctionScope(Sema &S, CXXMethodDecl *Method)
+      : S(S), SavedContext(S, Method) 
+    {
+      S.PushFunctionScope();
+      S.PushExpressionEvaluationContext(Sema::PotentiallyEvaluated);
+    }
+    
+    ~ImplicitlyDefinedFunctionScope() {
+      S.PopExpressionEvaluationContext();
+      S.PopFunctionScopeInfo();
+    }
+  };
+}
+
+Sema::ImplicitExceptionSpecification
+Sema::ComputeDefaultedDefaultCtorExceptionSpec(CXXRecordDecl *ClassDecl) {
+  // C++ [except.spec]p14:
+  //   An implicitly declared special member function (Clause 12) shall have an 
+  //   exception-specification. [...]
+  ImplicitExceptionSpecification ExceptSpec(*this);
+  if (ClassDecl->isInvalidDecl())
+    return ExceptSpec;
+
+  // Direct base-class constructors.
+  for (CXXRecordDecl::base_class_iterator B = ClassDecl->bases_begin(),
+                                       BEnd = ClassDecl->bases_end();
+       B != BEnd; ++B) {
+    if (B->isVirtual()) // Handled below.
+      continue;
+    
+    if (const RecordType *BaseType = B->getType()->getAs<RecordType>()) {
+      CXXRecordDecl *BaseClassDecl = cast<CXXRecordDecl>(BaseType->getDecl());
+      CXXConstructorDecl *Constructor = LookupDefaultConstructor(BaseClassDecl);
+      // If this is a deleted function, add it anyway. This might be conformant
+      // with the standard. This might not. I'm not sure. It might not matter.
+      if (Constructor)
+        ExceptSpec.CalledDecl(B->getLocStart(), Constructor);
+    }
+  }
+
+  // Virtual base-class constructors.
+  for (CXXRecordDecl::base_class_iterator B = ClassDecl->vbases_begin(),
+                                       BEnd = ClassDecl->vbases_end();
+       B != BEnd; ++B) {
+    if (const RecordType *BaseType = B->getType()->getAs<RecordType>()) {
+      CXXRecordDecl *BaseClassDecl = cast<CXXRecordDecl>(BaseType->getDecl());
+      CXXConstructorDecl *Constructor = LookupDefaultConstructor(BaseClassDecl);
+      // If this is a deleted function, add it anyway. This might be conformant
+      // with the standard. This might not. I'm not sure. It might not matter.
+      if (Constructor)
+        ExceptSpec.CalledDecl(B->getLocStart(), Constructor);
+    }
+  }
+
+  // Field constructors.
+  for (RecordDecl::field_iterator F = ClassDecl->field_begin(),
+                               FEnd = ClassDecl->field_end();
+       F != FEnd; ++F) {
+    if (F->hasInClassInitializer()) {
+      if (Expr *E = F->getInClassInitializer())
+        ExceptSpec.CalledExpr(E);
+      else if (!F->isInvalidDecl())
+        ExceptSpec.SetDelayed();
+    } else if (const RecordType *RecordTy
+              = Context.getBaseElementType(F->getType())->getAs<RecordType>()) {
+      CXXRecordDecl *FieldRecDecl = cast<CXXRecordDecl>(RecordTy->getDecl());
+      CXXConstructorDecl *Constructor = LookupDefaultConstructor(FieldRecDecl);
+      // If this is a deleted function, add it anyway. This might be conformant
+      // with the standard. This might not. I'm not sure. It might not matter.
+      // In particular, the problem is that this function never gets called. It
+      // might just be ill-formed because this function attempts to refer to
+      // a deleted function here.
+      if (Constructor)
+        ExceptSpec.CalledDecl(F->getLocation(), Constructor);
+    }
+  }
+
+  return ExceptSpec;
+}
+
+CXXConstructorDecl *Sema::DeclareImplicitDefaultConstructor(
+                                                     CXXRecordDecl *ClassDecl) {
+  // C++ [class.ctor]p5:
+  //   A default constructor for a class X is a constructor of class X
+  //   that can be called without an argument. If there is no
+  //   user-declared constructor for class X, a default constructor is
+  //   implicitly declared. An implicitly-declared default constructor
+  //   is an inline public member of its class.
+  assert(!ClassDecl->hasUserDeclaredConstructor() && 
+         "Should not build implicit default constructor!");
+
+  ImplicitExceptionSpecification Spec = 
+    ComputeDefaultedDefaultCtorExceptionSpec(ClassDecl);
+  FunctionProtoType::ExtProtoInfo EPI = Spec.getEPI();
+
+  // Create the actual constructor declaration.
+  CanQualType ClassType
+    = Context.getCanonicalType(Context.getTypeDeclType(ClassDecl));
+  SourceLocation ClassLoc = ClassDecl->getLocation();
+  DeclarationName Name
+    = Context.DeclarationNames.getCXXConstructorName(ClassType);
+  DeclarationNameInfo NameInfo(Name, ClassLoc);
+  CXXConstructorDecl *DefaultCon = CXXConstructorDecl::Create(
+      Context, ClassDecl, ClassLoc, NameInfo,
+      Context.getFunctionType(Context.VoidTy, 0, 0, EPI), /*TInfo=*/0,
+      /*isExplicit=*/false, /*isInline=*/true, /*isImplicitlyDeclared=*/true,
+      /*isConstexpr=*/ClassDecl->defaultedDefaultConstructorIsConstexpr() &&
+        getLangOpts().CPlusPlus0x);
+  DefaultCon->setAccess(AS_public);
+  DefaultCon->setDefaulted();
+  DefaultCon->setImplicit();
+  DefaultCon->setTrivial(ClassDecl->hasTrivialDefaultConstructor());
+  
+  // Note that we have declared this constructor.
+  ++ASTContext::NumImplicitDefaultConstructorsDeclared;
+  
+  if (Scope *S = getScopeForContext(ClassDecl))
+    PushOnScopeChains(DefaultCon, S, false);
+  ClassDecl->addDecl(DefaultCon);
+
+  if (ShouldDeleteSpecialMember(DefaultCon, CXXDefaultConstructor))
+    DefaultCon->setDeletedAsWritten();
+  
+  return DefaultCon;
+}
+
+void Sema::DefineImplicitDefaultConstructor(SourceLocation CurrentLocation,
+                                            CXXConstructorDecl *Constructor) {
+  assert((Constructor->isDefaulted() && Constructor->isDefaultConstructor() &&
+          !Constructor->doesThisDeclarationHaveABody() &&
+          !Constructor->isDeleted()) &&
+    "DefineImplicitDefaultConstructor - call it for implicit default ctor");
+
+  CXXRecordDecl *ClassDecl = Constructor->getParent();
+  assert(ClassDecl && "DefineImplicitDefaultConstructor - invalid constructor");
+
+  ImplicitlyDefinedFunctionScope Scope(*this, Constructor);
+  DiagnosticErrorTrap Trap(Diags);
+  if (SetCtorInitializers(Constructor, 0, 0, /*AnyErrors=*/false) ||
+      Trap.hasErrorOccurred()) {
+    Diag(CurrentLocation, diag::note_member_synthesized_at) 
+      << CXXDefaultConstructor << Context.getTagDeclType(ClassDecl);
+    Constructor->setInvalidDecl();
+    return;
+  }
+
+  SourceLocation Loc = Constructor->getLocation();
+  Constructor->setBody(new (Context) CompoundStmt(Context, 0, 0, Loc, Loc));
+
+  Constructor->setUsed();
+  MarkVTableUsed(CurrentLocation, ClassDecl);
+
+  if (ASTMutationListener *L = getASTMutationListener()) {
+    L->CompletedImplicitDefinition(Constructor);
+  }
+}
+
+/// Get any existing defaulted default constructor for the given class. Do not
+/// implicitly define one if it does not exist.
+static CXXConstructorDecl *getDefaultedDefaultConstructorUnsafe(Sema &Self,
+                                                             CXXRecordDecl *D) {
+  ASTContext &Context = Self.Context;
+  QualType ClassType = Context.getTypeDeclType(D);
+  DeclarationName ConstructorName
+    = Context.DeclarationNames.getCXXConstructorName(
+                      Context.getCanonicalType(ClassType.getUnqualifiedType()));
+
+  DeclContext::lookup_const_iterator Con, ConEnd;
+  for (llvm::tie(Con, ConEnd) = D->lookup(ConstructorName);
+       Con != ConEnd; ++Con) {
+    // A function template cannot be defaulted.
+    if (isa<FunctionTemplateDecl>(*Con))
+      continue;
+
+    CXXConstructorDecl *Constructor = cast<CXXConstructorDecl>(*Con);
+    if (Constructor->isDefaultConstructor())
+      return Constructor->isDefaulted() ? Constructor : 0;
+  }
+  return 0;
+}
+
+void Sema::ActOnFinishDelayedMemberInitializers(Decl *D) {
+  if (!D) return;
+  AdjustDeclIfTemplate(D);
+
+  CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(D);
+  CXXConstructorDecl *CtorDecl
+    = getDefaultedDefaultConstructorUnsafe(*this, ClassDecl);
+
+  if (!CtorDecl) return;
+
+  // Compute the exception specification for the default constructor.
+  const FunctionProtoType *CtorTy =
+    CtorDecl->getType()->castAs<FunctionProtoType>();
+  if (CtorTy->getExceptionSpecType() == EST_Delayed) {
+    // FIXME: Don't do this unless the exception spec is needed.
+    ImplicitExceptionSpecification Spec = 
+      ComputeDefaultedDefaultCtorExceptionSpec(ClassDecl);
+    FunctionProtoType::ExtProtoInfo EPI = Spec.getEPI();
+    assert(EPI.ExceptionSpecType != EST_Delayed);
+
+    CtorDecl->setType(Context.getFunctionType(Context.VoidTy, 0, 0, EPI));
+  }
+
+  // If the default constructor is explicitly defaulted, checking the exception
+  // specification is deferred until now.
+  if (!CtorDecl->isInvalidDecl() && CtorDecl->isExplicitlyDefaulted() &&
+      !ClassDecl->isDependentType())
+    CheckExplicitlyDefaultedDefaultConstructor(CtorDecl);
+}
+
+void Sema::DeclareInheritedConstructors(CXXRecordDecl *ClassDecl) {
+  // We start with an initial pass over the base classes to collect those that
+  // inherit constructors from. If there are none, we can forgo all further
+  // processing.
+  typedef SmallVector<const RecordType *, 4> BasesVector;
+  BasesVector BasesToInheritFrom;
+  for (CXXRecordDecl::base_class_iterator BaseIt = ClassDecl->bases_begin(),
+                                          BaseE = ClassDecl->bases_end();
+         BaseIt != BaseE; ++BaseIt) {
+    if (BaseIt->getInheritConstructors()) {
+      QualType Base = BaseIt->getType();
+      if (Base->isDependentType()) {
+        // If we inherit constructors from anything that is dependent, just
+        // abort processing altogether. We'll get another chance for the
+        // instantiations.
+        return;
+      }
+      BasesToInheritFrom.push_back(Base->castAs<RecordType>());
+    }
+  }
+  if (BasesToInheritFrom.empty())
+    return;
+
+  // Now collect the constructors that we already have in the current class.
+  // Those take precedence over inherited constructors.
+  // C++0x [class.inhctor]p3: [...] a constructor is implicitly declared [...]
+  //   unless there is a user-declared constructor with the same signature in
+  //   the class where the using-declaration appears.
+  llvm::SmallSet<const Type *, 8> ExistingConstructors;
+  for (CXXRecordDecl::ctor_iterator CtorIt = ClassDecl->ctor_begin(),
+                                    CtorE = ClassDecl->ctor_end();
+       CtorIt != CtorE; ++CtorIt) {
+    ExistingConstructors.insert(
+        Context.getCanonicalType(CtorIt->getType()).getTypePtr());
+  }
+
+  DeclarationName CreatedCtorName =
+      Context.DeclarationNames.getCXXConstructorName(
+          ClassDecl->getTypeForDecl()->getCanonicalTypeUnqualified());
+
+  // Now comes the true work.
+  // First, we keep a map from constructor types to the base that introduced
+  // them. Needed for finding conflicting constructors. We also keep the
+  // actually inserted declarations in there, for pretty diagnostics.
+  typedef std::pair<CanQualType, CXXConstructorDecl *> ConstructorInfo;
+  typedef llvm::DenseMap<const Type *, ConstructorInfo> ConstructorToSourceMap;
+  ConstructorToSourceMap InheritedConstructors;
+  for (BasesVector::iterator BaseIt = BasesToInheritFrom.begin(),
+                             BaseE = BasesToInheritFrom.end();
+       BaseIt != BaseE; ++BaseIt) {
+    const RecordType *Base = *BaseIt;
+    CanQualType CanonicalBase = Base->getCanonicalTypeUnqualified();
+    CXXRecordDecl *BaseDecl = cast<CXXRecordDecl>(Base->getDecl());
+    for (CXXRecordDecl::ctor_iterator CtorIt = BaseDecl->ctor_begin(),
+                                      CtorE = BaseDecl->ctor_end();
+         CtorIt != CtorE; ++CtorIt) {
+      // Find the using declaration for inheriting this base's constructors.
+      // FIXME: Don't perform name lookup just to obtain a source location!
+      DeclarationName Name =
+          Context.DeclarationNames.getCXXConstructorName(CanonicalBase);
+      LookupResult Result(*this, Name, SourceLocation(), LookupUsingDeclName);
+      LookupQualifiedName(Result, CurContext);
+      UsingDecl *UD = Result.getAsSingle<UsingDecl>();
+      SourceLocation UsingLoc = UD ? UD->getLocation() :
+                                     ClassDecl->getLocation();
+
+      // C++0x [class.inhctor]p1: The candidate set of inherited constructors
+      //   from the class X named in the using-declaration consists of actual
+      //   constructors and notional constructors that result from the
+      //   transformation of defaulted parameters as follows:
+      //   - all non-template default constructors of X, and
+      //   - for each non-template constructor of X that has at least one
+      //     parameter with a default argument, the set of constructors that
+      //     results from omitting any ellipsis parameter specification and
+      //     successively omitting parameters with a default argument from the
+      //     end of the parameter-type-list.
+      CXXConstructorDecl *BaseCtor = *CtorIt;
+      bool CanBeCopyOrMove = BaseCtor->isCopyOrMoveConstructor();
+      const FunctionProtoType *BaseCtorType =
+          BaseCtor->getType()->getAs<FunctionProtoType>();
+
+      for (unsigned params = BaseCtor->getMinRequiredArguments(),
+                    maxParams = BaseCtor->getNumParams();
+           params <= maxParams; ++params) {
+        // Skip default constructors. They're never inherited.
+        if (params == 0)
+          continue;
+        // Skip copy and move constructors for the same reason.
+        if (CanBeCopyOrMove && params == 1)
+          continue;
+
+        // Build up a function type for this particular constructor.
+        // FIXME: The working paper does not consider that the exception spec
+        // for the inheriting constructor might be larger than that of the
+        // source. This code doesn't yet, either. When it does, this code will
+        // need to be delayed until after exception specifications and in-class
+        // member initializers are attached.
+        const Type *NewCtorType;
+        if (params == maxParams)
+          NewCtorType = BaseCtorType;
+        else {
+          SmallVector<QualType, 16> Args;
+          for (unsigned i = 0; i < params; ++i) {
+            Args.push_back(BaseCtorType->getArgType(i));
+          }
+          FunctionProtoType::ExtProtoInfo ExtInfo =
+              BaseCtorType->getExtProtoInfo();
+          ExtInfo.Variadic = false;
+          NewCtorType = Context.getFunctionType(BaseCtorType->getResultType(),
+                                                Args.data(), params, ExtInfo)
+                       .getTypePtr();
+        }
+        const Type *CanonicalNewCtorType =
+            Context.getCanonicalType(NewCtorType);
+
+        // Now that we have the type, first check if the class already has a
+        // constructor with this signature.
+        if (ExistingConstructors.count(CanonicalNewCtorType))
+          continue;
+
+        // Then we check if we have already declared an inherited constructor
+        // with this signature.
+        std::pair<ConstructorToSourceMap::iterator, bool> result =
+            InheritedConstructors.insert(std::make_pair(
+                CanonicalNewCtorType,
+                std::make_pair(CanonicalBase, (CXXConstructorDecl*)0)));
+        if (!result.second) {
+          // Already in the map. If it came from a different class, that's an
+          // error. Not if it's from the same.
+          CanQualType PreviousBase = result.first->second.first;
+          if (CanonicalBase != PreviousBase) {
+            const CXXConstructorDecl *PrevCtor = result.first->second.second;
+            const CXXConstructorDecl *PrevBaseCtor =
+                PrevCtor->getInheritedConstructor();
+            assert(PrevBaseCtor && "Conflicting constructor was not inherited");
+
+            Diag(UsingLoc, diag::err_using_decl_constructor_conflict);
+            Diag(BaseCtor->getLocation(),
+                 diag::note_using_decl_constructor_conflict_current_ctor);
+            Diag(PrevBaseCtor->getLocation(),
+                 diag::note_using_decl_constructor_conflict_previous_ctor);
+            Diag(PrevCtor->getLocation(),
+                 diag::note_using_decl_constructor_conflict_previous_using);
+          }
+          continue;
+        }
+
+        // OK, we're there, now add the constructor.
+        // C++0x [class.inhctor]p8: [...] that would be performed by a
+        //   user-written inline constructor [...]
+        DeclarationNameInfo DNI(CreatedCtorName, UsingLoc);
+        CXXConstructorDecl *NewCtor = CXXConstructorDecl::Create(
+            Context, ClassDecl, UsingLoc, DNI, QualType(NewCtorType, 0),
+            /*TInfo=*/0, BaseCtor->isExplicit(), /*Inline=*/true,
+            /*ImplicitlyDeclared=*/true,
+            // FIXME: Due to a defect in the standard, we treat inherited
+            // constructors as constexpr even if that makes them ill-formed.
+            /*Constexpr=*/BaseCtor->isConstexpr());
+        NewCtor->setAccess(BaseCtor->getAccess());
+
+        // Build up the parameter decls and add them.
+        SmallVector<ParmVarDecl *, 16> ParamDecls;
+        for (unsigned i = 0; i < params; ++i) {
+          ParamDecls.push_back(ParmVarDecl::Create(Context, NewCtor,
+                                                   UsingLoc, UsingLoc,
+                                                   /*IdentifierInfo=*/0,
+                                                   BaseCtorType->getArgType(i),
+                                                   /*TInfo=*/0, SC_None,
+                                                   SC_None, /*DefaultArg=*/0));
+        }
+        NewCtor->setParams(ParamDecls);
+        NewCtor->setInheritedConstructor(BaseCtor);
+
+        ClassDecl->addDecl(NewCtor);
+        result.first->second.second = NewCtor;
+      }
+    }
+  }
+}
+
+Sema::ImplicitExceptionSpecification
+Sema::ComputeDefaultedDtorExceptionSpec(CXXRecordDecl *ClassDecl) {
+  // C++ [except.spec]p14: 
+  //   An implicitly declared special member function (Clause 12) shall have 
+  //   an exception-specification.
+  ImplicitExceptionSpecification ExceptSpec(*this);
+  if (ClassDecl->isInvalidDecl())
+    return ExceptSpec;
+
+  // Direct base-class destructors.
+  for (CXXRecordDecl::base_class_iterator B = ClassDecl->bases_begin(),
+                                       BEnd = ClassDecl->bases_end();
+       B != BEnd; ++B) {
+    if (B->isVirtual()) // Handled below.
+      continue;
+    
+    if (const RecordType *BaseType = B->getType()->getAs<RecordType>())
+      ExceptSpec.CalledDecl(B->getLocStart(),
+                   LookupDestructor(cast<CXXRecordDecl>(BaseType->getDecl())));
+  }
+
+  // Virtual base-class destructors.
+  for (CXXRecordDecl::base_class_iterator B = ClassDecl->vbases_begin(),
+                                       BEnd = ClassDecl->vbases_end();
+       B != BEnd; ++B) {
+    if (const RecordType *BaseType = B->getType()->getAs<RecordType>())
+      ExceptSpec.CalledDecl(B->getLocStart(),
+                  LookupDestructor(cast<CXXRecordDecl>(BaseType->getDecl())));
+  }
+
+  // Field destructors.
+  for (RecordDecl::field_iterator F = ClassDecl->field_begin(),
+                               FEnd = ClassDecl->field_end();
+       F != FEnd; ++F) {
+    if (const RecordType *RecordTy
+        = Context.getBaseElementType(F->getType())->getAs<RecordType>())
+      ExceptSpec.CalledDecl(F->getLocation(),
+                  LookupDestructor(cast<CXXRecordDecl>(RecordTy->getDecl())));
+  }
+
+  return ExceptSpec;
+}
+
+CXXDestructorDecl *Sema::DeclareImplicitDestructor(CXXRecordDecl *ClassDecl) {
+  // C++ [class.dtor]p2:
+  //   If a class has no user-declared destructor, a destructor is
+  //   declared implicitly. An implicitly-declared destructor is an
+  //   inline public member of its class.
+  
+  ImplicitExceptionSpecification Spec =
+      ComputeDefaultedDtorExceptionSpec(ClassDecl); 
+  FunctionProtoType::ExtProtoInfo EPI = Spec.getEPI();
+
+  // Create the actual destructor declaration.
+  QualType Ty = Context.getFunctionType(Context.VoidTy, 0, 0, EPI);
+
+  CanQualType ClassType
+    = Context.getCanonicalType(Context.getTypeDeclType(ClassDecl));
+  SourceLocation ClassLoc = ClassDecl->getLocation();
+  DeclarationName Name
+    = Context.DeclarationNames.getCXXDestructorName(ClassType);
+  DeclarationNameInfo NameInfo(Name, ClassLoc);
+  CXXDestructorDecl *Destructor
+      = CXXDestructorDecl::Create(Context, ClassDecl, ClassLoc, NameInfo, Ty, 0,
+                                  /*isInline=*/true,
+                                  /*isImplicitlyDeclared=*/true);
+  Destructor->setAccess(AS_public);
+  Destructor->setDefaulted();
+  Destructor->setImplicit();
+  Destructor->setTrivial(ClassDecl->hasTrivialDestructor());
+  
+  // Note that we have declared this destructor.
+  ++ASTContext::NumImplicitDestructorsDeclared;
+  
+  // Introduce this destructor into its scope.
+  if (Scope *S = getScopeForContext(ClassDecl))
+    PushOnScopeChains(Destructor, S, false);
+  ClassDecl->addDecl(Destructor);
+  
+  // This could be uniqued if it ever proves significant.
+  Destructor->setTypeSourceInfo(Context.getTrivialTypeSourceInfo(Ty));
+
+  AddOverriddenMethods(ClassDecl, Destructor);
+
+  if (ShouldDeleteSpecialMember(Destructor, CXXDestructor))
+    Destructor->setDeletedAsWritten();
+
+  return Destructor;
+}
+
+void Sema::DefineImplicitDestructor(SourceLocation CurrentLocation,
+                                    CXXDestructorDecl *Destructor) {
+  assert((Destructor->isDefaulted() &&
+          !Destructor->doesThisDeclarationHaveABody() &&
+          !Destructor->isDeleted()) &&
+         "DefineImplicitDestructor - call it for implicit default dtor");
+  CXXRecordDecl *ClassDecl = Destructor->getParent();
+  assert(ClassDecl && "DefineImplicitDestructor - invalid destructor");
+
+  if (Destructor->isInvalidDecl())
+    return;
+
+  ImplicitlyDefinedFunctionScope Scope(*this, Destructor);
+
+  DiagnosticErrorTrap Trap(Diags);
+  MarkBaseAndMemberDestructorsReferenced(Destructor->getLocation(),
+                                         Destructor->getParent());
+
+  if (CheckDestructor(Destructor) || Trap.hasErrorOccurred()) {
+    Diag(CurrentLocation, diag::note_member_synthesized_at) 
+      << CXXDestructor << Context.getTagDeclType(ClassDecl);
+
+    Destructor->setInvalidDecl();
+    return;
+  }
+
+  SourceLocation Loc = Destructor->getLocation();
+  Destructor->setBody(new (Context) CompoundStmt(Context, 0, 0, Loc, Loc));
+  Destructor->setImplicitlyDefined(true);
+  Destructor->setUsed();
+  MarkVTableUsed(CurrentLocation, ClassDecl);
+
+  if (ASTMutationListener *L = getASTMutationListener()) {
+    L->CompletedImplicitDefinition(Destructor);
+  }
+}
+
+/// \brief Perform any semantic analysis which needs to be delayed until all
+/// pending class member declarations have been parsed.
+void Sema::ActOnFinishCXXMemberDecls() {
+  // Now we have parsed all exception specifications, determine the implicit
+  // exception specifications for destructors.
+  for (unsigned i = 0, e = DelayedDestructorExceptionSpecs.size();
+       i != e; ++i) {
+    CXXDestructorDecl *Dtor = DelayedDestructorExceptionSpecs[i];
+    AdjustDestructorExceptionSpec(Dtor->getParent(), Dtor, true);
+  }
+  DelayedDestructorExceptionSpecs.clear();
+
+  // Perform any deferred checking of exception specifications for virtual
+  // destructors.
+  for (unsigned i = 0, e = DelayedDestructorExceptionSpecChecks.size();
+       i != e; ++i) {
+    const CXXDestructorDecl *Dtor =
+        DelayedDestructorExceptionSpecChecks[i].first;
+    assert(!Dtor->getParent()->isDependentType() &&
+           "Should not ever add destructors of templates into the list.");
+    CheckOverridingFunctionExceptionSpec(Dtor,
+        DelayedDestructorExceptionSpecChecks[i].second);
+  }
+  DelayedDestructorExceptionSpecChecks.clear();
+}
+
+void Sema::AdjustDestructorExceptionSpec(CXXRecordDecl *classDecl,
+                                         CXXDestructorDecl *destructor,
+                                         bool WasDelayed) {
+  // C++11 [class.dtor]p3:
+  //   A declaration of a destructor that does not have an exception-
+  //   specification is implicitly considered to have the same exception-
+  //   specification as an implicit declaration.
+  const FunctionProtoType *dtorType = destructor->getType()->
+                                        getAs<FunctionProtoType>();
+  if (!WasDelayed && dtorType->hasExceptionSpec())
+    return;
+
+  ImplicitExceptionSpecification exceptSpec =
+      ComputeDefaultedDtorExceptionSpec(classDecl);
+
+  // Replace the destructor's type, building off the existing one. Fortunately,
+  // the only thing of interest in the destructor type is its extended info.
+  // The return and arguments are fixed.
+  FunctionProtoType::ExtProtoInfo epi = dtorType->getExtProtoInfo();
+  epi.ExceptionSpecType = exceptSpec.getExceptionSpecType();
+  epi.NumExceptions = exceptSpec.size();
+  epi.Exceptions = exceptSpec.data();
+  QualType ty = Context.getFunctionType(Context.VoidTy, 0, 0, epi);
+
+  destructor->setType(ty);
+
+  // If we can't compute the exception specification for this destructor yet
+  // (because it depends on an exception specification which we have not parsed
+  // yet), make a note that we need to try again when the class is complete.
+  if (epi.ExceptionSpecType == EST_Delayed) {
+    assert(!WasDelayed && "couldn't compute destructor exception spec");
+    DelayedDestructorExceptionSpecs.push_back(destructor);
+  }
+
+  // FIXME: If the destructor has a body that could throw, and the newly created
+  // spec doesn't allow exceptions, we should emit a warning, because this
+  // change in behavior can break conforming C++03 programs at runtime.
+  // However, we don't have a body yet, so it needs to be done somewhere else.
+}
+
+/// \brief Builds a statement that copies/moves the given entity from \p From to
+/// \c To.
+///
+/// This routine is used to copy/move the members of a class with an
+/// implicitly-declared copy/move assignment operator. When the entities being
+/// copied are arrays, this routine builds for loops to copy them.
+///
+/// \param S The Sema object used for type-checking.
+///
+/// \param Loc The location where the implicit copy/move is being generated.
+///
+/// \param T The type of the expressions being copied/moved. Both expressions
+/// must have this type.
+///
+/// \param To The expression we are copying/moving to.
+///
+/// \param From The expression we are copying/moving from.
+///
+/// \param CopyingBaseSubobject Whether we're copying/moving a base subobject.
+/// Otherwise, it's a non-static member subobject.
+///
+/// \param Copying Whether we're copying or moving.
+///
+/// \param Depth Internal parameter recording the depth of the recursion.
+///
+/// \returns A statement or a loop that copies the expressions.
+static StmtResult
+BuildSingleCopyAssign(Sema &S, SourceLocation Loc, QualType T, 
+                      Expr *To, Expr *From,
+                      bool CopyingBaseSubobject, bool Copying,
+                      unsigned Depth = 0) {
+  // C++0x [class.copy]p28:
+  //   Each subobject is assigned in the manner appropriate to its type:
+  //
+  //     - if the subobject is of class type, as if by a call to operator= with
+  //       the subobject as the object expression and the corresponding
+  //       subobject of x as a single function argument (as if by explicit
+  //       qualification; that is, ignoring any possible virtual overriding
+  //       functions in more derived classes);
+  if (const RecordType *RecordTy = T->getAs<RecordType>()) {
+    CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(RecordTy->getDecl());
+    
+    // Look for operator=.
+    DeclarationName Name
+      = S.Context.DeclarationNames.getCXXOperatorName(OO_Equal);
+    LookupResult OpLookup(S, Name, Loc, Sema::LookupOrdinaryName);
+    S.LookupQualifiedName(OpLookup, ClassDecl, false);
+    
+    // Filter out any result that isn't a copy/move-assignment operator.
+    LookupResult::Filter F = OpLookup.makeFilter();
+    while (F.hasNext()) {
+      NamedDecl *D = F.next();
+      if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(D))
+        if (Method->isCopyAssignmentOperator() ||
+            (!Copying && Method->isMoveAssignmentOperator()))
+          continue;
+
+      F.erase();
+    }
+    F.done();
+    
+    // Suppress the protected check (C++ [class.protected]) for each of the
+    // assignment operators we found. This strange dance is required when 
+    // we're assigning via a base classes's copy-assignment operator. To
+    // ensure that we're getting the right base class subobject (without 
+    // ambiguities), we need to cast "this" to that subobject type; to
+    // ensure that we don't go through the virtual call mechanism, we need
+    // to qualify the operator= name with the base class (see below). However,
+    // this means that if the base class has a protected copy assignment
+    // operator, the protected member access check will fail. So, we
+    // rewrite "protected" access to "public" access in this case, since we
+    // know by construction that we're calling from a derived class.
+    if (CopyingBaseSubobject) {
+      for (LookupResult::iterator L = OpLookup.begin(), LEnd = OpLookup.end();
+           L != LEnd; ++L) {
+        if (L.getAccess() == AS_protected)
+          L.setAccess(AS_public);
+      }
+    }
+    
+    // Create the nested-name-specifier that will be used to qualify the
+    // reference to operator=; this is required to suppress the virtual
+    // call mechanism.
+    CXXScopeSpec SS;
+    const Type *CanonicalT = S.Context.getCanonicalType(T.getTypePtr());
+    SS.MakeTrivial(S.Context, 
+                   NestedNameSpecifier::Create(S.Context, 0, false, 
+                                               CanonicalT),
+                   Loc);
+    
+    // Create the reference to operator=.
+    ExprResult OpEqualRef
+      = S.BuildMemberReferenceExpr(To, T, Loc, /*isArrow=*/false, SS, 
+                                   /*TemplateKWLoc=*/SourceLocation(),
+                                   /*FirstQualifierInScope=*/0,
+                                   OpLookup,
+                                   /*TemplateArgs=*/0,
+                                   /*SuppressQualifierCheck=*/true);
+    if (OpEqualRef.isInvalid())
+      return StmtError();
+    
+    // Build the call to the assignment operator.
+
+    ExprResult Call = S.BuildCallToMemberFunction(/*Scope=*/0, 
+                                                  OpEqualRef.takeAs<Expr>(),
+                                                  Loc, &From, 1, Loc);
+    if (Call.isInvalid())
+      return StmtError();
+    
+    return S.Owned(Call.takeAs<Stmt>());
+  }
+
+  //     - if the subobject is of scalar type, the built-in assignment 
+  //       operator is used.
+  const ConstantArrayType *ArrayTy = S.Context.getAsConstantArrayType(T);  
+  if (!ArrayTy) {
+    ExprResult Assignment = S.CreateBuiltinBinOp(Loc, BO_Assign, To, From);
+    if (Assignment.isInvalid())
+      return StmtError();
+    
+    return S.Owned(Assignment.takeAs<Stmt>());
+  }
+    
+  //     - if the subobject is an array, each element is assigned, in the 
+  //       manner appropriate to the element type;
+  
+  // Construct a loop over the array bounds, e.g.,
+  //
+  //   for (__SIZE_TYPE__ i0 = 0; i0 != array-size; ++i0)
+  //
+  // that will copy each of the array elements. 
+  QualType SizeType = S.Context.getSizeType();
+  
+  // Create the iteration variable.
+  IdentifierInfo *IterationVarName = 0;
+  {
+    SmallString<8> Str;
+    llvm::raw_svector_ostream OS(Str);
+    OS << "__i" << Depth;
+    IterationVarName = &S.Context.Idents.get(OS.str());
+  }
+  VarDecl *IterationVar = VarDecl::Create(S.Context, S.CurContext, Loc, Loc,
+                                          IterationVarName, SizeType,
+                            S.Context.getTrivialTypeSourceInfo(SizeType, Loc),
+                                          SC_None, SC_None);
+  
+  // Initialize the iteration variable to zero.
+  llvm::APInt Zero(S.Context.getTypeSize(SizeType), 0);
+  IterationVar->setInit(IntegerLiteral::Create(S.Context, Zero, SizeType, Loc));
+
+  // Create a reference to the iteration variable; we'll use this several
+  // times throughout.
+  Expr *IterationVarRef
+    = S.BuildDeclRefExpr(IterationVar, SizeType, VK_LValue, Loc).take();
+  assert(IterationVarRef && "Reference to invented variable cannot fail!");
+  Expr *IterationVarRefRVal = S.DefaultLvalueConversion(IterationVarRef).take();
+  assert(IterationVarRefRVal && "Conversion of invented variable cannot fail!");
+
+  // Create the DeclStmt that holds the iteration variable.
+  Stmt *InitStmt = new (S.Context) DeclStmt(DeclGroupRef(IterationVar),Loc,Loc);
+  
+  // Create the comparison against the array bound.
+  llvm::APInt Upper
+    = ArrayTy->getSize().zextOrTrunc(S.Context.getTypeSize(SizeType));
+  Expr *Comparison
+    = new (S.Context) BinaryOperator(IterationVarRefRVal,
+                     IntegerLiteral::Create(S.Context, Upper, SizeType, Loc),
+                                     BO_NE, S.Context.BoolTy,
+                                     VK_RValue, OK_Ordinary, Loc);
+  
+  // Create the pre-increment of the iteration variable.
+  Expr *Increment
+    = new (S.Context) UnaryOperator(IterationVarRef, UO_PreInc, SizeType,
+                                    VK_LValue, OK_Ordinary, Loc);
+  
+  // Subscript the "from" and "to" expressions with the iteration variable.
+  From = AssertSuccess(S.CreateBuiltinArraySubscriptExpr(From, Loc,
+                                                         IterationVarRefRVal,
+                                                         Loc));
+  To = AssertSuccess(S.CreateBuiltinArraySubscriptExpr(To, Loc,
+                                                       IterationVarRefRVal,
+                                                       Loc));
+  if (!Copying) // Cast to rvalue
+    From = CastForMoving(S, From);
+
+  // Build the copy/move for an individual element of the array.
+  StmtResult Copy = BuildSingleCopyAssign(S, Loc, ArrayTy->getElementType(),
+                                          To, From, CopyingBaseSubobject,
+                                          Copying, Depth + 1);
+  if (Copy.isInvalid())
+    return StmtError();
+  
+  // Construct the loop that copies all elements of this array.
+  return S.ActOnForStmt(Loc, Loc, InitStmt, 
+                        S.MakeFullExpr(Comparison),
+                        0, S.MakeFullExpr(Increment),
+                        Loc, Copy.take());
+}
+
+std::pair<Sema::ImplicitExceptionSpecification, bool>
+Sema::ComputeDefaultedCopyAssignmentExceptionSpecAndConst(
+                                                   CXXRecordDecl *ClassDecl) {
+  if (ClassDecl->isInvalidDecl())
+    return std::make_pair(ImplicitExceptionSpecification(*this), false);
+
+  // C++ [class.copy]p10:
+  //   If the class definition does not explicitly declare a copy
+  //   assignment operator, one is declared implicitly.
+  //   The implicitly-defined copy assignment operator for a class X
+  //   will have the form
+  //
+  //       X& X::operator=(const X&)
+  //
+  //   if
+  bool HasConstCopyAssignment = true;
+  
+  //       -- each direct base class B of X has a copy assignment operator
+  //          whose parameter is of type const B&, const volatile B& or B,
+  //          and
+  for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin(),
+                                       BaseEnd = ClassDecl->bases_end();
+       HasConstCopyAssignment && Base != BaseEnd; ++Base) {
+    // We'll handle this below
+    if (LangOpts.CPlusPlus0x && Base->isVirtual())
+      continue;
+
+    assert(!Base->getType()->isDependentType() &&
+           "Cannot generate implicit members for class with dependent bases.");
+    CXXRecordDecl *BaseClassDecl = Base->getType()->getAsCXXRecordDecl();
+    HasConstCopyAssignment &=
+      (bool)LookupCopyingAssignment(BaseClassDecl, Qualifiers::Const,
+                                    false, 0);
+  }
+
+  // In C++11, the above citation has "or virtual" added
+  if (LangOpts.CPlusPlus0x) {
+    for (CXXRecordDecl::base_class_iterator Base = ClassDecl->vbases_begin(),
+                                         BaseEnd = ClassDecl->vbases_end();
+         HasConstCopyAssignment && Base != BaseEnd; ++Base) {
+      assert(!Base->getType()->isDependentType() &&
+             "Cannot generate implicit members for class with dependent bases.");
+      CXXRecordDecl *BaseClassDecl = Base->getType()->getAsCXXRecordDecl();
+      HasConstCopyAssignment &=
+        (bool)LookupCopyingAssignment(BaseClassDecl, Qualifiers::Const,
+                                      false, 0);
+    }
+  }
+  
+  //       -- for all the nonstatic data members of X that are of a class
+  //          type M (or array thereof), each such class type has a copy
+  //          assignment operator whose parameter is of type const M&,
+  //          const volatile M& or M.
+  for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(),
+                                  FieldEnd = ClassDecl->field_end();
+       HasConstCopyAssignment && Field != FieldEnd;
+       ++Field) {
+    QualType FieldType = Context.getBaseElementType((*Field)->getType());
+    if (CXXRecordDecl *FieldClassDecl = FieldType->getAsCXXRecordDecl()) {
+      HasConstCopyAssignment &=
+        (bool)LookupCopyingAssignment(FieldClassDecl, Qualifiers::Const,
+                                      false, 0);
+    }
+  }
+  
+  //   Otherwise, the implicitly declared copy assignment operator will
+  //   have the form
+  //
+  //       X& X::operator=(X&)
+  
+  // C++ [except.spec]p14:
+  //   An implicitly declared special member function (Clause 12) shall have an 
+  //   exception-specification. [...]
+
+  // It is unspecified whether or not an implicit copy assignment operator
+  // attempts to deduplicate calls to assignment operators of virtual bases are
+  // made. As such, this exception specification is effectively unspecified.
+  // Based on a similar decision made for constness in C++0x, we're erring on
+  // the side of assuming such calls to be made regardless of whether they
+  // actually happen.
+  ImplicitExceptionSpecification ExceptSpec(*this);
+  unsigned ArgQuals = HasConstCopyAssignment ? Qualifiers::Const : 0;
+  for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin(),
+                                       BaseEnd = ClassDecl->bases_end();
+       Base != BaseEnd; ++Base) {
+    if (Base->isVirtual())
+      continue;
+
+    CXXRecordDecl *BaseClassDecl
+      = cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());
+    if (CXXMethodDecl *CopyAssign = LookupCopyingAssignment(BaseClassDecl,
+                                                            ArgQuals, false, 0))
+      ExceptSpec.CalledDecl(Base->getLocStart(), CopyAssign);
+  }
+
+  for (CXXRecordDecl::base_class_iterator Base = ClassDecl->vbases_begin(),
+                                       BaseEnd = ClassDecl->vbases_end();
+       Base != BaseEnd; ++Base) {
+    CXXRecordDecl *BaseClassDecl
+      = cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());
+    if (CXXMethodDecl *CopyAssign = LookupCopyingAssignment(BaseClassDecl,
+                                                            ArgQuals, false, 0))
+      ExceptSpec.CalledDecl(Base->getLocStart(), CopyAssign);
+  }
+
+  for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(),
+                                  FieldEnd = ClassDecl->field_end();
+       Field != FieldEnd;
+       ++Field) {
+    QualType FieldType = Context.getBaseElementType((*Field)->getType());
+    if (CXXRecordDecl *FieldClassDecl = FieldType->getAsCXXRecordDecl()) {
+      if (CXXMethodDecl *CopyAssign =
+          LookupCopyingAssignment(FieldClassDecl, ArgQuals, false, 0))
+        ExceptSpec.CalledDecl(Field->getLocation(), CopyAssign);
+    }
+  }
+
+  return std::make_pair(ExceptSpec, HasConstCopyAssignment);
+}
+
+CXXMethodDecl *Sema::DeclareImplicitCopyAssignment(CXXRecordDecl *ClassDecl) {
+  // Note: The following rules are largely analoguous to the copy
+  // constructor rules. Note that virtual bases are not taken into account
+  // for determining the argument type of the operator. Note also that
+  // operators taking an object instead of a reference are allowed.
+
+  ImplicitExceptionSpecification Spec(*this);
+  bool Const;
+  llvm::tie(Spec, Const) =
+    ComputeDefaultedCopyAssignmentExceptionSpecAndConst(ClassDecl);
+
+  QualType ArgType = Context.getTypeDeclType(ClassDecl);
+  QualType RetType = Context.getLValueReferenceType(ArgType);
+  if (Const)
+    ArgType = ArgType.withConst();
+  ArgType = Context.getLValueReferenceType(ArgType);
+
+  //   An implicitly-declared copy assignment operator is an inline public
+  //   member of its class.
+  FunctionProtoType::ExtProtoInfo EPI = Spec.getEPI();
+  DeclarationName Name = Context.DeclarationNames.getCXXOperatorName(OO_Equal);
+  SourceLocation ClassLoc = ClassDecl->getLocation();
+  DeclarationNameInfo NameInfo(Name, ClassLoc);
+  CXXMethodDecl *CopyAssignment
+    = CXXMethodDecl::Create(Context, ClassDecl, ClassLoc, NameInfo,
+                            Context.getFunctionType(RetType, &ArgType, 1, EPI),
+                            /*TInfo=*/0, /*isStatic=*/false,
+                            /*StorageClassAsWritten=*/SC_None,
+                            /*isInline=*/true, /*isConstexpr=*/false,
+                            SourceLocation());
+  CopyAssignment->setAccess(AS_public);
+  CopyAssignment->setDefaulted();
+  CopyAssignment->setImplicit();
+  CopyAssignment->setTrivial(ClassDecl->hasTrivialCopyAssignment());
+  
+  // Add the parameter to the operator.
+  ParmVarDecl *FromParam = ParmVarDecl::Create(Context, CopyAssignment,
+                                               ClassLoc, ClassLoc, /*Id=*/0,
+                                               ArgType, /*TInfo=*/0,
+                                               SC_None,
+                                               SC_None, 0);
+  CopyAssignment->setParams(FromParam);
+  
+  // Note that we have added this copy-assignment operator.
+  ++ASTContext::NumImplicitCopyAssignmentOperatorsDeclared;
+
+  if (Scope *S = getScopeForContext(ClassDecl))
+    PushOnScopeChains(CopyAssignment, S, false);
+  ClassDecl->addDecl(CopyAssignment);
+  
+  // C++0x [class.copy]p19:
+  //   ....  If the class definition does not explicitly declare a copy
+  //   assignment operator, there is no user-declared move constructor, and
+  //   there is no user-declared move assignment operator, a copy assignment
+  //   operator is implicitly declared as defaulted.
+  if (ShouldDeleteSpecialMember(CopyAssignment, CXXCopyAssignment))
+    CopyAssignment->setDeletedAsWritten();
+
+  AddOverriddenMethods(ClassDecl, CopyAssignment);
+  return CopyAssignment;
+}
+
+void Sema::DefineImplicitCopyAssignment(SourceLocation CurrentLocation,
+                                        CXXMethodDecl *CopyAssignOperator) {
+  assert((CopyAssignOperator->isDefaulted() && 
+          CopyAssignOperator->isOverloadedOperator() &&
+          CopyAssignOperator->getOverloadedOperator() == OO_Equal &&
+          !CopyAssignOperator->doesThisDeclarationHaveABody() &&
+          !CopyAssignOperator->isDeleted()) &&
+         "DefineImplicitCopyAssignment called for wrong function");
+
+  CXXRecordDecl *ClassDecl = CopyAssignOperator->getParent();
+
+  if (ClassDecl->isInvalidDecl() || CopyAssignOperator->isInvalidDecl()) {
+    CopyAssignOperator->setInvalidDecl();
+    return;
+  }
+  
+  CopyAssignOperator->setUsed();
+
+  ImplicitlyDefinedFunctionScope Scope(*this, CopyAssignOperator);
+  DiagnosticErrorTrap Trap(Diags);
+
+  // C++0x [class.copy]p30:
+  //   The implicitly-defined or explicitly-defaulted copy assignment operator
+  //   for a non-union class X performs memberwise copy assignment of its 
+  //   subobjects. The direct base classes of X are assigned first, in the 
+  //   order of their declaration in the base-specifier-list, and then the 
+  //   immediate non-static data members of X are assigned, in the order in 
+  //   which they were declared in the class definition.
+  
+  // The statements that form the synthesized function body.
+  ASTOwningVector<Stmt*> Statements(*this);
+  
+  // The parameter for the "other" object, which we are copying from.
+  ParmVarDecl *Other = CopyAssignOperator->getParamDecl(0);
+  Qualifiers OtherQuals = Other->getType().getQualifiers();
+  QualType OtherRefType = Other->getType();
+  if (const LValueReferenceType *OtherRef
+                                = OtherRefType->getAs<LValueReferenceType>()) {
+    OtherRefType = OtherRef->getPointeeType();
+    OtherQuals = OtherRefType.getQualifiers();
+  }
+  
+  // Our location for everything implicitly-generated.
+  SourceLocation Loc = CopyAssignOperator->getLocation();
+  
+  // Construct a reference to the "other" object. We'll be using this 
+  // throughout the generated ASTs.
+  Expr *OtherRef = BuildDeclRefExpr(Other, OtherRefType, VK_LValue, Loc).take();
+  assert(OtherRef && "Reference to parameter cannot fail!");
+  
+  // Construct the "this" pointer. We'll be using this throughout the generated
+  // ASTs.
+  Expr *This = ActOnCXXThis(Loc).takeAs<Expr>();
+  assert(This && "Reference to this cannot fail!");
+  
+  // Assign base classes.
+  bool Invalid = false;
+  for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin(),
+       E = ClassDecl->bases_end(); Base != E; ++Base) {
+    // Form the assignment:
+    //   static_cast<Base*>(this)->Base::operator=(static_cast<Base&>(other));
+    QualType BaseType = Base->getType().getUnqualifiedType();
+    if (!BaseType->isRecordType()) {
+      Invalid = true;
+      continue;
+    }
+
+    CXXCastPath BasePath;
+    BasePath.push_back(Base);
+
+    // Construct the "from" expression, which is an implicit cast to the
+    // appropriately-qualified base type.
+    Expr *From = OtherRef;
+    From = ImpCastExprToType(From, Context.getQualifiedType(BaseType, OtherQuals),
+                             CK_UncheckedDerivedToBase,
+                             VK_LValue, &BasePath).take();
+
+    // Dereference "this".
+    ExprResult To = CreateBuiltinUnaryOp(Loc, UO_Deref, This);
+    
+    // Implicitly cast "this" to the appropriately-qualified base type.
+    To = ImpCastExprToType(To.take(), 
+                           Context.getCVRQualifiedType(BaseType,
+                                     CopyAssignOperator->getTypeQualifiers()),
+                           CK_UncheckedDerivedToBase, 
+                           VK_LValue, &BasePath);
+
+    // Build the copy.
+    StmtResult Copy = BuildSingleCopyAssign(*this, Loc, BaseType,
+                                            To.get(), From,
+                                            /*CopyingBaseSubobject=*/true,
+                                            /*Copying=*/true);
+    if (Copy.isInvalid()) {
+      Diag(CurrentLocation, diag::note_member_synthesized_at) 
+        << CXXCopyAssignment << Context.getTagDeclType(ClassDecl);
+      CopyAssignOperator->setInvalidDecl();
+      return;
+    }
+    
+    // Success! Record the copy.
+    Statements.push_back(Copy.takeAs<Expr>());
+  }
+  
+  // \brief Reference to the __builtin_memcpy function.
+  Expr *BuiltinMemCpyRef = 0;
+  // \brief Reference to the __builtin_objc_memmove_collectable function.
+  Expr *CollectableMemCpyRef = 0;
+  
+  // Assign non-static members.
+  for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(),
+                                  FieldEnd = ClassDecl->field_end(); 
+       Field != FieldEnd; ++Field) {
+    if (Field->isUnnamedBitfield())
+      continue;
+    
+    // Check for members of reference type; we can't copy those.
+    if (Field->getType()->isReferenceType()) {
+      Diag(ClassDecl->getLocation(), diag::err_uninitialized_member_for_assign)
+        << Context.getTagDeclType(ClassDecl) << 0 << Field->getDeclName();
+      Diag(Field->getLocation(), diag::note_declared_at);
+      Diag(CurrentLocation, diag::note_member_synthesized_at) 
+        << CXXCopyAssignment << Context.getTagDeclType(ClassDecl);
+      Invalid = true;
+      continue;
+    }
+    
+    // Check for members of const-qualified, non-class type.
+    QualType BaseType = Context.getBaseElementType(Field->getType());
+    if (!BaseType->getAs<RecordType>() && BaseType.isConstQualified()) {
+      Diag(ClassDecl->getLocation(), diag::err_uninitialized_member_for_assign)
+        << Context.getTagDeclType(ClassDecl) << 1 << Field->getDeclName();
+      Diag(Field->getLocation(), diag::note_declared_at);
+      Diag(CurrentLocation, diag::note_member_synthesized_at) 
+        << CXXCopyAssignment << Context.getTagDeclType(ClassDecl);
+      Invalid = true;      
+      continue;
+    }
+
+    // Suppress assigning zero-width bitfields.
+    if (Field->isBitField() && Field->getBitWidthValue(Context) == 0)
+      continue;
+    
+    QualType FieldType = Field->getType().getNonReferenceType();
+    if (FieldType->isIncompleteArrayType()) {
+      assert(ClassDecl->hasFlexibleArrayMember() && 
+             "Incomplete array type is not valid");
+      continue;
+    }
+    
+    // Build references to the field in the object we're copying from and to.
+    CXXScopeSpec SS; // Intentionally empty
+    LookupResult MemberLookup(*this, Field->getDeclName(), Loc,
+                              LookupMemberName);
+    MemberLookup.addDecl(*Field);
+    MemberLookup.resolveKind();
+    ExprResult From = BuildMemberReferenceExpr(OtherRef, OtherRefType,
+                                               Loc, /*IsArrow=*/false,
+                                               SS, SourceLocation(), 0,
+                                               MemberLookup, 0);
+    ExprResult To = BuildMemberReferenceExpr(This, This->getType(),
+                                             Loc, /*IsArrow=*/true,
+                                             SS, SourceLocation(), 0,
+                                             MemberLookup, 0);
+    assert(!From.isInvalid() && "Implicit field reference cannot fail");
+    assert(!To.isInvalid() && "Implicit field reference cannot fail");
+    
+    // If the field should be copied with __builtin_memcpy rather than via
+    // explicit assignments, do so. This optimization only applies for arrays 
+    // of scalars and arrays of class type with trivial copy-assignment 
+    // operators.
+    if (FieldType->isArrayType() && !FieldType.isVolatileQualified()
+        && BaseType.hasTrivialAssignment(Context, /*Copying=*/true)) {
+      // Compute the size of the memory buffer to be copied.
+      QualType SizeType = Context.getSizeType();
+      llvm::APInt Size(Context.getTypeSize(SizeType), 
+                       Context.getTypeSizeInChars(BaseType).getQuantity());
+      for (const ConstantArrayType *Array
+              = Context.getAsConstantArrayType(FieldType);
+           Array; 
+           Array = Context.getAsConstantArrayType(Array->getElementType())) {
+        llvm::APInt ArraySize
+          = Array->getSize().zextOrTrunc(Size.getBitWidth());
+        Size *= ArraySize;
+      }
+          
+      // Take the address of the field references for "from" and "to".
+      From = CreateBuiltinUnaryOp(Loc, UO_AddrOf, From.get());
+      To = CreateBuiltinUnaryOp(Loc, UO_AddrOf, To.get());
+          
+      bool NeedsCollectableMemCpy = 
+          (BaseType->isRecordType() && 
+           BaseType->getAs<RecordType>()->getDecl()->hasObjectMember());
+          
+      if (NeedsCollectableMemCpy) {
+        if (!CollectableMemCpyRef) {
+          // Create a reference to the __builtin_objc_memmove_collectable function.
+          LookupResult R(*this, 
+                         &Context.Idents.get("__builtin_objc_memmove_collectable"), 
+                         Loc, LookupOrdinaryName);
+          LookupName(R, TUScope, true);
+        
+          FunctionDecl *CollectableMemCpy = R.getAsSingle<FunctionDecl>();
+          if (!CollectableMemCpy) {
+            // Something went horribly wrong earlier, and we will have 
+            // complained about it.
+            Invalid = true;
+            continue;
+          }
+        
+          CollectableMemCpyRef = BuildDeclRefExpr(CollectableMemCpy, 
+                                                  CollectableMemCpy->getType(),
+                                                  VK_LValue, Loc, 0).take();
+          assert(CollectableMemCpyRef && "Builtin reference cannot fail");
+        }
+      }
+      // Create a reference to the __builtin_memcpy builtin function.
+      else if (!BuiltinMemCpyRef) {
+        LookupResult R(*this, &Context.Idents.get("__builtin_memcpy"), Loc,
+                       LookupOrdinaryName);
+        LookupName(R, TUScope, true);
+        
+        FunctionDecl *BuiltinMemCpy = R.getAsSingle<FunctionDecl>();
+        if (!BuiltinMemCpy) {
+          // Something went horribly wrong earlier, and we will have complained
+          // about it.
+          Invalid = true;
+          continue;
+        }
+
+        BuiltinMemCpyRef = BuildDeclRefExpr(BuiltinMemCpy, 
+                                            BuiltinMemCpy->getType(),
+                                            VK_LValue, Loc, 0).take();
+        assert(BuiltinMemCpyRef && "Builtin reference cannot fail");
+      }
+          
+      ASTOwningVector<Expr*> CallArgs(*this);
+      CallArgs.push_back(To.takeAs<Expr>());
+      CallArgs.push_back(From.takeAs<Expr>());
+      CallArgs.push_back(IntegerLiteral::Create(Context, Size, SizeType, Loc));
+      ExprResult Call = ExprError();
+      if (NeedsCollectableMemCpy)
+        Call = ActOnCallExpr(/*Scope=*/0,
+                             CollectableMemCpyRef,
+                             Loc, move_arg(CallArgs), 
+                             Loc);
+      else
+        Call = ActOnCallExpr(/*Scope=*/0,
+                             BuiltinMemCpyRef,
+                             Loc, move_arg(CallArgs), 
+                             Loc);
+          
+      assert(!Call.isInvalid() && "Call to __builtin_memcpy cannot fail!");
+      Statements.push_back(Call.takeAs<Expr>());
+      continue;
+    }
+    
+    // Build the copy of this field.
+    StmtResult Copy = BuildSingleCopyAssign(*this, Loc, FieldType, 
+                                            To.get(), From.get(),
+                                            /*CopyingBaseSubobject=*/false,
+                                            /*Copying=*/true);
+    if (Copy.isInvalid()) {
+      Diag(CurrentLocation, diag::note_member_synthesized_at) 
+        << CXXCopyAssignment << Context.getTagDeclType(ClassDecl);
+      CopyAssignOperator->setInvalidDecl();
+      return;
+    }
+    
+    // Success! Record the copy.
+    Statements.push_back(Copy.takeAs<Stmt>());
+  }
+
+  if (!Invalid) {
+    // Add a "return *this;"
+    ExprResult ThisObj = CreateBuiltinUnaryOp(Loc, UO_Deref, This);
+    
+    StmtResult Return = ActOnReturnStmt(Loc, ThisObj.get());
+    if (Return.isInvalid())
+      Invalid = true;
+    else {
+      Statements.push_back(Return.takeAs<Stmt>());
+
+      if (Trap.hasErrorOccurred()) {
+        Diag(CurrentLocation, diag::note_member_synthesized_at) 
+          << CXXCopyAssignment << Context.getTagDeclType(ClassDecl);
+        Invalid = true;
+      }
+    }
+  }
+
+  if (Invalid) {
+    CopyAssignOperator->setInvalidDecl();
+    return;
+  }
+
+  StmtResult Body;
+  {
+    CompoundScopeRAII CompoundScope(*this);
+    Body = ActOnCompoundStmt(Loc, Loc, move_arg(Statements),
+                             /*isStmtExpr=*/false);
+    assert(!Body.isInvalid() && "Compound statement creation cannot fail");
+  }
+  CopyAssignOperator->setBody(Body.takeAs<Stmt>());
+
+  if (ASTMutationListener *L = getASTMutationListener()) {
+    L->CompletedImplicitDefinition(CopyAssignOperator);
+  }
+}
+
+Sema::ImplicitExceptionSpecification
+Sema::ComputeDefaultedMoveAssignmentExceptionSpec(CXXRecordDecl *ClassDecl) {
+  ImplicitExceptionSpecification ExceptSpec(*this);
+
+  if (ClassDecl->isInvalidDecl())
+    return ExceptSpec;
+
+  // C++0x [except.spec]p14:
+  //   An implicitly declared special member function (Clause 12) shall have an 
+  //   exception-specification. [...]
+
+  // It is unspecified whether or not an implicit move assignment operator
+  // attempts to deduplicate calls to assignment operators of virtual bases are
+  // made. As such, this exception specification is effectively unspecified.
+  // Based on a similar decision made for constness in C++0x, we're erring on
+  // the side of assuming such calls to be made regardless of whether they
+  // actually happen.
+  // Note that a move constructor is not implicitly declared when there are
+  // virtual bases, but it can still be user-declared and explicitly defaulted.
+  for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin(),
+                                       BaseEnd = ClassDecl->bases_end();
+       Base != BaseEnd; ++Base) {
+    if (Base->isVirtual())
+      continue;
+
+    CXXRecordDecl *BaseClassDecl
+      = cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());
+    if (CXXMethodDecl *MoveAssign = LookupMovingAssignment(BaseClassDecl,
+                                                           false, 0))
+      ExceptSpec.CalledDecl(Base->getLocStart(), MoveAssign);
+  }
+
+  for (CXXRecordDecl::base_class_iterator Base = ClassDecl->vbases_begin(),
+                                       BaseEnd = ClassDecl->vbases_end();
+       Base != BaseEnd; ++Base) {
+    CXXRecordDecl *BaseClassDecl
+      = cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());
+    if (CXXMethodDecl *MoveAssign = LookupMovingAssignment(BaseClassDecl,
+                                                           false, 0))
+      ExceptSpec.CalledDecl(Base->getLocStart(), MoveAssign);
+  }
+
+  for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(),
+                                  FieldEnd = ClassDecl->field_end();
+       Field != FieldEnd;
+       ++Field) {
+    QualType FieldType = Context.getBaseElementType((*Field)->getType());
+    if (CXXRecordDecl *FieldClassDecl = FieldType->getAsCXXRecordDecl()) {
+      if (CXXMethodDecl *MoveAssign = LookupMovingAssignment(FieldClassDecl,
+                                                             false, 0))
+        ExceptSpec.CalledDecl(Field->getLocation(), MoveAssign);
+    }
+  }
+
+  return ExceptSpec;
+}
+
+/// Determine whether the class type has any direct or indirect virtual base
+/// classes which have a non-trivial move assignment operator.
+static bool
+hasVirtualBaseWithNonTrivialMoveAssignment(Sema &S, CXXRecordDecl *ClassDecl) {
+  for (CXXRecordDecl::base_class_iterator Base = ClassDecl->vbases_begin(),
+                                          BaseEnd = ClassDecl->vbases_end();
+       Base != BaseEnd; ++Base) {
+    CXXRecordDecl *BaseClass =
+        cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());
+
+    // Try to declare the move assignment. If it would be deleted, then the
+    // class does not have a non-trivial move assignment.
+    if (BaseClass->needsImplicitMoveAssignment())
+      S.DeclareImplicitMoveAssignment(BaseClass);
+
+    // If the class has both a trivial move assignment and a non-trivial move
+    // assignment, hasTrivialMoveAssignment() is false.
+    if (BaseClass->hasDeclaredMoveAssignment() &&
+        !BaseClass->hasTrivialMoveAssignment())
+      return true;
+  }
+
+  return false;
+}
+
+/// Determine whether the given type either has a move constructor or is
+/// trivially copyable.
+static bool
+hasMoveOrIsTriviallyCopyable(Sema &S, QualType Type, bool IsConstructor) {
+  Type = S.Context.getBaseElementType(Type);
+
+  // FIXME: Technically, non-trivially-copyable non-class types, such as
+  // reference types, are supposed to return false here, but that appears
+  // to be a standard defect.
+  CXXRecordDecl *ClassDecl = Type->getAsCXXRecordDecl();
+  if (!ClassDecl)
+    return true;
+
+  if (Type.isTriviallyCopyableType(S.Context))
+    return true;
+
+  if (IsConstructor) {
+    if (ClassDecl->needsImplicitMoveConstructor())
+      S.DeclareImplicitMoveConstructor(ClassDecl);
+    return ClassDecl->hasDeclaredMoveConstructor();
+  }
+
+  if (ClassDecl->needsImplicitMoveAssignment())
+    S.DeclareImplicitMoveAssignment(ClassDecl);
+  return ClassDecl->hasDeclaredMoveAssignment();
+}
+
+/// Determine whether all non-static data members and direct or virtual bases
+/// of class \p ClassDecl have either a move operation, or are trivially
+/// copyable.
+static bool subobjectsHaveMoveOrTrivialCopy(Sema &S, CXXRecordDecl *ClassDecl,
+                                            bool IsConstructor) {
+  for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin(),
+                                          BaseEnd = ClassDecl->bases_end();
+       Base != BaseEnd; ++Base) {
+    if (Base->isVirtual())
+      continue;
+
+    if (!hasMoveOrIsTriviallyCopyable(S, Base->getType(), IsConstructor))
+      return false;
+  }
+
+  for (CXXRecordDecl::base_class_iterator Base = ClassDecl->vbases_begin(),
+                                          BaseEnd = ClassDecl->vbases_end();
+       Base != BaseEnd; ++Base) {
+    if (!hasMoveOrIsTriviallyCopyable(S, Base->getType(), IsConstructor))
+      return false;
+  }
+
+  for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(),
+                                     FieldEnd = ClassDecl->field_end();
+       Field != FieldEnd; ++Field) {
+    if (!hasMoveOrIsTriviallyCopyable(S, (*Field)->getType(), IsConstructor))
+      return false;
+  }
+
+  return true;
+}
+
+CXXMethodDecl *Sema::DeclareImplicitMoveAssignment(CXXRecordDecl *ClassDecl) {
+  // C++11 [class.copy]p20:
+  //   If the definition of a class X does not explicitly declare a move
+  //   assignment operator, one will be implicitly declared as defaulted
+  //   if and only if:
+  //
+  //   - [first 4 bullets]
+  assert(ClassDecl->needsImplicitMoveAssignment());
+
+  // [Checked after we build the declaration]
+  //   - the move assignment operator would not be implicitly defined as
+  //     deleted,
+
+  // [DR1402]:
+  //   - X has no direct or indirect virtual base class with a non-trivial
+  //     move assignment operator, and
+  //   - each of X's non-static data members and direct or virtual base classes
+  //     has a type that either has a move assignment operator or is trivially
+  //     copyable.
+  if (hasVirtualBaseWithNonTrivialMoveAssignment(*this, ClassDecl) ||
+      !subobjectsHaveMoveOrTrivialCopy(*this, ClassDecl,/*Constructor*/false)) {
+    ClassDecl->setFailedImplicitMoveAssignment();
+    return 0;
+  }
+
+  // Note: The following rules are largely analoguous to the move
+  // constructor rules.
+
+  ImplicitExceptionSpecification Spec(
+      ComputeDefaultedMoveAssignmentExceptionSpec(ClassDecl));
+
+  QualType ArgType = Context.getTypeDeclType(ClassDecl);
+  QualType RetType = Context.getLValueReferenceType(ArgType);
+  ArgType = Context.getRValueReferenceType(ArgType);
+
+  //   An implicitly-declared move assignment operator is an inline public
+  //   member of its class.
+  FunctionProtoType::ExtProtoInfo EPI = Spec.getEPI();
+  DeclarationName Name = Context.DeclarationNames.getCXXOperatorName(OO_Equal);
+  SourceLocation ClassLoc = ClassDecl->getLocation();
+  DeclarationNameInfo NameInfo(Name, ClassLoc);
+  CXXMethodDecl *MoveAssignment
+    = CXXMethodDecl::Create(Context, ClassDecl, ClassLoc, NameInfo,
+                            Context.getFunctionType(RetType, &ArgType, 1, EPI),
+                            /*TInfo=*/0, /*isStatic=*/false,
+                            /*StorageClassAsWritten=*/SC_None,
+                            /*isInline=*/true,
+                            /*isConstexpr=*/false,
+                            SourceLocation());
+  MoveAssignment->setAccess(AS_public);
+  MoveAssignment->setDefaulted();
+  MoveAssignment->setImplicit();
+  MoveAssignment->setTrivial(ClassDecl->hasTrivialMoveAssignment());
+
+  // Add the parameter to the operator.
+  ParmVarDecl *FromParam = ParmVarDecl::Create(Context, MoveAssignment,
+                                               ClassLoc, ClassLoc, /*Id=*/0,
+                                               ArgType, /*TInfo=*/0,
+                                               SC_None,
+                                               SC_None, 0);
+  MoveAssignment->setParams(FromParam);
+
+  // Note that we have added this copy-assignment operator.
+  ++ASTContext::NumImplicitMoveAssignmentOperatorsDeclared;
+
+  // C++0x [class.copy]p9:
+  //   If the definition of a class X does not explicitly declare a move
+  //   assignment operator, one will be implicitly declared as defaulted if and
+  //   only if:
+  //   [...]
+  //   - the move assignment operator would not be implicitly defined as
+  //     deleted.
+  if (ShouldDeleteSpecialMember(MoveAssignment, CXXMoveAssignment)) {
+    // Cache this result so that we don't try to generate this over and over
+    // on every lookup, leaking memory and wasting time.
+    ClassDecl->setFailedImplicitMoveAssignment();
+    return 0;
+  }
+
+  if (Scope *S = getScopeForContext(ClassDecl))
+    PushOnScopeChains(MoveAssignment, S, false);
+  ClassDecl->addDecl(MoveAssignment);
+
+  AddOverriddenMethods(ClassDecl, MoveAssignment);
+  return MoveAssignment;
+}
+
+void Sema::DefineImplicitMoveAssignment(SourceLocation CurrentLocation,
+                                        CXXMethodDecl *MoveAssignOperator) {
+  assert((MoveAssignOperator->isDefaulted() && 
+          MoveAssignOperator->isOverloadedOperator() &&
+          MoveAssignOperator->getOverloadedOperator() == OO_Equal &&
+          !MoveAssignOperator->doesThisDeclarationHaveABody() &&
+          !MoveAssignOperator->isDeleted()) &&
+         "DefineImplicitMoveAssignment called for wrong function");
+
+  CXXRecordDecl *ClassDecl = MoveAssignOperator->getParent();
+
+  if (ClassDecl->isInvalidDecl() || MoveAssignOperator->isInvalidDecl()) {
+    MoveAssignOperator->setInvalidDecl();
+    return;
+  }
+  
+  MoveAssignOperator->setUsed();
+
+  ImplicitlyDefinedFunctionScope Scope(*this, MoveAssignOperator);
+  DiagnosticErrorTrap Trap(Diags);
+
+  // C++0x [class.copy]p28:
+  //   The implicitly-defined or move assignment operator for a non-union class
+  //   X performs memberwise move assignment of its subobjects. The direct base
+  //   classes of X are assigned first, in the order of their declaration in the
+  //   base-specifier-list, and then the immediate non-static data members of X
+  //   are assigned, in the order in which they were declared in the class
+  //   definition.
+
+  // The statements that form the synthesized function body.
+  ASTOwningVector<Stmt*> Statements(*this);
+
+  // The parameter for the "other" object, which we are move from.
+  ParmVarDecl *Other = MoveAssignOperator->getParamDecl(0);
+  QualType OtherRefType = Other->getType()->
+      getAs<RValueReferenceType>()->getPointeeType();
+  assert(OtherRefType.getQualifiers() == 0 &&
+         "Bad argument type of defaulted move assignment");
+
+  // Our location for everything implicitly-generated.
+  SourceLocation Loc = MoveAssignOperator->getLocation();
+
+  // Construct a reference to the "other" object. We'll be using this 
+  // throughout the generated ASTs.
+  Expr *OtherRef = BuildDeclRefExpr(Other, OtherRefType, VK_LValue, Loc).take();
+  assert(OtherRef && "Reference to parameter cannot fail!");
+  // Cast to rvalue.
+  OtherRef = CastForMoving(*this, OtherRef);
+
+  // Construct the "this" pointer. We'll be using this throughout the generated
+  // ASTs.
+  Expr *This = ActOnCXXThis(Loc).takeAs<Expr>();
+  assert(This && "Reference to this cannot fail!");
+
+  // Assign base classes.
+  bool Invalid = false;
+  for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin(),
+       E = ClassDecl->bases_end(); Base != E; ++Base) {
+    // Form the assignment:
+    //   static_cast<Base*>(this)->Base::operator=(static_cast<Base&&>(other));
+    QualType BaseType = Base->getType().getUnqualifiedType();
+    if (!BaseType->isRecordType()) {
+      Invalid = true;
+      continue;
+    }
+
+    CXXCastPath BasePath;
+    BasePath.push_back(Base);
+
+    // Construct the "from" expression, which is an implicit cast to the
+    // appropriately-qualified base type.
+    Expr *From = OtherRef;
+    From = ImpCastExprToType(From, BaseType, CK_UncheckedDerivedToBase,
+                             VK_XValue, &BasePath).take();
+
+    // Dereference "this".
+    ExprResult To = CreateBuiltinUnaryOp(Loc, UO_Deref, This);
+
+    // Implicitly cast "this" to the appropriately-qualified base type.
+    To = ImpCastExprToType(To.take(), 
+                           Context.getCVRQualifiedType(BaseType,
+                                     MoveAssignOperator->getTypeQualifiers()),
+                           CK_UncheckedDerivedToBase, 
+                           VK_LValue, &BasePath);
+
+    // Build the move.
+    StmtResult Move = BuildSingleCopyAssign(*this, Loc, BaseType,
+                                            To.get(), From,
+                                            /*CopyingBaseSubobject=*/true,
+                                            /*Copying=*/false);
+    if (Move.isInvalid()) {
+      Diag(CurrentLocation, diag::note_member_synthesized_at) 
+        << CXXMoveAssignment << Context.getTagDeclType(ClassDecl);
+      MoveAssignOperator->setInvalidDecl();
+      return;
+    }
+
+    // Success! Record the move.
+    Statements.push_back(Move.takeAs<Expr>());
+  }
+
+  // \brief Reference to the __builtin_memcpy function.
+  Expr *BuiltinMemCpyRef = 0;
+  // \brief Reference to the __builtin_objc_memmove_collectable function.
+  Expr *CollectableMemCpyRef = 0;
+
+  // Assign non-static members.
+  for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(),
+                                  FieldEnd = ClassDecl->field_end(); 
+       Field != FieldEnd; ++Field) {
+    if (Field->isUnnamedBitfield())
+      continue;
+
+    // Check for members of reference type; we can't move those.
+    if (Field->getType()->isReferenceType()) {
+      Diag(ClassDecl->getLocation(), diag::err_uninitialized_member_for_assign)
+        << Context.getTagDeclType(ClassDecl) << 0 << Field->getDeclName();
+      Diag(Field->getLocation(), diag::note_declared_at);
+      Diag(CurrentLocation, diag::note_member_synthesized_at) 
+        << CXXMoveAssignment << Context.getTagDeclType(ClassDecl);
+      Invalid = true;
+      continue;
+    }
+
+    // Check for members of const-qualified, non-class type.
+    QualType BaseType = Context.getBaseElementType(Field->getType());
+    if (!BaseType->getAs<RecordType>() && BaseType.isConstQualified()) {
+      Diag(ClassDecl->getLocation(), diag::err_uninitialized_member_for_assign)
+        << Context.getTagDeclType(ClassDecl) << 1 << Field->getDeclName();
+      Diag(Field->getLocation(), diag::note_declared_at);
+      Diag(CurrentLocation, diag::note_member_synthesized_at) 
+        << CXXMoveAssignment << Context.getTagDeclType(ClassDecl);
+      Invalid = true;      
+      continue;
+    }
+
+    // Suppress assigning zero-width bitfields.
+    if (Field->isBitField() && Field->getBitWidthValue(Context) == 0)
+      continue;
+    
+    QualType FieldType = Field->getType().getNonReferenceType();
+    if (FieldType->isIncompleteArrayType()) {
+      assert(ClassDecl->hasFlexibleArrayMember() && 
+             "Incomplete array type is not valid");
+      continue;
+    }
+    
+    // Build references to the field in the object we're copying from and to.
+    CXXScopeSpec SS; // Intentionally empty
+    LookupResult MemberLookup(*this, Field->getDeclName(), Loc,
+                              LookupMemberName);
+    MemberLookup.addDecl(*Field);
+    MemberLookup.resolveKind();
+    ExprResult From = BuildMemberReferenceExpr(OtherRef, OtherRefType,
+                                               Loc, /*IsArrow=*/false,
+                                               SS, SourceLocation(), 0,
+                                               MemberLookup, 0);
+    ExprResult To = BuildMemberReferenceExpr(This, This->getType(),
+                                             Loc, /*IsArrow=*/true,
+                                             SS, SourceLocation(), 0,
+                                             MemberLookup, 0);
+    assert(!From.isInvalid() && "Implicit field reference cannot fail");
+    assert(!To.isInvalid() && "Implicit field reference cannot fail");
+
+    assert(!From.get()->isLValue() && // could be xvalue or prvalue
+        "Member reference with rvalue base must be rvalue except for reference "
+        "members, which aren't allowed for move assignment.");
+
+    // If the field should be copied with __builtin_memcpy rather than via
+    // explicit assignments, do so. This optimization only applies for arrays 
+    // of scalars and arrays of class type with trivial move-assignment 
+    // operators.
+    if (FieldType->isArrayType() && !FieldType.isVolatileQualified()
+        && BaseType.hasTrivialAssignment(Context, /*Copying=*/false)) {
+      // Compute the size of the memory buffer to be copied.
+      QualType SizeType = Context.getSizeType();
+      llvm::APInt Size(Context.getTypeSize(SizeType), 
+                       Context.getTypeSizeInChars(BaseType).getQuantity());
+      for (const ConstantArrayType *Array
+              = Context.getAsConstantArrayType(FieldType);
+           Array; 
+           Array = Context.getAsConstantArrayType(Array->getElementType())) {
+        llvm::APInt ArraySize
+          = Array->getSize().zextOrTrunc(Size.getBitWidth());
+        Size *= ArraySize;
+      }
+
+      // Take the address of the field references for "from" and "to". We
+      // directly construct UnaryOperators here because semantic analysis
+      // does not permit us to take the address of an xvalue.
+      From = new (Context) UnaryOperator(From.get(), UO_AddrOf,
+                             Context.getPointerType(From.get()->getType()),
+                             VK_RValue, OK_Ordinary, Loc);
+      To = new (Context) UnaryOperator(To.get(), UO_AddrOf,
+                           Context.getPointerType(To.get()->getType()),
+                           VK_RValue, OK_Ordinary, Loc);
+          
+      bool NeedsCollectableMemCpy = 
+          (BaseType->isRecordType() && 
+           BaseType->getAs<RecordType>()->getDecl()->hasObjectMember());
+          
+      if (NeedsCollectableMemCpy) {
+        if (!CollectableMemCpyRef) {
+          // Create a reference to the __builtin_objc_memmove_collectable function.
+          LookupResult R(*this, 
+                         &Context.Idents.get("__builtin_objc_memmove_collectable"), 
+                         Loc, LookupOrdinaryName);
+          LookupName(R, TUScope, true);
+        
+          FunctionDecl *CollectableMemCpy = R.getAsSingle<FunctionDecl>();
+          if (!CollectableMemCpy) {
+            // Something went horribly wrong earlier, and we will have 
+            // complained about it.
+            Invalid = true;
+            continue;
+          }
+        
+          CollectableMemCpyRef = BuildDeclRefExpr(CollectableMemCpy, 
+                                                  CollectableMemCpy->getType(),
+                                                  VK_LValue, Loc, 0).take();
+          assert(CollectableMemCpyRef && "Builtin reference cannot fail");
+        }
+      }
+      // Create a reference to the __builtin_memcpy builtin function.
+      else if (!BuiltinMemCpyRef) {
+        LookupResult R(*this, &Context.Idents.get("__builtin_memcpy"), Loc,
+                       LookupOrdinaryName);
+        LookupName(R, TUScope, true);
+        
+        FunctionDecl *BuiltinMemCpy = R.getAsSingle<FunctionDecl>();
+        if (!BuiltinMemCpy) {
+          // Something went horribly wrong earlier, and we will have complained
+          // about it.
+          Invalid = true;
+          continue;
+        }
+
+        BuiltinMemCpyRef = BuildDeclRefExpr(BuiltinMemCpy, 
+                                            BuiltinMemCpy->getType(),
+                                            VK_LValue, Loc, 0).take();
+        assert(BuiltinMemCpyRef && "Builtin reference cannot fail");
+      }
+          
+      ASTOwningVector<Expr*> CallArgs(*this);
+      CallArgs.push_back(To.takeAs<Expr>());
+      CallArgs.push_back(From.takeAs<Expr>());
+      CallArgs.push_back(IntegerLiteral::Create(Context, Size, SizeType, Loc));
+      ExprResult Call = ExprError();
+      if (NeedsCollectableMemCpy)
+        Call = ActOnCallExpr(/*Scope=*/0,
+                             CollectableMemCpyRef,
+                             Loc, move_arg(CallArgs), 
+                             Loc);
+      else
+        Call = ActOnCallExpr(/*Scope=*/0,
+                             BuiltinMemCpyRef,
+                             Loc, move_arg(CallArgs), 
+                             Loc);
+          
+      assert(!Call.isInvalid() && "Call to __builtin_memcpy cannot fail!");
+      Statements.push_back(Call.takeAs<Expr>());
+      continue;
+    }
+    
+    // Build the move of this field.
+    StmtResult Move = BuildSingleCopyAssign(*this, Loc, FieldType, 
+                                            To.get(), From.get(),
+                                            /*CopyingBaseSubobject=*/false,
+                                            /*Copying=*/false);
+    if (Move.isInvalid()) {
+      Diag(CurrentLocation, diag::note_member_synthesized_at) 
+        << CXXMoveAssignment << Context.getTagDeclType(ClassDecl);
+      MoveAssignOperator->setInvalidDecl();
+      return;
+    }
+    
+    // Success! Record the copy.
+    Statements.push_back(Move.takeAs<Stmt>());
+  }
+
+  if (!Invalid) {
+    // Add a "return *this;"
+    ExprResult ThisObj = CreateBuiltinUnaryOp(Loc, UO_Deref, This);
+    
+    StmtResult Return = ActOnReturnStmt(Loc, ThisObj.get());
+    if (Return.isInvalid())
+      Invalid = true;
+    else {
+      Statements.push_back(Return.takeAs<Stmt>());
+
+      if (Trap.hasErrorOccurred()) {
+        Diag(CurrentLocation, diag::note_member_synthesized_at) 
+          << CXXMoveAssignment << Context.getTagDeclType(ClassDecl);
+        Invalid = true;
+      }
+    }
+  }
+
+  if (Invalid) {
+    MoveAssignOperator->setInvalidDecl();
+    return;
+  }
+
+  StmtResult Body;
+  {
+    CompoundScopeRAII CompoundScope(*this);
+    Body = ActOnCompoundStmt(Loc, Loc, move_arg(Statements),
+                             /*isStmtExpr=*/false);
+    assert(!Body.isInvalid() && "Compound statement creation cannot fail");
+  }
+  MoveAssignOperator->setBody(Body.takeAs<Stmt>());
+
+  if (ASTMutationListener *L = getASTMutationListener()) {
+    L->CompletedImplicitDefinition(MoveAssignOperator);
+  }
+}
+
+std::pair<Sema::ImplicitExceptionSpecification, bool>
+Sema::ComputeDefaultedCopyCtorExceptionSpecAndConst(CXXRecordDecl *ClassDecl) {
+  if (ClassDecl->isInvalidDecl())
+    return std::make_pair(ImplicitExceptionSpecification(*this), false);
+
+  // C++ [class.copy]p5:
+  //   The implicitly-declared copy constructor for a class X will
+  //   have the form
+  //
+  //       X::X(const X&)
+  //
+  //   if
+  // FIXME: It ought to be possible to store this on the record.
+  bool HasConstCopyConstructor = true;
+  
+  //     -- each direct or virtual base class B of X has a copy
+  //        constructor whose first parameter is of type const B& or
+  //        const volatile B&, and
+  for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin(),
+                                       BaseEnd = ClassDecl->bases_end();
+       HasConstCopyConstructor && Base != BaseEnd; 
+       ++Base) {
+    // Virtual bases are handled below.
+    if (Base->isVirtual())
+      continue;
+    
+    CXXRecordDecl *BaseClassDecl
+      = cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());
+    HasConstCopyConstructor &=
+      (bool)LookupCopyingConstructor(BaseClassDecl, Qualifiers::Const);
+  }
+
+  for (CXXRecordDecl::base_class_iterator Base = ClassDecl->vbases_begin(),
+                                       BaseEnd = ClassDecl->vbases_end();
+       HasConstCopyConstructor && Base != BaseEnd; 
+       ++Base) {
+    CXXRecordDecl *BaseClassDecl
+      = cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());
+    HasConstCopyConstructor &=
+      (bool)LookupCopyingConstructor(BaseClassDecl, Qualifiers::Const);
+  }
+  
+  //     -- for all the nonstatic data members of X that are of a
+  //        class type M (or array thereof), each such class type
+  //        has a copy constructor whose first parameter is of type
+  //        const M& or const volatile M&.
+  for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(),
+                                  FieldEnd = ClassDecl->field_end();
+       HasConstCopyConstructor && Field != FieldEnd;
+       ++Field) {
+    QualType FieldType = Context.getBaseElementType((*Field)->getType());
+    if (CXXRecordDecl *FieldClassDecl = FieldType->getAsCXXRecordDecl()) {
+      HasConstCopyConstructor &=
+        (bool)LookupCopyingConstructor(FieldClassDecl, Qualifiers::Const);
+    }
+  }
+  //   Otherwise, the implicitly declared copy constructor will have
+  //   the form
+  //
+  //       X::X(X&)
+ 
+  // C++ [except.spec]p14:
+  //   An implicitly declared special member function (Clause 12) shall have an 
+  //   exception-specification. [...]
+  ImplicitExceptionSpecification ExceptSpec(*this);
+  unsigned Quals = HasConstCopyConstructor? Qualifiers::Const : 0;
+  for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin(),
+                                       BaseEnd = ClassDecl->bases_end();
+       Base != BaseEnd; 
+       ++Base) {
+    // Virtual bases are handled below.
+    if (Base->isVirtual())
+      continue;
+    
+    CXXRecordDecl *BaseClassDecl
+      = cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());
+    if (CXXConstructorDecl *CopyConstructor =
+          LookupCopyingConstructor(BaseClassDecl, Quals))
+      ExceptSpec.CalledDecl(Base->getLocStart(), CopyConstructor);
+  }
+  for (CXXRecordDecl::base_class_iterator Base = ClassDecl->vbases_begin(),
+                                       BaseEnd = ClassDecl->vbases_end();
+       Base != BaseEnd; 
+       ++Base) {
+    CXXRecordDecl *BaseClassDecl
+      = cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());
+    if (CXXConstructorDecl *CopyConstructor =
+          LookupCopyingConstructor(BaseClassDecl, Quals))
+      ExceptSpec.CalledDecl(Base->getLocStart(), CopyConstructor);
+  }
+  for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(),
+                                  FieldEnd = ClassDecl->field_end();
+       Field != FieldEnd;
+       ++Field) {
+    QualType FieldType = Context.getBaseElementType((*Field)->getType());
+    if (CXXRecordDecl *FieldClassDecl = FieldType->getAsCXXRecordDecl()) {
+      if (CXXConstructorDecl *CopyConstructor =
+        LookupCopyingConstructor(FieldClassDecl, Quals))
+      ExceptSpec.CalledDecl(Field->getLocation(), CopyConstructor);
+    }
+  }
+
+  return std::make_pair(ExceptSpec, HasConstCopyConstructor);
+}
+
+CXXConstructorDecl *Sema::DeclareImplicitCopyConstructor(
+                                                    CXXRecordDecl *ClassDecl) {
+  // C++ [class.copy]p4:
+  //   If the class definition does not explicitly declare a copy
+  //   constructor, one is declared implicitly.
+
+  ImplicitExceptionSpecification Spec(*this);
+  bool Const;
+  llvm::tie(Spec, Const) =
+    ComputeDefaultedCopyCtorExceptionSpecAndConst(ClassDecl);
+
+  QualType ClassType = Context.getTypeDeclType(ClassDecl);
+  QualType ArgType = ClassType;
+  if (Const)
+    ArgType = ArgType.withConst();
+  ArgType = Context.getLValueReferenceType(ArgType);
+ 
+  FunctionProtoType::ExtProtoInfo EPI = Spec.getEPI();
+
+  DeclarationName Name
+    = Context.DeclarationNames.getCXXConstructorName(
+                                           Context.getCanonicalType(ClassType));
+  SourceLocation ClassLoc = ClassDecl->getLocation();
+  DeclarationNameInfo NameInfo(Name, ClassLoc);
+
+  //   An implicitly-declared copy constructor is an inline public
+  //   member of its class.
+  CXXConstructorDecl *CopyConstructor = CXXConstructorDecl::Create(
+      Context, ClassDecl, ClassLoc, NameInfo,
+      Context.getFunctionType(Context.VoidTy, &ArgType, 1, EPI), /*TInfo=*/0,
+      /*isExplicit=*/false, /*isInline=*/true, /*isImplicitlyDeclared=*/true,
+      /*isConstexpr=*/ClassDecl->defaultedCopyConstructorIsConstexpr() &&
+        getLangOpts().CPlusPlus0x);
+  CopyConstructor->setAccess(AS_public);
+  CopyConstructor->setDefaulted();
+  CopyConstructor->setTrivial(ClassDecl->hasTrivialCopyConstructor());
+
+  // Note that we have declared this constructor.
+  ++ASTContext::NumImplicitCopyConstructorsDeclared;
+  
+  // Add the parameter to the constructor.
+  ParmVarDecl *FromParam = ParmVarDecl::Create(Context, CopyConstructor,
+                                               ClassLoc, ClassLoc,
+                                               /*IdentifierInfo=*/0,
+                                               ArgType, /*TInfo=*/0,
+                                               SC_None,
+                                               SC_None, 0);
+  CopyConstructor->setParams(FromParam);
+
+  if (Scope *S = getScopeForContext(ClassDecl))
+    PushOnScopeChains(CopyConstructor, S, false);
+  ClassDecl->addDecl(CopyConstructor);
+
+  // C++11 [class.copy]p8:
+  //   ... If the class definition does not explicitly declare a copy
+  //   constructor, there is no user-declared move constructor, and there is no
+  //   user-declared move assignment operator, a copy constructor is implicitly
+  //   declared as defaulted.
+  if (ShouldDeleteSpecialMember(CopyConstructor, CXXCopyConstructor))
+    CopyConstructor->setDeletedAsWritten();
+
+  return CopyConstructor;
+}
+
+void Sema::DefineImplicitCopyConstructor(SourceLocation CurrentLocation,
+                                   CXXConstructorDecl *CopyConstructor) {
+  assert((CopyConstructor->isDefaulted() &&
+          CopyConstructor->isCopyConstructor() &&
+          !CopyConstructor->doesThisDeclarationHaveABody() &&
+          !CopyConstructor->isDeleted()) &&
+         "DefineImplicitCopyConstructor - call it for implicit copy ctor");
+
+  CXXRecordDecl *ClassDecl = CopyConstructor->getParent();
+  assert(ClassDecl && "DefineImplicitCopyConstructor - invalid constructor");
+
+  ImplicitlyDefinedFunctionScope Scope(*this, CopyConstructor);
+  DiagnosticErrorTrap Trap(Diags);
+
+  if (SetCtorInitializers(CopyConstructor, 0, 0, /*AnyErrors=*/false) ||
+      Trap.hasErrorOccurred()) {
+    Diag(CurrentLocation, diag::note_member_synthesized_at) 
+      << CXXCopyConstructor << Context.getTagDeclType(ClassDecl);
+    CopyConstructor->setInvalidDecl();
+  }  else {
+    Sema::CompoundScopeRAII CompoundScope(*this);
+    CopyConstructor->setBody(ActOnCompoundStmt(CopyConstructor->getLocation(),
+                                               CopyConstructor->getLocation(),
+                                               MultiStmtArg(*this, 0, 0),
+                                               /*isStmtExpr=*/false)
+                                                              .takeAs<Stmt>());
+    CopyConstructor->setImplicitlyDefined(true);
+  }
+  
+  CopyConstructor->setUsed();
+  if (ASTMutationListener *L = getASTMutationListener()) {
+    L->CompletedImplicitDefinition(CopyConstructor);
+  }
+}
+
+Sema::ImplicitExceptionSpecification
+Sema::ComputeDefaultedMoveCtorExceptionSpec(CXXRecordDecl *ClassDecl) {
+  // C++ [except.spec]p14:
+  //   An implicitly declared special member function (Clause 12) shall have an 
+  //   exception-specification. [...]
+  ImplicitExceptionSpecification ExceptSpec(*this);
+  if (ClassDecl->isInvalidDecl())
+    return ExceptSpec;
+
+  // Direct base-class constructors.
+  for (CXXRecordDecl::base_class_iterator B = ClassDecl->bases_begin(),
+                                       BEnd = ClassDecl->bases_end();
+       B != BEnd; ++B) {
+    if (B->isVirtual()) // Handled below.
+      continue;
+    
+    if (const RecordType *BaseType = B->getType()->getAs<RecordType>()) {
+      CXXRecordDecl *BaseClassDecl = cast<CXXRecordDecl>(BaseType->getDecl());
+      CXXConstructorDecl *Constructor = LookupMovingConstructor(BaseClassDecl);
+      // If this is a deleted function, add it anyway. This might be conformant
+      // with the standard. This might not. I'm not sure. It might not matter.
+      if (Constructor)
+        ExceptSpec.CalledDecl(B->getLocStart(), Constructor);
+    }
+  }
+
+  // Virtual base-class constructors.
+  for (CXXRecordDecl::base_class_iterator B = ClassDecl->vbases_begin(),
+                                       BEnd = ClassDecl->vbases_end();
+       B != BEnd; ++B) {
+    if (const RecordType *BaseType = B->getType()->getAs<RecordType>()) {
+      CXXRecordDecl *BaseClassDecl = cast<CXXRecordDecl>(BaseType->getDecl());
+      CXXConstructorDecl *Constructor = LookupMovingConstructor(BaseClassDecl);
+      // If this is a deleted function, add it anyway. This might be conformant
+      // with the standard. This might not. I'm not sure. It might not matter.
+      if (Constructor)
+        ExceptSpec.CalledDecl(B->getLocStart(), Constructor);
+    }
+  }
+
+  // Field constructors.
+  for (RecordDecl::field_iterator F = ClassDecl->field_begin(),
+                               FEnd = ClassDecl->field_end();
+       F != FEnd; ++F) {
+    if (const RecordType *RecordTy
+              = Context.getBaseElementType(F->getType())->getAs<RecordType>()) {
+      CXXRecordDecl *FieldRecDecl = cast<CXXRecordDecl>(RecordTy->getDecl());
+      CXXConstructorDecl *Constructor = LookupMovingConstructor(FieldRecDecl);
+      // If this is a deleted function, add it anyway. This might be conformant
+      // with the standard. This might not. I'm not sure. It might not matter.
+      // In particular, the problem is that this function never gets called. It
+      // might just be ill-formed because this function attempts to refer to
+      // a deleted function here.
+      if (Constructor)
+        ExceptSpec.CalledDecl(F->getLocation(), Constructor);
+    }
+  }
+
+  return ExceptSpec;
+}
+
+CXXConstructorDecl *Sema::DeclareImplicitMoveConstructor(
+                                                    CXXRecordDecl *ClassDecl) {
+  // C++11 [class.copy]p9:
+  //   If the definition of a class X does not explicitly declare a move
+  //   constructor, one will be implicitly declared as defaulted if and only if:
+  //
+  //   - [first 4 bullets]
+  assert(ClassDecl->needsImplicitMoveConstructor());
+
+  // [Checked after we build the declaration]
+  //   - the move assignment operator would not be implicitly defined as
+  //     deleted,
+
+  // [DR1402]:
+  //   - each of X's non-static data members and direct or virtual base classes
+  //     has a type that either has a move constructor or is trivially copyable.
+  if (!subobjectsHaveMoveOrTrivialCopy(*this, ClassDecl, /*Constructor*/true)) {
+    ClassDecl->setFailedImplicitMoveConstructor();
+    return 0;
+  }
+
+  ImplicitExceptionSpecification Spec(
+      ComputeDefaultedMoveCtorExceptionSpec(ClassDecl));
+
+  QualType ClassType = Context.getTypeDeclType(ClassDecl);
+  QualType ArgType = Context.getRValueReferenceType(ClassType);
+ 
+  FunctionProtoType::ExtProtoInfo EPI = Spec.getEPI();
+
+  DeclarationName Name
+    = Context.DeclarationNames.getCXXConstructorName(
+                                           Context.getCanonicalType(ClassType));
+  SourceLocation ClassLoc = ClassDecl->getLocation();
+  DeclarationNameInfo NameInfo(Name, ClassLoc);
+
+  // C++0x [class.copy]p11:
+  //   An implicitly-declared copy/move constructor is an inline public
+  //   member of its class.
+  CXXConstructorDecl *MoveConstructor = CXXConstructorDecl::Create(
+      Context, ClassDecl, ClassLoc, NameInfo,
+      Context.getFunctionType(Context.VoidTy, &ArgType, 1, EPI), /*TInfo=*/0,
+      /*isExplicit=*/false, /*isInline=*/true, /*isImplicitlyDeclared=*/true,
+      /*isConstexpr=*/ClassDecl->defaultedMoveConstructorIsConstexpr() &&
+        getLangOpts().CPlusPlus0x);
+  MoveConstructor->setAccess(AS_public);
+  MoveConstructor->setDefaulted();
+  MoveConstructor->setTrivial(ClassDecl->hasTrivialMoveConstructor());
+
+  // Add the parameter to the constructor.
+  ParmVarDecl *FromParam = ParmVarDecl::Create(Context, MoveConstructor,
+                                               ClassLoc, ClassLoc,
+                                               /*IdentifierInfo=*/0,
+                                               ArgType, /*TInfo=*/0,
+                                               SC_None,
+                                               SC_None, 0);
+  MoveConstructor->setParams(FromParam);
+
+  // C++0x [class.copy]p9:
+  //   If the definition of a class X does not explicitly declare a move
+  //   constructor, one will be implicitly declared as defaulted if and only if:
+  //   [...]
+  //   - the move constructor would not be implicitly defined as deleted.
+  if (ShouldDeleteSpecialMember(MoveConstructor, CXXMoveConstructor)) {
+    // Cache this result so that we don't try to generate this over and over
+    // on every lookup, leaking memory and wasting time.
+    ClassDecl->setFailedImplicitMoveConstructor();
+    return 0;
+  }
+
+  // Note that we have declared this constructor.
+  ++ASTContext::NumImplicitMoveConstructorsDeclared;
+
+  if (Scope *S = getScopeForContext(ClassDecl))
+    PushOnScopeChains(MoveConstructor, S, false);
+  ClassDecl->addDecl(MoveConstructor);
+
+  return MoveConstructor;
+}
+
+void Sema::DefineImplicitMoveConstructor(SourceLocation CurrentLocation,
+                                   CXXConstructorDecl *MoveConstructor) {
+  assert((MoveConstructor->isDefaulted() &&
+          MoveConstructor->isMoveConstructor() &&
+          !MoveConstructor->doesThisDeclarationHaveABody() &&
+          !MoveConstructor->isDeleted()) &&
+         "DefineImplicitMoveConstructor - call it for implicit move ctor");
+
+  CXXRecordDecl *ClassDecl = MoveConstructor->getParent();
+  assert(ClassDecl && "DefineImplicitMoveConstructor - invalid constructor");
+
+  ImplicitlyDefinedFunctionScope Scope(*this, MoveConstructor);
+  DiagnosticErrorTrap Trap(Diags);
+
+  if (SetCtorInitializers(MoveConstructor, 0, 0, /*AnyErrors=*/false) ||
+      Trap.hasErrorOccurred()) {
+    Diag(CurrentLocation, diag::note_member_synthesized_at) 
+      << CXXMoveConstructor << Context.getTagDeclType(ClassDecl);
+    MoveConstructor->setInvalidDecl();
+  }  else {
+    Sema::CompoundScopeRAII CompoundScope(*this);
+    MoveConstructor->setBody(ActOnCompoundStmt(MoveConstructor->getLocation(),
+                                               MoveConstructor->getLocation(),
+                                               MultiStmtArg(*this, 0, 0),
+                                               /*isStmtExpr=*/false)
+                                                              .takeAs<Stmt>());
+    MoveConstructor->setImplicitlyDefined(true);
+  }
+
+  MoveConstructor->setUsed();
+
+  if (ASTMutationListener *L = getASTMutationListener()) {
+    L->CompletedImplicitDefinition(MoveConstructor);
+  }
+}
+
+bool Sema::isImplicitlyDeleted(FunctionDecl *FD) {
+  return FD->isDeleted() && 
+         (FD->isDefaulted() || FD->isImplicit()) &&
+         isa<CXXMethodDecl>(FD);
+}
+
+/// \brief Mark the call operator of the given lambda closure type as "used".
+static void markLambdaCallOperatorUsed(Sema &S, CXXRecordDecl *Lambda) {
+  CXXMethodDecl *CallOperator 
+    = cast<CXXMethodDecl>(
+        *Lambda->lookup(
+          S.Context.DeclarationNames.getCXXOperatorName(OO_Call)).first);
+  CallOperator->setReferenced();
+  CallOperator->setUsed();
+}
+
+void Sema::DefineImplicitLambdaToFunctionPointerConversion(
+       SourceLocation CurrentLocation,
+       CXXConversionDecl *Conv) 
+{
+  CXXRecordDecl *Lambda = Conv->getParent();
+  
+  // Make sure that the lambda call operator is marked used.
+  markLambdaCallOperatorUsed(*this, Lambda);
+  
+  Conv->setUsed();
+  
+  ImplicitlyDefinedFunctionScope Scope(*this, Conv);
+  DiagnosticErrorTrap Trap(Diags);
+  
+  // Return the address of the __invoke function.
+  DeclarationName InvokeName = &Context.Idents.get("__invoke");
+  CXXMethodDecl *Invoke 
+    = cast<CXXMethodDecl>(*Lambda->lookup(InvokeName).first);
+  Expr *FunctionRef = BuildDeclRefExpr(Invoke, Invoke->getType(),
+                                       VK_LValue, Conv->getLocation()).take();
+  assert(FunctionRef && "Can't refer to __invoke function?");
+  Stmt *Return = ActOnReturnStmt(Conv->getLocation(), FunctionRef).take();
+  Conv->setBody(new (Context) CompoundStmt(Context, &Return, 1, 
+                                           Conv->getLocation(),
+                                           Conv->getLocation()));
+    
+  // Fill in the __invoke function with a dummy implementation. IR generation
+  // will fill in the actual details.
+  Invoke->setUsed();
+  Invoke->setReferenced();
+  Invoke->setBody(new (Context) CompoundStmt(Context, 0, 0, Conv->getLocation(),
+                                             Conv->getLocation()));
+  
+  if (ASTMutationListener *L = getASTMutationListener()) {
+    L->CompletedImplicitDefinition(Conv);
+    L->CompletedImplicitDefinition(Invoke);
+  }
+}
+
+void Sema::DefineImplicitLambdaToBlockPointerConversion(
+       SourceLocation CurrentLocation,
+       CXXConversionDecl *Conv) 
+{
+  Conv->setUsed();
+  
+  ImplicitlyDefinedFunctionScope Scope(*this, Conv);
+  DiagnosticErrorTrap Trap(Diags);
+  
+  // Copy-initialize the lambda object as needed to capture it.
+  Expr *This = ActOnCXXThis(CurrentLocation).take();
+  Expr *DerefThis =CreateBuiltinUnaryOp(CurrentLocation, UO_Deref, This).take();
+  
+  ExprResult BuildBlock = BuildBlockForLambdaConversion(CurrentLocation,
+                                                        Conv->getLocation(),
+                                                        Conv, DerefThis);
+
+  // If we're not under ARC, make sure we still get the _Block_copy/autorelease
+  // behavior.  Note that only the general conversion function does this
+  // (since it's unusable otherwise); in the case where we inline the
+  // block literal, it has block literal lifetime semantics.
+  if (!BuildBlock.isInvalid() && !getLangOpts().ObjCAutoRefCount)
+    BuildBlock = ImplicitCastExpr::Create(Context, BuildBlock.get()->getType(),
+                                          CK_CopyAndAutoreleaseBlockObject,
+                                          BuildBlock.get(), 0, VK_RValue);
+
+  if (BuildBlock.isInvalid()) {
+    Diag(CurrentLocation, diag::note_lambda_to_block_conv);
+    Conv->setInvalidDecl();
+    return;
+  }
+
+  // Create the return statement that returns the block from the conversion
+  // function.
+  StmtResult Return = ActOnReturnStmt(Conv->getLocation(), BuildBlock.get());
+  if (Return.isInvalid()) {
+    Diag(CurrentLocation, diag::note_lambda_to_block_conv);
+    Conv->setInvalidDecl();
+    return;
+  }
+
+  // Set the body of the conversion function.
+  Stmt *ReturnS = Return.take();
+  Conv->setBody(new (Context) CompoundStmt(Context, &ReturnS, 1, 
+                                           Conv->getLocation(), 
+                                           Conv->getLocation()));
+  
+  // We're done; notify the mutation listener, if any.
+  if (ASTMutationListener *L = getASTMutationListener()) {
+    L->CompletedImplicitDefinition(Conv);
+  }
+}
+
+/// \brief Determine whether the given list arguments contains exactly one 
+/// "real" (non-default) argument.
+static bool hasOneRealArgument(MultiExprArg Args) {
+  switch (Args.size()) {
+  case 0:
+    return false;
+    
+  default:
+    if (!Args.get()[1]->isDefaultArgument())
+      return false;
+    
+    // fall through
+  case 1:
+    return !Args.get()[0]->isDefaultArgument();
+  }
+  
+  return false;
+}
+
+ExprResult
+Sema::BuildCXXConstructExpr(SourceLocation ConstructLoc, QualType DeclInitType,
+                            CXXConstructorDecl *Constructor,
+                            MultiExprArg ExprArgs,
+                            bool HadMultipleCandidates,
+                            bool RequiresZeroInit,
+                            unsigned ConstructKind,
+                            SourceRange ParenRange) {
+  bool Elidable = false;
+
+  // C++0x [class.copy]p34:
+  //   When certain criteria are met, an implementation is allowed to
+  //   omit the copy/move construction of a class object, even if the
+  //   copy/move constructor and/or destructor for the object have
+  //   side effects. [...]
+  //     - when a temporary class object that has not been bound to a
+  //       reference (12.2) would be copied/moved to a class object
+  //       with the same cv-unqualified type, the copy/move operation
+  //       can be omitted by constructing the temporary object
+  //       directly into the target of the omitted copy/move
+  if (ConstructKind == CXXConstructExpr::CK_Complete &&
+      Constructor->isCopyOrMoveConstructor() && hasOneRealArgument(ExprArgs)) {
+    Expr *SubExpr = ((Expr **)ExprArgs.get())[0];
+    Elidable = SubExpr->isTemporaryObject(Context, Constructor->getParent());
+  }
+
+  return BuildCXXConstructExpr(ConstructLoc, DeclInitType, Constructor,
+                               Elidable, move(ExprArgs), HadMultipleCandidates,
+                               RequiresZeroInit, ConstructKind, ParenRange);
+}
+
+/// BuildCXXConstructExpr - Creates a complete call to a constructor,
+/// including handling of its default argument expressions.
+ExprResult
+Sema::BuildCXXConstructExpr(SourceLocation ConstructLoc, QualType DeclInitType,
+                            CXXConstructorDecl *Constructor, bool Elidable,
+                            MultiExprArg ExprArgs,
+                            bool HadMultipleCandidates,
+                            bool RequiresZeroInit,
+                            unsigned ConstructKind,
+                            SourceRange ParenRange) {
+  unsigned NumExprs = ExprArgs.size();
+  Expr **Exprs = (Expr **)ExprArgs.release();
+
+  for (specific_attr_iterator<NonNullAttr>
+           i = Constructor->specific_attr_begin<NonNullAttr>(),
+           e = Constructor->specific_attr_end<NonNullAttr>(); i != e; ++i) {
+    const NonNullAttr *NonNull = *i;
+    CheckNonNullArguments(NonNull, ExprArgs.get(), ConstructLoc);
+  }
+
+  MarkFunctionReferenced(ConstructLoc, Constructor);
+  return Owned(CXXConstructExpr::Create(Context, DeclInitType, ConstructLoc,
+                                        Constructor, Elidable, Exprs, NumExprs,
+                                        HadMultipleCandidates, /*FIXME*/false,
+                                        RequiresZeroInit,
+              static_cast<CXXConstructExpr::ConstructionKind>(ConstructKind),
+                                        ParenRange));
+}
+
+bool Sema::InitializeVarWithConstructor(VarDecl *VD,
+                                        CXXConstructorDecl *Constructor,
+                                        MultiExprArg Exprs,
+                                        bool HadMultipleCandidates) {
+  // FIXME: Provide the correct paren SourceRange when available.
+  ExprResult TempResult =
+    BuildCXXConstructExpr(VD->getLocation(), VD->getType(), Constructor,
+                          move(Exprs), HadMultipleCandidates, false,
+                          CXXConstructExpr::CK_Complete, SourceRange());
+  if (TempResult.isInvalid())
+    return true;
+
+  Expr *Temp = TempResult.takeAs<Expr>();
+  CheckImplicitConversions(Temp, VD->getLocation());
+  MarkFunctionReferenced(VD->getLocation(), Constructor);
+  Temp = MaybeCreateExprWithCleanups(Temp);
+  VD->setInit(Temp);
+
+  return false;
+}
+
+void Sema::FinalizeVarWithDestructor(VarDecl *VD, const RecordType *Record) {
+  if (VD->isInvalidDecl()) return;
+
+  CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(Record->getDecl());
+  if (ClassDecl->isInvalidDecl()) return;
+  if (ClassDecl->hasIrrelevantDestructor()) return;
+  if (ClassDecl->isDependentContext()) return;
+
+  CXXDestructorDecl *Destructor = LookupDestructor(ClassDecl);
+  MarkFunctionReferenced(VD->getLocation(), Destructor);
+  CheckDestructorAccess(VD->getLocation(), Destructor,
+                        PDiag(diag::err_access_dtor_var)
+                        << VD->getDeclName()
+                        << VD->getType());
+  DiagnoseUseOfDecl(Destructor, VD->getLocation());
+
+  if (!VD->hasGlobalStorage()) return;
+
+  // Emit warning for non-trivial dtor in global scope (a real global,
+  // class-static, function-static).
+  Diag(VD->getLocation(), diag::warn_exit_time_destructor);
+
+  // TODO: this should be re-enabled for static locals by !CXAAtExit
+  if (!VD->isStaticLocal())
+    Diag(VD->getLocation(), diag::warn_global_destructor);
+}
+
+/// \brief Given a constructor and the set of arguments provided for the
+/// constructor, convert the arguments and add any required default arguments
+/// to form a proper call to this constructor.
+///
+/// \returns true if an error occurred, false otherwise.
+bool 
+Sema::CompleteConstructorCall(CXXConstructorDecl *Constructor,
+                              MultiExprArg ArgsPtr,
+                              SourceLocation Loc,                                    
+                              ASTOwningVector<Expr*> &ConvertedArgs,
+                              bool AllowExplicit) {
+  // FIXME: This duplicates a lot of code from Sema::ConvertArgumentsForCall.
+  unsigned NumArgs = ArgsPtr.size();
+  Expr **Args = (Expr **)ArgsPtr.get();
+
+  const FunctionProtoType *Proto 
+    = Constructor->getType()->getAs<FunctionProtoType>();
+  assert(Proto && "Constructor without a prototype?");
+  unsigned NumArgsInProto = Proto->getNumArgs();
+  
+  // If too few arguments are available, we'll fill in the rest with defaults.
+  if (NumArgs < NumArgsInProto)
+    ConvertedArgs.reserve(NumArgsInProto);
+  else
+    ConvertedArgs.reserve(NumArgs);
+
+  VariadicCallType CallType = 
+    Proto->isVariadic() ? VariadicConstructor : VariadicDoesNotApply;
+  SmallVector<Expr *, 8> AllArgs;
+  bool Invalid = GatherArgumentsForCall(Loc, Constructor,
+                                        Proto, 0, Args, NumArgs, AllArgs, 
+                                        CallType, AllowExplicit);
+  ConvertedArgs.append(AllArgs.begin(), AllArgs.end());
+
+  DiagnoseSentinelCalls(Constructor, Loc, AllArgs.data(), AllArgs.size());
+
+  // FIXME: Missing call to CheckFunctionCall or equivalent
+
+  return Invalid;
+}
+
+static inline bool
+CheckOperatorNewDeleteDeclarationScope(Sema &SemaRef, 
+                                       const FunctionDecl *FnDecl) {
+  const DeclContext *DC = FnDecl->getDeclContext()->getRedeclContext();
+  if (isa<NamespaceDecl>(DC)) {
+    return SemaRef.Diag(FnDecl->getLocation(), 
+                        diag::err_operator_new_delete_declared_in_namespace)
+      << FnDecl->getDeclName();
+  }
+  
+  if (isa<TranslationUnitDecl>(DC) && 
+      FnDecl->getStorageClass() == SC_Static) {
+    return SemaRef.Diag(FnDecl->getLocation(),
+                        diag::err_operator_new_delete_declared_static)
+      << FnDecl->getDeclName();
+  }
+  
+  return false;
+}
+
+static inline bool
+CheckOperatorNewDeleteTypes(Sema &SemaRef, const FunctionDecl *FnDecl,
+                            CanQualType ExpectedResultType,
+                            CanQualType ExpectedFirstParamType,
+                            unsigned DependentParamTypeDiag,
+                            unsigned InvalidParamTypeDiag) {
+  QualType ResultType = 
+    FnDecl->getType()->getAs<FunctionType>()->getResultType();
+
+  // Check that the result type is not dependent.
+  if (ResultType->isDependentType())
+    return SemaRef.Diag(FnDecl->getLocation(),
+                        diag::err_operator_new_delete_dependent_result_type)
+    << FnDecl->getDeclName() << ExpectedResultType;
+
+  // Check that the result type is what we expect.
+  if (SemaRef.Context.getCanonicalType(ResultType) != ExpectedResultType)
+    return SemaRef.Diag(FnDecl->getLocation(),
+                        diag::err_operator_new_delete_invalid_result_type) 
+    << FnDecl->getDeclName() << ExpectedResultType;
+  
+  // A function template must have at least 2 parameters.
+  if (FnDecl->getDescribedFunctionTemplate() && FnDecl->getNumParams() < 2)
+    return SemaRef.Diag(FnDecl->getLocation(),
+                      diag::err_operator_new_delete_template_too_few_parameters)
+        << FnDecl->getDeclName();
+  
+  // The function decl must have at least 1 parameter.
+  if (FnDecl->getNumParams() == 0)
+    return SemaRef.Diag(FnDecl->getLocation(),
+                        diag::err_operator_new_delete_too_few_parameters)
+      << FnDecl->getDeclName();
+ 
+  // Check the the first parameter type is not dependent.
+  QualType FirstParamType = FnDecl->getParamDecl(0)->getType();
+  if (FirstParamType->isDependentType())
+    return SemaRef.Diag(FnDecl->getLocation(), DependentParamTypeDiag)
+      << FnDecl->getDeclName() << ExpectedFirstParamType;
+
+  // Check that the first parameter type is what we expect.
+  if (SemaRef.Context.getCanonicalType(FirstParamType).getUnqualifiedType() != 
+      ExpectedFirstParamType)
+    return SemaRef.Diag(FnDecl->getLocation(), InvalidParamTypeDiag)
+    << FnDecl->getDeclName() << ExpectedFirstParamType;
+  
+  return false;
+}
+
+static bool
+CheckOperatorNewDeclaration(Sema &SemaRef, const FunctionDecl *FnDecl) {
+  // C++ [basic.stc.dynamic.allocation]p1:
+  //   A program is ill-formed if an allocation function is declared in a
+  //   namespace scope other than global scope or declared static in global 
+  //   scope.
+  if (CheckOperatorNewDeleteDeclarationScope(SemaRef, FnDecl))
+    return true;
+
+  CanQualType SizeTy = 
+    SemaRef.Context.getCanonicalType(SemaRef.Context.getSizeType());
+
+  // C++ [basic.stc.dynamic.allocation]p1:
+  //  The return type shall be void*. The first parameter shall have type 
+  //  std::size_t.
+  if (CheckOperatorNewDeleteTypes(SemaRef, FnDecl, SemaRef.Context.VoidPtrTy, 
+                                  SizeTy,
+                                  diag::err_operator_new_dependent_param_type,
+                                  diag::err_operator_new_param_type))
+    return true;
+
+  // C++ [basic.stc.dynamic.allocation]p1:
+  //  The first parameter shall not have an associated default argument.
+  if (FnDecl->getParamDecl(0)->hasDefaultArg())
+    return SemaRef.Diag(FnDecl->getLocation(),
+                        diag::err_operator_new_default_arg)
+      << FnDecl->getDeclName() << FnDecl->getParamDecl(0)->getDefaultArgRange();
+
+  return false;
+}
+
+static bool
+CheckOperatorDeleteDeclaration(Sema &SemaRef, const FunctionDecl *FnDecl) {
+  // C++ [basic.stc.dynamic.deallocation]p1:
+  //   A program is ill-formed if deallocation functions are declared in a
+  //   namespace scope other than global scope or declared static in global 
+  //   scope.
+  if (CheckOperatorNewDeleteDeclarationScope(SemaRef, FnDecl))
+    return true;
+
+  // C++ [basic.stc.dynamic.deallocation]p2:
+  //   Each deallocation function shall return void and its first parameter 
+  //   shall be void*.
+  if (CheckOperatorNewDeleteTypes(SemaRef, FnDecl, SemaRef.Context.VoidTy, 
+                                  SemaRef.Context.VoidPtrTy,
+                                 diag::err_operator_delete_dependent_param_type,
+                                 diag::err_operator_delete_param_type))
+    return true;
+
+  return false;
+}
+
+/// CheckOverloadedOperatorDeclaration - Check whether the declaration
+/// of this overloaded operator is well-formed. If so, returns false;
+/// otherwise, emits appropriate diagnostics and returns true.
+bool Sema::CheckOverloadedOperatorDeclaration(FunctionDecl *FnDecl) {
+  assert(FnDecl && FnDecl->isOverloadedOperator() &&
+         "Expected an overloaded operator declaration");
+
+  OverloadedOperatorKind Op = FnDecl->getOverloadedOperator();
+
+  // C++ [over.oper]p5:
+  //   The allocation and deallocation functions, operator new,
+  //   operator new[], operator delete and operator delete[], are
+  //   described completely in 3.7.3. The attributes and restrictions
+  //   found in the rest of this subclause do not apply to them unless
+  //   explicitly stated in 3.7.3.
+  if (Op == OO_Delete || Op == OO_Array_Delete)
+    return CheckOperatorDeleteDeclaration(*this, FnDecl);
+  
+  if (Op == OO_New || Op == OO_Array_New)
+    return CheckOperatorNewDeclaration(*this, FnDecl);
+
+  // C++ [over.oper]p6:
+  //   An operator function shall either be a non-static member
+  //   function or be a non-member function and have at least one
+  //   parameter whose type is a class, a reference to a class, an
+  //   enumeration, or a reference to an enumeration.
+  if (CXXMethodDecl *MethodDecl = dyn_cast<CXXMethodDecl>(FnDecl)) {
+    if (MethodDecl->isStatic())
+      return Diag(FnDecl->getLocation(),
+                  diag::err_operator_overload_static) << FnDecl->getDeclName();
+  } else {
+    bool ClassOrEnumParam = false;
+    for (FunctionDecl::param_iterator Param = FnDecl->param_begin(),
+                                   ParamEnd = FnDecl->param_end();
+         Param != ParamEnd; ++Param) {
+      QualType ParamType = (*Param)->getType().getNonReferenceType();
+      if (ParamType->isDependentType() || ParamType->isRecordType() ||
+          ParamType->isEnumeralType()) {
+        ClassOrEnumParam = true;
+        break;
+      }
+    }
+
+    if (!ClassOrEnumParam)
+      return Diag(FnDecl->getLocation(),
+                  diag::err_operator_overload_needs_class_or_enum)
+        << FnDecl->getDeclName();
+  }
+
+  // C++ [over.oper]p8:
+  //   An operator function cannot have default arguments (8.3.6),
+  //   except where explicitly stated below.
+  //
+  // Only the function-call operator allows default arguments
+  // (C++ [over.call]p1).
+  if (Op != OO_Call) {
+    for (FunctionDecl::param_iterator Param = FnDecl->param_begin();
+         Param != FnDecl->param_end(); ++Param) {
+      if ((*Param)->hasDefaultArg())
+        return Diag((*Param)->getLocation(),
+                    diag::err_operator_overload_default_arg)
+          << FnDecl->getDeclName() << (*Param)->getDefaultArgRange();
+    }
+  }
+
+  static const bool OperatorUses[NUM_OVERLOADED_OPERATORS][3] = {
+    { false, false, false }
+#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \
+    , { Unary, Binary, MemberOnly }
+#include "clang/Basic/OperatorKinds.def"
+  };
+
+  bool CanBeUnaryOperator = OperatorUses[Op][0];
+  bool CanBeBinaryOperator = OperatorUses[Op][1];
+  bool MustBeMemberOperator = OperatorUses[Op][2];
+
+  // C++ [over.oper]p8:
+  //   [...] Operator functions cannot have more or fewer parameters
+  //   than the number required for the corresponding operator, as
+  //   described in the rest of this subclause.
+  unsigned NumParams = FnDecl->getNumParams()
+                     + (isa<CXXMethodDecl>(FnDecl)? 1 : 0);
+  if (Op != OO_Call &&
+      ((NumParams == 1 && !CanBeUnaryOperator) ||
+       (NumParams == 2 && !CanBeBinaryOperator) ||
+       (NumParams < 1) || (NumParams > 2))) {
+    // We have the wrong number of parameters.
+    unsigned ErrorKind;
+    if (CanBeUnaryOperator && CanBeBinaryOperator) {
+      ErrorKind = 2;  // 2 -> unary or binary.
+    } else if (CanBeUnaryOperator) {
+      ErrorKind = 0;  // 0 -> unary
+    } else {
+      assert(CanBeBinaryOperator &&
+             "All non-call overloaded operators are unary or binary!");
+      ErrorKind = 1;  // 1 -> binary
+    }
+
+    return Diag(FnDecl->getLocation(), diag::err_operator_overload_must_be)
+      << FnDecl->getDeclName() << NumParams << ErrorKind;
+  }
+
+  // Overloaded operators other than operator() cannot be variadic.
+  if (Op != OO_Call &&
+      FnDecl->getType()->getAs<FunctionProtoType>()->isVariadic()) {
+    return Diag(FnDecl->getLocation(), diag::err_operator_overload_variadic)
+      << FnDecl->getDeclName();
+  }
+
+  // Some operators must be non-static member functions.
+  if (MustBeMemberOperator && !isa<CXXMethodDecl>(FnDecl)) {
+    return Diag(FnDecl->getLocation(),
+                diag::err_operator_overload_must_be_member)
+      << FnDecl->getDeclName();
+  }
+
+  // C++ [over.inc]p1:
+  //   The user-defined function called operator++ implements the
+  //   prefix and postfix ++ operator. If this function is a member
+  //   function with no parameters, or a non-member function with one
+  //   parameter of class or enumeration type, it defines the prefix
+  //   increment operator ++ for objects of that type. If the function
+  //   is a member function with one parameter (which shall be of type
+  //   int) or a non-member function with two parameters (the second
+  //   of which shall be of type int), it defines the postfix
+  //   increment operator ++ for objects of that type.
+  if ((Op == OO_PlusPlus || Op == OO_MinusMinus) && NumParams == 2) {
+    ParmVarDecl *LastParam = FnDecl->getParamDecl(FnDecl->getNumParams() - 1);
+    bool ParamIsInt = false;
+    if (const BuiltinType *BT = LastParam->getType()->getAs<BuiltinType>())
+      ParamIsInt = BT->getKind() == BuiltinType::Int;
+
+    if (!ParamIsInt)
+      return Diag(LastParam->getLocation(),
+                  diag::err_operator_overload_post_incdec_must_be_int)
+        << LastParam->getType() << (Op == OO_MinusMinus);
+  }
+
+  return false;
+}
+
+/// CheckLiteralOperatorDeclaration - Check whether the declaration
+/// of this literal operator function is well-formed. If so, returns
+/// false; otherwise, emits appropriate diagnostics and returns true.
+bool Sema::CheckLiteralOperatorDeclaration(FunctionDecl *FnDecl) {
+  if (isa<CXXMethodDecl>(FnDecl)) {
+    Diag(FnDecl->getLocation(), diag::err_literal_operator_outside_namespace)
+      << FnDecl->getDeclName();
+    return true;
+  }
+
+  if (FnDecl->isExternC()) {
+    Diag(FnDecl->getLocation(), diag::err_literal_operator_extern_c);
+    return true;
+  }
+
+  bool Valid = false;
+
+  // This might be the definition of a literal operator template.
+  FunctionTemplateDecl *TpDecl = FnDecl->getDescribedFunctionTemplate();
+  // This might be a specialization of a literal operator template.
+  if (!TpDecl)
+    TpDecl = FnDecl->getPrimaryTemplate();
+
+  // template <char...> type operator "" name() is the only valid template
+  // signature, and the only valid signature with no parameters.
+  if (TpDecl) {
+    if (FnDecl->param_size() == 0) {
+      // Must have only one template parameter
+      TemplateParameterList *Params = TpDecl->getTemplateParameters();
+      if (Params->size() == 1) {
+        NonTypeTemplateParmDecl *PmDecl =
+          cast<NonTypeTemplateParmDecl>(Params->getParam(0));
+
+        // The template parameter must be a char parameter pack.
+        if (PmDecl && PmDecl->isTemplateParameterPack() &&
+            Context.hasSameType(PmDecl->getType(), Context.CharTy))
+          Valid = true;
+      }
+    }
+  } else if (FnDecl->param_size()) {
+    // Check the first parameter
+    FunctionDecl::param_iterator Param = FnDecl->param_begin();
+
+    QualType T = (*Param)->getType().getUnqualifiedType();
+
+    // unsigned long long int, long double, and any character type are allowed
+    // as the only parameters.
+    if (Context.hasSameType(T, Context.UnsignedLongLongTy) ||
+        Context.hasSameType(T, Context.LongDoubleTy) ||
+        Context.hasSameType(T, Context.CharTy) ||
+        Context.hasSameType(T, Context.WCharTy) ||
+        Context.hasSameType(T, Context.Char16Ty) ||
+        Context.hasSameType(T, Context.Char32Ty)) {
+      if (++Param == FnDecl->param_end())
+        Valid = true;
+      goto FinishedParams;
+    }
+
+    // Otherwise it must be a pointer to const; let's strip those qualifiers.
+    const PointerType *PT = T->getAs<PointerType>();
+    if (!PT)
+      goto FinishedParams;
+    T = PT->getPointeeType();
+    if (!T.isConstQualified() || T.isVolatileQualified())
+      goto FinishedParams;
+    T = T.getUnqualifiedType();
+
+    // Move on to the second parameter;
+    ++Param;
+
+    // If there is no second parameter, the first must be a const char *
+    if (Param == FnDecl->param_end()) {
+      if (Context.hasSameType(T, Context.CharTy))
+        Valid = true;
+      goto FinishedParams;
+    }
+
+    // const char *, const wchar_t*, const char16_t*, and const char32_t*
+    // are allowed as the first parameter to a two-parameter function
+    if (!(Context.hasSameType(T, Context.CharTy) ||
+          Context.hasSameType(T, Context.WCharTy) ||
+          Context.hasSameType(T, Context.Char16Ty) ||
+          Context.hasSameType(T, Context.Char32Ty)))
+      goto FinishedParams;
+
+    // The second and final parameter must be an std::size_t
+    T = (*Param)->getType().getUnqualifiedType();
+    if (Context.hasSameType(T, Context.getSizeType()) &&
+        ++Param == FnDecl->param_end())
+      Valid = true;
+  }
+
+  // FIXME: This diagnostic is absolutely terrible.
+FinishedParams:
+  if (!Valid) {
+    Diag(FnDecl->getLocation(), diag::err_literal_operator_params)
+      << FnDecl->getDeclName();
+    return true;
+  }
+
+  // A parameter-declaration-clause containing a default argument is not
+  // equivalent to any of the permitted forms.
+  for (FunctionDecl::param_iterator Param = FnDecl->param_begin(),
+                                    ParamEnd = FnDecl->param_end();
+       Param != ParamEnd; ++Param) {
+    if ((*Param)->hasDefaultArg()) {
+      Diag((*Param)->getDefaultArgRange().getBegin(),
+           diag::err_literal_operator_default_argument)
+        << (*Param)->getDefaultArgRange();
+      break;
+    }
+  }
+
+  StringRef LiteralName
+    = FnDecl->getDeclName().getCXXLiteralIdentifier()->getName();
+  if (LiteralName[0] != '_') {
+    // C++11 [usrlit.suffix]p1:
+    //   Literal suffix identifiers that do not start with an underscore
+    //   are reserved for future standardization.
+    Diag(FnDecl->getLocation(), diag::warn_user_literal_reserved);
+  }
+
+  return false;
+}
+
+/// ActOnStartLinkageSpecification - Parsed the beginning of a C++
+/// linkage specification, including the language and (if present)
+/// the '{'. ExternLoc is the location of the 'extern', LangLoc is
+/// the location of the language string literal, which is provided
+/// by Lang/StrSize. LBraceLoc, if valid, provides the location of
+/// the '{' brace. Otherwise, this linkage specification does not
+/// have any braces.
+Decl *Sema::ActOnStartLinkageSpecification(Scope *S, SourceLocation ExternLoc,
+                                           SourceLocation LangLoc,
+                                           StringRef Lang,
+                                           SourceLocation LBraceLoc) {
+  LinkageSpecDecl::LanguageIDs Language;
+  if (Lang == "\"C\"")
+    Language = LinkageSpecDecl::lang_c;
+  else if (Lang == "\"C++\"")
+    Language = LinkageSpecDecl::lang_cxx;
+  else {
+    Diag(LangLoc, diag::err_bad_language);
+    return 0;
+  }
+
+  // FIXME: Add all the various semantics of linkage specifications
+
+  LinkageSpecDecl *D = LinkageSpecDecl::Create(Context, CurContext,
+                                               ExternLoc, LangLoc, Language);
+  CurContext->addDecl(D);
+  PushDeclContext(S, D);
+  return D;
+}
+
+/// ActOnFinishLinkageSpecification - Complete the definition of
+/// the C++ linkage specification LinkageSpec. If RBraceLoc is
+/// valid, it's the position of the closing '}' brace in a linkage
+/// specification that uses braces.
+Decl *Sema::ActOnFinishLinkageSpecification(Scope *S,
+                                            Decl *LinkageSpec,
+                                            SourceLocation RBraceLoc) {
+  if (LinkageSpec) {
+    if (RBraceLoc.isValid()) {
+      LinkageSpecDecl* LSDecl = cast<LinkageSpecDecl>(LinkageSpec);
+      LSDecl->setRBraceLoc(RBraceLoc);
+    }
+    PopDeclContext();
+  }
+  return LinkageSpec;
+}
+
+/// \brief Perform semantic analysis for the variable declaration that
+/// occurs within a C++ catch clause, returning the newly-created
+/// variable.
+VarDecl *Sema::BuildExceptionDeclaration(Scope *S,
+                                         TypeSourceInfo *TInfo,
+                                         SourceLocation StartLoc,
+                                         SourceLocation Loc,
+                                         IdentifierInfo *Name) {
+  bool Invalid = false;
+  QualType ExDeclType = TInfo->getType();
+  
+  // Arrays and functions decay.
+  if (ExDeclType->isArrayType())
+    ExDeclType = Context.getArrayDecayedType(ExDeclType);
+  else if (ExDeclType->isFunctionType())
+    ExDeclType = Context.getPointerType(ExDeclType);
+
+  // C++ 15.3p1: The exception-declaration shall not denote an incomplete type.
+  // The exception-declaration shall not denote a pointer or reference to an
+  // incomplete type, other than [cv] void*.
+  // N2844 forbids rvalue references.
+  if (!ExDeclType->isDependentType() && ExDeclType->isRValueReferenceType()) {
+    Diag(Loc, diag::err_catch_rvalue_ref);
+    Invalid = true;
+  }
+
+  QualType BaseType = ExDeclType;
+  int Mode = 0; // 0 for direct type, 1 for pointer, 2 for reference
+  unsigned DK = diag::err_catch_incomplete;
+  if (const PointerType *Ptr = BaseType->getAs<PointerType>()) {
+    BaseType = Ptr->getPointeeType();
+    Mode = 1;
+    DK = diag::err_catch_incomplete_ptr;
+  } else if (const ReferenceType *Ref = BaseType->getAs<ReferenceType>()) {
+    // For the purpose of error recovery, we treat rvalue refs like lvalue refs.
+    BaseType = Ref->getPointeeType();
+    Mode = 2;
+    DK = diag::err_catch_incomplete_ref;
+  }
+  if (!Invalid && (Mode == 0 || !BaseType->isVoidType()) &&
+      !BaseType->isDependentType() && RequireCompleteType(Loc, BaseType, DK))
+    Invalid = true;
+
+  if (!Invalid && !ExDeclType->isDependentType() &&
+      RequireNonAbstractType(Loc, ExDeclType,
+                             diag::err_abstract_type_in_decl,
+                             AbstractVariableType))
+    Invalid = true;
+
+  // Only the non-fragile NeXT runtime currently supports C++ catches
+  // of ObjC types, and no runtime supports catching ObjC types by value.
+  if (!Invalid && getLangOpts().ObjC1) {
+    QualType T = ExDeclType;
+    if (const ReferenceType *RT = T->getAs<ReferenceType>())
+      T = RT->getPointeeType();
+
+    if (T->isObjCObjectType()) {
+      Diag(Loc, diag::err_objc_object_catch);
+      Invalid = true;
+    } else if (T->isObjCObjectPointerType()) {
+      if (!getLangOpts().ObjCNonFragileABI)
+        Diag(Loc, diag::warn_objc_pointer_cxx_catch_fragile);
+    }
+  }
+
+  VarDecl *ExDecl = VarDecl::Create(Context, CurContext, StartLoc, Loc, Name,
+                                    ExDeclType, TInfo, SC_None, SC_None);
+  ExDecl->setExceptionVariable(true);
+  
+  // In ARC, infer 'retaining' for variables of retainable type.
+  if (getLangOpts().ObjCAutoRefCount && inferObjCARCLifetime(ExDecl))
+    Invalid = true;
+
+  if (!Invalid && !ExDeclType->isDependentType()) {
+    if (const RecordType *recordType = ExDeclType->getAs<RecordType>()) {
+      // C++ [except.handle]p16:
+      //   The object declared in an exception-declaration or, if the 
+      //   exception-declaration does not specify a name, a temporary (12.2) is 
+      //   copy-initialized (8.5) from the exception object. [...]
+      //   The object is destroyed when the handler exits, after the destruction
+      //   of any automatic objects initialized within the handler.
+      //
+      // We just pretend to initialize the object with itself, then make sure 
+      // it can be destroyed later.
+      QualType initType = ExDeclType;
+
+      InitializedEntity entity =
+        InitializedEntity::InitializeVariable(ExDecl);
+      InitializationKind initKind =
+        InitializationKind::CreateCopy(Loc, SourceLocation());
+
+      Expr *opaqueValue =
+        new (Context) OpaqueValueExpr(Loc, initType, VK_LValue, OK_Ordinary);
+      InitializationSequence sequence(*this, entity, initKind, &opaqueValue, 1);
+      ExprResult result = sequence.Perform(*this, entity, initKind,
+                                           MultiExprArg(&opaqueValue, 1));
+      if (result.isInvalid())
+        Invalid = true;
+      else {
+        // If the constructor used was non-trivial, set this as the
+        // "initializer".
+        CXXConstructExpr *construct = cast<CXXConstructExpr>(result.take());
+        if (!construct->getConstructor()->isTrivial()) {
+          Expr *init = MaybeCreateExprWithCleanups(construct);
+          ExDecl->setInit(init);
+        }
+        
+        // And make sure it's destructable.
+        FinalizeVarWithDestructor(ExDecl, recordType);
+      }
+    }
+  }
+  
+  if (Invalid)
+    ExDecl->setInvalidDecl();
+
+  return ExDecl;
+}
+
+/// ActOnExceptionDeclarator - Parsed the exception-declarator in a C++ catch
+/// handler.
+Decl *Sema::ActOnExceptionDeclarator(Scope *S, Declarator &D) {
+  TypeSourceInfo *TInfo = GetTypeForDeclarator(D, S);
+  bool Invalid = D.isInvalidType();
+
+  // Check for unexpanded parameter packs.
+  if (TInfo && DiagnoseUnexpandedParameterPack(D.getIdentifierLoc(), TInfo,
+                                               UPPC_ExceptionType)) {
+    TInfo = Context.getTrivialTypeSourceInfo(Context.IntTy, 
+                                             D.getIdentifierLoc());
+    Invalid = true;
+  }
+
+  IdentifierInfo *II = D.getIdentifier();
+  if (NamedDecl *PrevDecl = LookupSingleName(S, II, D.getIdentifierLoc(),
+                                             LookupOrdinaryName,
+                                             ForRedeclaration)) {
+    // The scope should be freshly made just for us. There is just no way
+    // it contains any previous declaration.
+    assert(!S->isDeclScope(PrevDecl));
+    if (PrevDecl->isTemplateParameter()) {
+      // Maybe we will complain about the shadowed template parameter.
+      DiagnoseTemplateParameterShadow(D.getIdentifierLoc(), PrevDecl);
+      PrevDecl = 0;
+    }
+  }
+
+  if (D.getCXXScopeSpec().isSet() && !Invalid) {
+    Diag(D.getIdentifierLoc(), diag::err_qualified_catch_declarator)
+      << D.getCXXScopeSpec().getRange();
+    Invalid = true;
+  }
+
+  VarDecl *ExDecl = BuildExceptionDeclaration(S, TInfo,
+                                              D.getLocStart(),
+                                              D.getIdentifierLoc(),
+                                              D.getIdentifier());
+  if (Invalid)
+    ExDecl->setInvalidDecl();
+
+  // Add the exception declaration into this scope.
+  if (II)
+    PushOnScopeChains(ExDecl, S);
+  else
+    CurContext->addDecl(ExDecl);
+
+  ProcessDeclAttributes(S, ExDecl, D);
+  return ExDecl;
+}
+
+Decl *Sema::ActOnStaticAssertDeclaration(SourceLocation StaticAssertLoc,
+                                         Expr *AssertExpr,
+                                         Expr *AssertMessageExpr_,
+                                         SourceLocation RParenLoc) {
+  StringLiteral *AssertMessage = cast<StringLiteral>(AssertMessageExpr_);
+
+  if (!AssertExpr->isTypeDependent() && !AssertExpr->isValueDependent()) {
+    // In a static_assert-declaration, the constant-expression shall be a
+    // constant expression that can be contextually converted to bool.
+    ExprResult Converted = PerformContextuallyConvertToBool(AssertExpr);
+    if (Converted.isInvalid())
+      return 0;
+
+    llvm::APSInt Cond;
+    if (VerifyIntegerConstantExpression(Converted.get(), &Cond,
+          PDiag(diag::err_static_assert_expression_is_not_constant),
+          /*AllowFold=*/false).isInvalid())
+      return 0;
+
+    if (!Cond) {
+      llvm::SmallString<256> MsgBuffer;
+      llvm::raw_svector_ostream Msg(MsgBuffer);
+      AssertMessage->printPretty(Msg, Context, 0, getPrintingPolicy());
+      Diag(StaticAssertLoc, diag::err_static_assert_failed)
+        << Msg.str() << AssertExpr->getSourceRange();
+    }
+  }
+
+  if (DiagnoseUnexpandedParameterPack(AssertExpr, UPPC_StaticAssertExpression))
+    return 0;
+
+  Decl *Decl = StaticAssertDecl::Create(Context, CurContext, StaticAssertLoc,
+                                        AssertExpr, AssertMessage, RParenLoc);
+
+  CurContext->addDecl(Decl);
+  return Decl;
+}
+
+/// \brief Perform semantic analysis of the given friend type declaration.
+///
+/// \returns A friend declaration that.
+FriendDecl *Sema::CheckFriendTypeDecl(SourceLocation Loc,
+                                      SourceLocation FriendLoc,
+                                      TypeSourceInfo *TSInfo) {
+  assert(TSInfo && "NULL TypeSourceInfo for friend type declaration");
+  
+  QualType T = TSInfo->getType();
+  SourceRange TypeRange = TSInfo->getTypeLoc().getLocalSourceRange();
+  
+  // C++03 [class.friend]p2:
+  //   An elaborated-type-specifier shall be used in a friend declaration
+  //   for a class.*
+  //
+  //   * The class-key of the elaborated-type-specifier is required.
+  if (!ActiveTemplateInstantiations.empty()) {
+    // Do not complain about the form of friend template types during
+    // template instantiation; we will already have complained when the
+    // template was declared.
+  } else if (!T->isElaboratedTypeSpecifier()) {
+    // If we evaluated the type to a record type, suggest putting
+    // a tag in front.
+    if (const RecordType *RT = T->getAs<RecordType>()) {
+      RecordDecl *RD = RT->getDecl();
+      
+      std::string InsertionText = std::string(" ") + RD->getKindName();
+      
+      Diag(TypeRange.getBegin(),
+           getLangOpts().CPlusPlus0x ?
+             diag::warn_cxx98_compat_unelaborated_friend_type :
+             diag::ext_unelaborated_friend_type)
+        << (unsigned) RD->getTagKind()
+        << T
+        << FixItHint::CreateInsertion(PP.getLocForEndOfToken(FriendLoc),
+                                      InsertionText);
+    } else {
+      Diag(FriendLoc,
+           getLangOpts().CPlusPlus0x ?
+             diag::warn_cxx98_compat_nonclass_type_friend :
+             diag::ext_nonclass_type_friend)
+        << T
+        << SourceRange(FriendLoc, TypeRange.getEnd());
+    }
+  } else if (T->getAs<EnumType>()) {
+    Diag(FriendLoc,
+         getLangOpts().CPlusPlus0x ?
+           diag::warn_cxx98_compat_enum_friend :
+           diag::ext_enum_friend)
+      << T
+      << SourceRange(FriendLoc, TypeRange.getEnd());
+  }
+  
+  // C++0x [class.friend]p3:
+  //   If the type specifier in a friend declaration designates a (possibly
+  //   cv-qualified) class type, that class is declared as a friend; otherwise, 
+  //   the friend declaration is ignored.
+  
+  // FIXME: C++0x has some syntactic restrictions on friend type declarations
+  // in [class.friend]p3 that we do not implement.
+  
+  return FriendDecl::Create(Context, CurContext, Loc, TSInfo, FriendLoc);
+}
+
+/// Handle a friend tag declaration where the scope specifier was
+/// templated.
+Decl *Sema::ActOnTemplatedFriendTag(Scope *S, SourceLocation FriendLoc,
+                                    unsigned TagSpec, SourceLocation TagLoc,
+                                    CXXScopeSpec &SS,
+                                    IdentifierInfo *Name, SourceLocation NameLoc,
+                                    AttributeList *Attr,
+                                    MultiTemplateParamsArg TempParamLists) {
+  TagTypeKind Kind = TypeWithKeyword::getTagTypeKindForTypeSpec(TagSpec);
+
+  bool isExplicitSpecialization = false;
+  bool Invalid = false;
+
+  if (TemplateParameterList *TemplateParams
+        = MatchTemplateParametersToScopeSpecifier(TagLoc, NameLoc, SS,
+                                                  TempParamLists.get(),
+                                                  TempParamLists.size(),
+                                                  /*friend*/ true,
+                                                  isExplicitSpecialization,
+                                                  Invalid)) {
+    if (TemplateParams->size() > 0) {
+      // This is a declaration of a class template.
+      if (Invalid)
+        return 0;
+
+      return CheckClassTemplate(S, TagSpec, TUK_Friend, TagLoc,
+                                SS, Name, NameLoc, Attr,
+                                TemplateParams, AS_public,
+                                /*ModulePrivateLoc=*/SourceLocation(),
+                                TempParamLists.size() - 1,
+                   (TemplateParameterList**) TempParamLists.release()).take();
+    } else {
+      // The "template<>" header is extraneous.
+      Diag(TemplateParams->getTemplateLoc(), diag::err_template_tag_noparams)
+        << TypeWithKeyword::getTagTypeKindName(Kind) << Name;
+      isExplicitSpecialization = true;
+    }
+  }
+
+  if (Invalid) return 0;
+
+  bool isAllExplicitSpecializations = true;
+  for (unsigned I = TempParamLists.size(); I-- > 0; ) {
+    if (TempParamLists.get()[I]->size()) {
+      isAllExplicitSpecializations = false;
+      break;
+    }
+  }
+
+  // FIXME: don't ignore attributes.
+
+  // If it's explicit specializations all the way down, just forget
+  // about the template header and build an appropriate non-templated
+  // friend.  TODO: for source fidelity, remember the headers.
+  if (isAllExplicitSpecializations) {
+    if (SS.isEmpty()) {
+      bool Owned = false;
+      bool IsDependent = false;
+      return ActOnTag(S, TagSpec, TUK_Friend, TagLoc, SS, Name, NameLoc,
+                      Attr, AS_public, 
+                      /*ModulePrivateLoc=*/SourceLocation(),
+                      MultiTemplateParamsArg(), Owned, IsDependent, 
+                      /*ScopedEnumKWLoc=*/SourceLocation(),
+                      /*ScopedEnumUsesClassTag=*/false,
+                      /*UnderlyingType=*/TypeResult());          
+    }
+    
+    NestedNameSpecifierLoc QualifierLoc = SS.getWithLocInContext(Context);
+    ElaboratedTypeKeyword Keyword
+      = TypeWithKeyword::getKeywordForTagTypeKind(Kind);
+    QualType T = CheckTypenameType(Keyword, TagLoc, QualifierLoc,
+                                   *Name, NameLoc);
+    if (T.isNull())
+      return 0;
+
+    TypeSourceInfo *TSI = Context.CreateTypeSourceInfo(T);
+    if (isa<DependentNameType>(T)) {
+      DependentNameTypeLoc TL = cast<DependentNameTypeLoc>(TSI->getTypeLoc());
+      TL.setElaboratedKeywordLoc(TagLoc);
+      TL.setQualifierLoc(QualifierLoc);
+      TL.setNameLoc(NameLoc);
+    } else {
+      ElaboratedTypeLoc TL = cast<ElaboratedTypeLoc>(TSI->getTypeLoc());
+      TL.setElaboratedKeywordLoc(TagLoc);
+      TL.setQualifierLoc(QualifierLoc);
+      cast<TypeSpecTypeLoc>(TL.getNamedTypeLoc()).setNameLoc(NameLoc);
+    }
+
+    FriendDecl *Friend = FriendDecl::Create(Context, CurContext, NameLoc,
+                                            TSI, FriendLoc);
+    Friend->setAccess(AS_public);
+    CurContext->addDecl(Friend);
+    return Friend;
+  }
+  
+  assert(SS.isNotEmpty() && "valid templated tag with no SS and no direct?");
+  
+
+
+  // Handle the case of a templated-scope friend class.  e.g.
+  //   template <class T> class A<T>::B;
+  // FIXME: we don't support these right now.
+  ElaboratedTypeKeyword ETK = TypeWithKeyword::getKeywordForTagTypeKind(Kind);
+  QualType T = Context.getDependentNameType(ETK, SS.getScopeRep(), Name);
+  TypeSourceInfo *TSI = Context.CreateTypeSourceInfo(T);
+  DependentNameTypeLoc TL = cast<DependentNameTypeLoc>(TSI->getTypeLoc());
+  TL.setElaboratedKeywordLoc(TagLoc);
+  TL.setQualifierLoc(SS.getWithLocInContext(Context));
+  TL.setNameLoc(NameLoc);
+
+  FriendDecl *Friend = FriendDecl::Create(Context, CurContext, NameLoc,
+                                          TSI, FriendLoc);
+  Friend->setAccess(AS_public);
+  Friend->setUnsupportedFriend(true);
+  CurContext->addDecl(Friend);
+  return Friend;
+}
+
+
+/// Handle a friend type declaration.  This works in tandem with
+/// ActOnTag.
+///
+/// Notes on friend class templates:
+///
+/// We generally treat friend class declarations as if they were
+/// declaring a class.  So, for example, the elaborated type specifier
+/// in a friend declaration is required to obey the restrictions of a
+/// class-head (i.e. no typedefs in the scope chain), template
+/// parameters are required to match up with simple template-ids, &c.
+/// However, unlike when declaring a template specialization, it's
+/// okay to refer to a template specialization without an empty
+/// template parameter declaration, e.g.
+///   friend class A<T>::B<unsigned>;
+/// We permit this as a special case; if there are any template
+/// parameters present at all, require proper matching, i.e.
+///   template <> template <class T> friend class A<int>::B;
+Decl *Sema::ActOnFriendTypeDecl(Scope *S, const DeclSpec &DS,
+                                MultiTemplateParamsArg TempParams) {
+  SourceLocation Loc = DS.getLocStart();
+
+  assert(DS.isFriendSpecified());
+  assert(DS.getStorageClassSpec() == DeclSpec::SCS_unspecified);
+
+  // Try to convert the decl specifier to a type.  This works for
+  // friend templates because ActOnTag never produces a ClassTemplateDecl
+  // for a TUK_Friend.
+  Declarator TheDeclarator(DS, Declarator::MemberContext);
+  TypeSourceInfo *TSI = GetTypeForDeclarator(TheDeclarator, S);
+  QualType T = TSI->getType();
+  if (TheDeclarator.isInvalidType())
+    return 0;
+
+  if (DiagnoseUnexpandedParameterPack(Loc, TSI, UPPC_FriendDeclaration))
+    return 0;
+
+  // This is definitely an error in C++98.  It's probably meant to
+  // be forbidden in C++0x, too, but the specification is just
+  // poorly written.
+  //
+  // The problem is with declarations like the following:
+  //   template <T> friend A<T>::foo;
+  // where deciding whether a class C is a friend or not now hinges
+  // on whether there exists an instantiation of A that causes
+  // 'foo' to equal C.  There are restrictions on class-heads
+  // (which we declare (by fiat) elaborated friend declarations to
+  // be) that makes this tractable.
+  //
+  // FIXME: handle "template <> friend class A<T>;", which
+  // is possibly well-formed?  Who even knows?
+  if (TempParams.size() && !T->isElaboratedTypeSpecifier()) {
+    Diag(Loc, diag::err_tagless_friend_type_template)
+      << DS.getSourceRange();
+    return 0;
+  }
+  
+  // C++98 [class.friend]p1: A friend of a class is a function
+  //   or class that is not a member of the class . . .
+  // This is fixed in DR77, which just barely didn't make the C++03
+  // deadline.  It's also a very silly restriction that seriously
+  // affects inner classes and which nobody else seems to implement;
+  // thus we never diagnose it, not even in -pedantic.
+  //
+  // But note that we could warn about it: it's always useless to
+  // friend one of your own members (it's not, however, worthless to
+  // friend a member of an arbitrary specialization of your template).
+
+  Decl *D;
+  if (unsigned NumTempParamLists = TempParams.size())
+    D = FriendTemplateDecl::Create(Context, CurContext, Loc,
+                                   NumTempParamLists,
+                                   TempParams.release(),
+                                   TSI,
+                                   DS.getFriendSpecLoc());
+  else
+    D = CheckFriendTypeDecl(Loc, DS.getFriendSpecLoc(), TSI);
+  
+  if (!D)
+    return 0;
+  
+  D->setAccess(AS_public);
+  CurContext->addDecl(D);
+
+  return D;
+}
+
+Decl *Sema::ActOnFriendFunctionDecl(Scope *S, Declarator &D,
+                                    MultiTemplateParamsArg TemplateParams) {
+  const DeclSpec &DS = D.getDeclSpec();
+
+  assert(DS.isFriendSpecified());
+  assert(DS.getStorageClassSpec() == DeclSpec::SCS_unspecified);
+
+  SourceLocation Loc = D.getIdentifierLoc();
+  TypeSourceInfo *TInfo = GetTypeForDeclarator(D, S);
+
+  // C++ [class.friend]p1
+  //   A friend of a class is a function or class....
+  // Note that this sees through typedefs, which is intended.
+  // It *doesn't* see through dependent types, which is correct
+  // according to [temp.arg.type]p3:
+  //   If a declaration acquires a function type through a
+  //   type dependent on a template-parameter and this causes
+  //   a declaration that does not use the syntactic form of a
+  //   function declarator to have a function type, the program
+  //   is ill-formed.
+  if (!TInfo->getType()->isFunctionType()) {
+    Diag(Loc, diag::err_unexpected_friend);
+
+    // It might be worthwhile to try to recover by creating an
+    // appropriate declaration.
+    return 0;
+  }
+
+  // C++ [namespace.memdef]p3
+  //  - If a friend declaration in a non-local class first declares a
+  //    class or function, the friend class or function is a member
+  //    of the innermost enclosing namespace.
+  //  - The name of the friend is not found by simple name lookup
+  //    until a matching declaration is provided in that namespace
+  //    scope (either before or after the class declaration granting
+  //    friendship).
+  //  - If a friend function is called, its name may be found by the
+  //    name lookup that considers functions from namespaces and
+  //    classes associated with the types of the function arguments.
+  //  - When looking for a prior declaration of a class or a function
+  //    declared as a friend, scopes outside the innermost enclosing
+  //    namespace scope are not considered.
+
+  CXXScopeSpec &SS = D.getCXXScopeSpec();
+  DeclarationNameInfo NameInfo = GetNameForDeclarator(D);
+  DeclarationName Name = NameInfo.getName();
+  assert(Name);
+
+  // Check for unexpanded parameter packs.
+  if (DiagnoseUnexpandedParameterPack(Loc, TInfo, UPPC_FriendDeclaration) ||
+      DiagnoseUnexpandedParameterPack(NameInfo, UPPC_FriendDeclaration) ||
+      DiagnoseUnexpandedParameterPack(SS, UPPC_FriendDeclaration))
+    return 0;
+
+  // The context we found the declaration in, or in which we should
+  // create the declaration.
+  DeclContext *DC;
+  Scope *DCScope = S;
+  LookupResult Previous(*this, NameInfo, LookupOrdinaryName,
+                        ForRedeclaration);
+
+  // FIXME: there are different rules in local classes
+
+  // There are four cases here.
+  //   - There's no scope specifier, in which case we just go to the
+  //     appropriate scope and look for a function or function template
+  //     there as appropriate.
+  // Recover from invalid scope qualifiers as if they just weren't there.
+  if (SS.isInvalid() || !SS.isSet()) {
+    // C++0x [namespace.memdef]p3:
+    //   If the name in a friend declaration is neither qualified nor
+    //   a template-id and the declaration is a function or an
+    //   elaborated-type-specifier, the lookup to determine whether
+    //   the entity has been previously declared shall not consider
+    //   any scopes outside the innermost enclosing namespace.
+    // C++0x [class.friend]p11:
+    //   If a friend declaration appears in a local class and the name
+    //   specified is an unqualified name, a prior declaration is
+    //   looked up without considering scopes that are outside the
+    //   innermost enclosing non-class scope. For a friend function
+    //   declaration, if there is no prior declaration, the program is
+    //   ill-formed.
+    bool isLocal = cast<CXXRecordDecl>(CurContext)->isLocalClass();
+    bool isTemplateId = D.getName().getKind() == UnqualifiedId::IK_TemplateId;
+
+    // Find the appropriate context according to the above.
+    DC = CurContext;
+    while (true) {
+      // Skip class contexts.  If someone can cite chapter and verse
+      // for this behavior, that would be nice --- it's what GCC and
+      // EDG do, and it seems like a reasonable intent, but the spec
+      // really only says that checks for unqualified existing
+      // declarations should stop at the nearest enclosing namespace,
+      // not that they should only consider the nearest enclosing
+      // namespace.
+      while (DC->isRecord() || DC->isTransparentContext()) 
+        DC = DC->getParent();
+
+      LookupQualifiedName(Previous, DC);
+
+      // TODO: decide what we think about using declarations.
+      if (isLocal || !Previous.empty())
+        break;
+
+      if (isTemplateId) {
+        if (isa<TranslationUnitDecl>(DC)) break;
+      } else {
+        if (DC->isFileContext()) break;
+      }
+      DC = DC->getParent();
+    }
+
+    // C++ [class.friend]p1: A friend of a class is a function or
+    //   class that is not a member of the class . . .
+    // C++11 changes this for both friend types and functions.
+    // Most C++ 98 compilers do seem to give an error here, so
+    // we do, too.
+    if (!Previous.empty() && DC->Equals(CurContext))
+      Diag(DS.getFriendSpecLoc(),
+           getLangOpts().CPlusPlus0x ?
+             diag::warn_cxx98_compat_friend_is_member :
+             diag::err_friend_is_member);
+
+    DCScope = getScopeForDeclContext(S, DC);
+    
+    // C++ [class.friend]p6:
+    //   A function can be defined in a friend declaration of a class if and 
+    //   only if the class is a non-local class (9.8), the function name is
+    //   unqualified, and the function has namespace scope.
+    if (isLocal && D.isFunctionDefinition()) {
+      Diag(NameInfo.getBeginLoc(), diag::err_friend_def_in_local_class);
+    }
+    
+  //   - There's a non-dependent scope specifier, in which case we
+  //     compute it and do a previous lookup there for a function
+  //     or function template.
+  } else if (!SS.getScopeRep()->isDependent()) {
+    DC = computeDeclContext(SS);
+    if (!DC) return 0;
+
+    if (RequireCompleteDeclContext(SS, DC)) return 0;
+
+    LookupQualifiedName(Previous, DC);
+
+    // Ignore things found implicitly in the wrong scope.
+    // TODO: better diagnostics for this case.  Suggesting the right
+    // qualified scope would be nice...
+    LookupResult::Filter F = Previous.makeFilter();
+    while (F.hasNext()) {
+      NamedDecl *D = F.next();
+      if (!DC->InEnclosingNamespaceSetOf(
+              D->getDeclContext()->getRedeclContext()))
+        F.erase();
+    }
+    F.done();
+
+    if (Previous.empty()) {
+      D.setInvalidType();
+      Diag(Loc, diag::err_qualified_friend_not_found)
+          << Name << TInfo->getType();
+      return 0;
+    }
+
+    // C++ [class.friend]p1: A friend of a class is a function or
+    //   class that is not a member of the class . . .
+    if (DC->Equals(CurContext))
+      Diag(DS.getFriendSpecLoc(),
+           getLangOpts().CPlusPlus0x ?
+             diag::warn_cxx98_compat_friend_is_member :
+             diag::err_friend_is_member);
+    
+    if (D.isFunctionDefinition()) {
+      // C++ [class.friend]p6:
+      //   A function can be defined in a friend declaration of a class if and 
+      //   only if the class is a non-local class (9.8), the function name is
+      //   unqualified, and the function has namespace scope.
+      SemaDiagnosticBuilder DB
+        = Diag(SS.getRange().getBegin(), diag::err_qualified_friend_def);
+      
+      DB << SS.getScopeRep();
+      if (DC->isFileContext())
+        DB << FixItHint::CreateRemoval(SS.getRange());
+      SS.clear();
+    }
+
+  //   - There's a scope specifier that does not match any template
+  //     parameter lists, in which case we use some arbitrary context,
+  //     create a method or method template, and wait for instantiation.
+  //   - There's a scope specifier that does match some template
+  //     parameter lists, which we don't handle right now.
+  } else {
+    if (D.isFunctionDefinition()) {
+      // C++ [class.friend]p6:
+      //   A function can be defined in a friend declaration of a class if and 
+      //   only if the class is a non-local class (9.8), the function name is
+      //   unqualified, and the function has namespace scope.
+      Diag(SS.getRange().getBegin(), diag::err_qualified_friend_def)
+        << SS.getScopeRep();
+    }
+    
+    DC = CurContext;
+    assert(isa<CXXRecordDecl>(DC) && "friend declaration not in class?");
+  }
+  
+  if (!DC->isRecord()) {
+    // This implies that it has to be an operator or function.
+    if (D.getName().getKind() == UnqualifiedId::IK_ConstructorName ||
+        D.getName().getKind() == UnqualifiedId::IK_DestructorName ||
+        D.getName().getKind() == UnqualifiedId::IK_ConversionFunctionId) {
+      Diag(Loc, diag::err_introducing_special_friend) <<
+        (D.getName().getKind() == UnqualifiedId::IK_ConstructorName ? 0 :
+         D.getName().getKind() == UnqualifiedId::IK_DestructorName ? 1 : 2);
+      return 0;
+    }
+  }
+
+  // FIXME: This is an egregious hack to cope with cases where the scope stack
+  // does not contain the declaration context, i.e., in an out-of-line 
+  // definition of a class.
+  Scope FakeDCScope(S, Scope::DeclScope, Diags);
+  if (!DCScope) {
+    FakeDCScope.setEntity(DC);
+    DCScope = &FakeDCScope;
+  }
+  
+  bool AddToScope = true;
+  NamedDecl *ND = ActOnFunctionDeclarator(DCScope, D, DC, TInfo, Previous,
+                                          move(TemplateParams), AddToScope);
+  if (!ND) return 0;
+
+  assert(ND->getDeclContext() == DC);
+  assert(ND->getLexicalDeclContext() == CurContext);
+
+  // Add the function declaration to the appropriate lookup tables,
+  // adjusting the redeclarations list as necessary.  We don't
+  // want to do this yet if the friending class is dependent.
+  //
+  // Also update the scope-based lookup if the target context's
+  // lookup context is in lexical scope.
+  if (!CurContext->isDependentContext()) {
+    DC = DC->getRedeclContext();
+    DC->makeDeclVisibleInContext(ND);
+    if (Scope *EnclosingScope = getScopeForDeclContext(S, DC))
+      PushOnScopeChains(ND, EnclosingScope, /*AddToContext=*/ false);
+  }
+
+  FriendDecl *FrD = FriendDecl::Create(Context, CurContext,
+                                       D.getIdentifierLoc(), ND,
+                                       DS.getFriendSpecLoc());
+  FrD->setAccess(AS_public);
+  CurContext->addDecl(FrD);
+
+  if (ND->isInvalidDecl())
+    FrD->setInvalidDecl();
+  else {
+    FunctionDecl *FD;
+    if (FunctionTemplateDecl *FTD = dyn_cast<FunctionTemplateDecl>(ND))
+      FD = FTD->getTemplatedDecl();
+    else
+      FD = cast<FunctionDecl>(ND);
+
+    // Mark templated-scope function declarations as unsupported.
+    if (FD->getNumTemplateParameterLists())
+      FrD->setUnsupportedFriend(true);
+  }
+
+  return ND;
+}
+
+void Sema::SetDeclDeleted(Decl *Dcl, SourceLocation DelLoc) {
+  AdjustDeclIfTemplate(Dcl);
+
+  FunctionDecl *Fn = dyn_cast<FunctionDecl>(Dcl);
+  if (!Fn) {
+    Diag(DelLoc, diag::err_deleted_non_function);
+    return;
+  }
+  if (const FunctionDecl *Prev = Fn->getPreviousDecl()) {
+    Diag(DelLoc, diag::err_deleted_decl_not_first);
+    Diag(Prev->getLocation(), diag::note_previous_declaration);
+    // If the declaration wasn't the first, we delete the function anyway for
+    // recovery.
+  }
+  Fn->setDeletedAsWritten();
+
+  CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(Dcl);
+  if (!MD)
+    return;
+
+  // A deleted special member function is trivial if the corresponding
+  // implicitly-declared function would have been.
+  switch (getSpecialMember(MD)) {
+  case CXXInvalid:
+    break;
+  case CXXDefaultConstructor:
+    MD->setTrivial(MD->getParent()->hasTrivialDefaultConstructor());
+    break;
+  case CXXCopyConstructor:
+    MD->setTrivial(MD->getParent()->hasTrivialCopyConstructor());
+    break;
+  case CXXMoveConstructor:
+    MD->setTrivial(MD->getParent()->hasTrivialMoveConstructor());
+    break;
+  case CXXCopyAssignment:
+    MD->setTrivial(MD->getParent()->hasTrivialCopyAssignment());
+    break;
+  case CXXMoveAssignment:
+    MD->setTrivial(MD->getParent()->hasTrivialMoveAssignment());
+    break;
+  case CXXDestructor:
+    MD->setTrivial(MD->getParent()->hasTrivialDestructor());
+    break;
+  }
+}
+
+void Sema::SetDeclDefaulted(Decl *Dcl, SourceLocation DefaultLoc) {
+  CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(Dcl);
+
+  if (MD) {
+    if (MD->getParent()->isDependentType()) {
+      MD->setDefaulted();
+      MD->setExplicitlyDefaulted();
+      return;
+    }
+
+    CXXSpecialMember Member = getSpecialMember(MD);
+    if (Member == CXXInvalid) {
+      Diag(DefaultLoc, diag::err_default_special_members);
+      return;
+    }
+
+    MD->setDefaulted();
+    MD->setExplicitlyDefaulted();
+
+    // If this definition appears within the record, do the checking when
+    // the record is complete.
+    const FunctionDecl *Primary = MD;
+    if (MD->getTemplatedKind() != FunctionDecl::TK_NonTemplate)
+      // Find the uninstantiated declaration that actually had the '= default'
+      // on it.
+      MD->getTemplateInstantiationPattern()->isDefined(Primary);
+
+    if (Primary == Primary->getCanonicalDecl())
+      return;
+
+    switch (Member) {
+    case CXXDefaultConstructor: {
+      CXXConstructorDecl *CD = cast<CXXConstructorDecl>(MD);
+      CheckExplicitlyDefaultedDefaultConstructor(CD);
+      if (!CD->isInvalidDecl())
+        DefineImplicitDefaultConstructor(DefaultLoc, CD);
+      break;
+    }
+
+    case CXXCopyConstructor: {
+      CXXConstructorDecl *CD = cast<CXXConstructorDecl>(MD);
+      CheckExplicitlyDefaultedCopyConstructor(CD);
+      if (!CD->isInvalidDecl())
+        DefineImplicitCopyConstructor(DefaultLoc, CD);
+      break;
+    }
+
+    case CXXCopyAssignment: {
+      CheckExplicitlyDefaultedCopyAssignment(MD);
+      if (!MD->isInvalidDecl())
+        DefineImplicitCopyAssignment(DefaultLoc, MD);
+      break;
+    }
+
+    case CXXDestructor: {
+      CXXDestructorDecl *DD = cast<CXXDestructorDecl>(MD);
+      CheckExplicitlyDefaultedDestructor(DD);
+      if (!DD->isInvalidDecl())
+        DefineImplicitDestructor(DefaultLoc, DD);
+      break;
+    }
+
+    case CXXMoveConstructor: {
+      CXXConstructorDecl *CD = cast<CXXConstructorDecl>(MD);
+      CheckExplicitlyDefaultedMoveConstructor(CD);
+      if (!CD->isInvalidDecl())
+        DefineImplicitMoveConstructor(DefaultLoc, CD);
+      break;
+    }
+
+    case CXXMoveAssignment: {
+      CheckExplicitlyDefaultedMoveAssignment(MD);
+      if (!MD->isInvalidDecl())
+        DefineImplicitMoveAssignment(DefaultLoc, MD);
+      break;
+    }
+
+    case CXXInvalid:
+      llvm_unreachable("Invalid special member.");
+    }
+  } else {
+    Diag(DefaultLoc, diag::err_default_special_members);
+  }
+}
+
+static void SearchForReturnInStmt(Sema &Self, Stmt *S) {
+  for (Stmt::child_range CI = S->children(); CI; ++CI) {
+    Stmt *SubStmt = *CI;
+    if (!SubStmt)
+      continue;
+    if (isa<ReturnStmt>(SubStmt))
+      Self.Diag(SubStmt->getLocStart(),
+           diag::err_return_in_constructor_handler);
+    if (!isa<Expr>(SubStmt))
+      SearchForReturnInStmt(Self, SubStmt);
+  }
+}
+
+void Sema::DiagnoseReturnInConstructorExceptionHandler(CXXTryStmt *TryBlock) {
+  for (unsigned I = 0, E = TryBlock->getNumHandlers(); I != E; ++I) {
+    CXXCatchStmt *Handler = TryBlock->getHandler(I);
+    SearchForReturnInStmt(*this, Handler);
+  }
+}
+
+bool Sema::CheckOverridingFunctionReturnType(const CXXMethodDecl *New,
+                                             const CXXMethodDecl *Old) {
+  QualType NewTy = New->getType()->getAs<FunctionType>()->getResultType();
+  QualType OldTy = Old->getType()->getAs<FunctionType>()->getResultType();
+
+  if (Context.hasSameType(NewTy, OldTy) ||
+      NewTy->isDependentType() || OldTy->isDependentType())
+    return false;
+
+  // Check if the return types are covariant
+  QualType NewClassTy, OldClassTy;
+
+  /// Both types must be pointers or references to classes.
+  if (const PointerType *NewPT = NewTy->getAs<PointerType>()) {
+    if (const PointerType *OldPT = OldTy->getAs<PointerType>()) {
+      NewClassTy = NewPT->getPointeeType();
+      OldClassTy = OldPT->getPointeeType();
+    }
+  } else if (const ReferenceType *NewRT = NewTy->getAs<ReferenceType>()) {
+    if (const ReferenceType *OldRT = OldTy->getAs<ReferenceType>()) {
+      if (NewRT->getTypeClass() == OldRT->getTypeClass()) {
+        NewClassTy = NewRT->getPointeeType();
+        OldClassTy = OldRT->getPointeeType();
+      }
+    }
+  }
+
+  // The return types aren't either both pointers or references to a class type.
+  if (NewClassTy.isNull()) {
+    Diag(New->getLocation(),
+         diag::err_different_return_type_for_overriding_virtual_function)
+      << New->getDeclName() << NewTy << OldTy;
+    Diag(Old->getLocation(), diag::note_overridden_virtual_function);
+
+    return true;
+  }
+
+  // C++ [class.virtual]p6:
+  //   If the return type of D::f differs from the return type of B::f, the 
+  //   class type in the return type of D::f shall be complete at the point of
+  //   declaration of D::f or shall be the class type D.
+  if (const RecordType *RT = NewClassTy->getAs<RecordType>()) {
+    if (!RT->isBeingDefined() &&
+        RequireCompleteType(New->getLocation(), NewClassTy, 
+                            PDiag(diag::err_covariant_return_incomplete)
+                              << New->getDeclName()))
+    return true;
+  }
+
+  if (!Context.hasSameUnqualifiedType(NewClassTy, OldClassTy)) {
+    // Check if the new class derives from the old class.
+    if (!IsDerivedFrom(NewClassTy, OldClassTy)) {
+      Diag(New->getLocation(),
+           diag::err_covariant_return_not_derived)
+      << New->getDeclName() << NewTy << OldTy;
+      Diag(Old->getLocation(), diag::note_overridden_virtual_function);
+      return true;
+    }
+
+    // Check if we the conversion from derived to base is valid.
+    if (CheckDerivedToBaseConversion(NewClassTy, OldClassTy,
+                    diag::err_covariant_return_inaccessible_base,
+                    diag::err_covariant_return_ambiguous_derived_to_base_conv,
+                    // FIXME: Should this point to the return type?
+                    New->getLocation(), SourceRange(), New->getDeclName(), 0)) {
+      // FIXME: this note won't trigger for delayed access control
+      // diagnostics, and it's impossible to get an undelayed error
+      // here from access control during the original parse because
+      // the ParsingDeclSpec/ParsingDeclarator are still in scope.
+      Diag(Old->getLocation(), diag::note_overridden_virtual_function);
+      return true;
+    }
+  }
+
+  // The qualifiers of the return types must be the same.
+  if (NewTy.getLocalCVRQualifiers() != OldTy.getLocalCVRQualifiers()) {
+    Diag(New->getLocation(),
+         diag::err_covariant_return_type_different_qualifications)
+    << New->getDeclName() << NewTy << OldTy;
+    Diag(Old->getLocation(), diag::note_overridden_virtual_function);
+    return true;
+  };
+
+
+  // The new class type must have the same or less qualifiers as the old type.
+  if (NewClassTy.isMoreQualifiedThan(OldClassTy)) {
+    Diag(New->getLocation(),
+         diag::err_covariant_return_type_class_type_more_qualified)
+    << New->getDeclName() << NewTy << OldTy;
+    Diag(Old->getLocation(), diag::note_overridden_virtual_function);
+    return true;
+  };
+
+  return false;
+}
+
+/// \brief Mark the given method pure.
+///
+/// \param Method the method to be marked pure.
+///
+/// \param InitRange the source range that covers the "0" initializer.
+bool Sema::CheckPureMethod(CXXMethodDecl *Method, SourceRange InitRange) {
+  SourceLocation EndLoc = InitRange.getEnd();
+  if (EndLoc.isValid())
+    Method->setRangeEnd(EndLoc);
+
+  if (Method->isVirtual() || Method->getParent()->isDependentContext()) {
+    Method->setPure();
+    return false;
+  }
+
+  if (!Method->isInvalidDecl())
+    Diag(Method->getLocation(), diag::err_non_virtual_pure)
+      << Method->getDeclName() << InitRange;
+  return true;
+}
+
+/// \brief Determine whether the given declaration is a static data member.
+static bool isStaticDataMember(Decl *D) {
+  VarDecl *Var = dyn_cast_or_null<VarDecl>(D);
+  if (!Var)
+    return false;
+  
+  return Var->isStaticDataMember();
+}
+/// ActOnCXXEnterDeclInitializer - Invoked when we are about to parse
+/// an initializer for the out-of-line declaration 'Dcl'.  The scope
+/// is a fresh scope pushed for just this purpose.
+///
+/// After this method is called, according to [C++ 3.4.1p13], if 'Dcl' is a
+/// static data member of class X, names should be looked up in the scope of
+/// class X.
+void Sema::ActOnCXXEnterDeclInitializer(Scope *S, Decl *D) {
+  // If there is no declaration, there was an error parsing it.
+  if (D == 0 || D->isInvalidDecl()) return;
+
+  // We should only get called for declarations with scope specifiers, like:
+  //   int foo::bar;
+  assert(D->isOutOfLine());
+  EnterDeclaratorContext(S, D->getDeclContext());
+  
+  // If we are parsing the initializer for a static data member, push a
+  // new expression evaluation context that is associated with this static
+  // data member.
+  if (isStaticDataMember(D))
+    PushExpressionEvaluationContext(PotentiallyEvaluated, D);
+}
+
+/// ActOnCXXExitDeclInitializer - Invoked after we are finished parsing an
+/// initializer for the out-of-line declaration 'D'.
+void Sema::ActOnCXXExitDeclInitializer(Scope *S, Decl *D) {
+  // If there is no declaration, there was an error parsing it.
+  if (D == 0 || D->isInvalidDecl()) return;
+
+  if (isStaticDataMember(D))
+    PopExpressionEvaluationContext();  
+
+  assert(D->isOutOfLine());
+  ExitDeclaratorContext(S);
+}
+
+/// ActOnCXXConditionDeclarationExpr - Parsed a condition declaration of a
+/// C++ if/switch/while/for statement.
+/// e.g: "if (int x = f()) {...}"
+DeclResult Sema::ActOnCXXConditionDeclaration(Scope *S, Declarator &D) {
+  // C++ 6.4p2:
+  // The declarator shall not specify a function or an array.
+  // The type-specifier-seq shall not contain typedef and shall not declare a
+  // new class or enumeration.
+  assert(D.getDeclSpec().getStorageClassSpec() != DeclSpec::SCS_typedef &&
+         "Parser allowed 'typedef' as storage class of condition decl.");
+
+  Decl *Dcl = ActOnDeclarator(S, D);
+  if (!Dcl)
+    return true;
+
+  if (isa<FunctionDecl>(Dcl)) { // The declarator shall not specify a function.
+    Diag(Dcl->getLocation(), diag::err_invalid_use_of_function_type)
+      << D.getSourceRange();
+    return true;
+  }
+
+  return Dcl;
+}
+
+void Sema::LoadExternalVTableUses() {
+  if (!ExternalSource)
+    return;
+  
+  SmallVector<ExternalVTableUse, 4> VTables;
+  ExternalSource->ReadUsedVTables(VTables);
+  SmallVector<VTableUse, 4> NewUses;
+  for (unsigned I = 0, N = VTables.size(); I != N; ++I) {
+    llvm::DenseMap<CXXRecordDecl *, bool>::iterator Pos
+      = VTablesUsed.find(VTables[I].Record);
+    // Even if a definition wasn't required before, it may be required now.
+    if (Pos != VTablesUsed.end()) {
+      if (!Pos->second && VTables[I].DefinitionRequired)
+        Pos->second = true;
+      continue;
+    }
+    
+    VTablesUsed[VTables[I].Record] = VTables[I].DefinitionRequired;
+    NewUses.push_back(VTableUse(VTables[I].Record, VTables[I].Location));
+  }
+  
+  VTableUses.insert(VTableUses.begin(), NewUses.begin(), NewUses.end());
+}
+
+void Sema::MarkVTableUsed(SourceLocation Loc, CXXRecordDecl *Class,
+                          bool DefinitionRequired) {
+  // Ignore any vtable uses in unevaluated operands or for classes that do
+  // not have a vtable.
+  if (!Class->isDynamicClass() || Class->isDependentContext() ||
+      CurContext->isDependentContext() ||
+      ExprEvalContexts.back().Context == Unevaluated)
+    return;
+
+  // Try to insert this class into the map.
+  LoadExternalVTableUses();
+  Class = cast<CXXRecordDecl>(Class->getCanonicalDecl());
+  std::pair<llvm::DenseMap<CXXRecordDecl *, bool>::iterator, bool>
+    Pos = VTablesUsed.insert(std::make_pair(Class, DefinitionRequired));
+  if (!Pos.second) {
+    // If we already had an entry, check to see if we are promoting this vtable
+    // to required a definition. If so, we need to reappend to the VTableUses
+    // list, since we may have already processed the first entry.
+    if (DefinitionRequired && !Pos.first->second) {
+      Pos.first->second = true;
+    } else {
+      // Otherwise, we can early exit.
+      return;
+    }
+  }
+
+  // Local classes need to have their virtual members marked
+  // immediately. For all other classes, we mark their virtual members
+  // at the end of the translation unit.
+  if (Class->isLocalClass())
+    MarkVirtualMembersReferenced(Loc, Class);
+  else
+    VTableUses.push_back(std::make_pair(Class, Loc));
+}
+
+bool Sema::DefineUsedVTables() {
+  LoadExternalVTableUses();
+  if (VTableUses.empty())
+    return false;
+
+  // Note: The VTableUses vector could grow as a result of marking
+  // the members of a class as "used", so we check the size each
+  // time through the loop and prefer indices (with are stable) to
+  // iterators (which are not).
+  bool DefinedAnything = false;
+  for (unsigned I = 0; I != VTableUses.size(); ++I) {
+    CXXRecordDecl *Class = VTableUses[I].first->getDefinition();
+    if (!Class)
+      continue;
+
+    SourceLocation Loc = VTableUses[I].second;
+
+    // If this class has a key function, but that key function is
+    // defined in another translation unit, we don't need to emit the
+    // vtable even though we're using it.
+    const CXXMethodDecl *KeyFunction = Context.getKeyFunction(Class);
+    if (KeyFunction && !KeyFunction->hasBody()) {
+      switch (KeyFunction->getTemplateSpecializationKind()) {
+      case TSK_Undeclared:
+      case TSK_ExplicitSpecialization:
+      case TSK_ExplicitInstantiationDeclaration:
+        // The key function is in another translation unit.
+        continue;
+
+      case TSK_ExplicitInstantiationDefinition:
+      case TSK_ImplicitInstantiation:
+        // We will be instantiating the key function.
+        break;
+      }
+    } else if (!KeyFunction) {
+      // If we have a class with no key function that is the subject
+      // of an explicit instantiation declaration, suppress the
+      // vtable; it will live with the explicit instantiation
+      // definition.
+      bool IsExplicitInstantiationDeclaration
+        = Class->getTemplateSpecializationKind()
+                                      == TSK_ExplicitInstantiationDeclaration;
+      for (TagDecl::redecl_iterator R = Class->redecls_begin(),
+                                 REnd = Class->redecls_end();
+           R != REnd; ++R) {
+        TemplateSpecializationKind TSK
+          = cast<CXXRecordDecl>(*R)->getTemplateSpecializationKind();
+        if (TSK == TSK_ExplicitInstantiationDeclaration)
+          IsExplicitInstantiationDeclaration = true;
+        else if (TSK == TSK_ExplicitInstantiationDefinition) {
+          IsExplicitInstantiationDeclaration = false;
+          break;
+        }
+      }
+
+      if (IsExplicitInstantiationDeclaration)
+        continue;
+    }
+
+    // Mark all of the virtual members of this class as referenced, so
+    // that we can build a vtable. Then, tell the AST consumer that a
+    // vtable for this class is required.
+    DefinedAnything = true;
+    MarkVirtualMembersReferenced(Loc, Class);
+    CXXRecordDecl *Canonical = cast<CXXRecordDecl>(Class->getCanonicalDecl());
+    Consumer.HandleVTable(Class, VTablesUsed[Canonical]);
+
+    // Optionally warn if we're emitting a weak vtable.
+    if (Class->getLinkage() == ExternalLinkage &&
+        Class->getTemplateSpecializationKind() != TSK_ImplicitInstantiation) {
+      const FunctionDecl *KeyFunctionDef = 0;
+      if (!KeyFunction || 
+          (KeyFunction->hasBody(KeyFunctionDef) && 
+           KeyFunctionDef->isInlined()))
+        Diag(Class->getLocation(), Class->getTemplateSpecializationKind() ==
+             TSK_ExplicitInstantiationDefinition 
+             ? diag::warn_weak_template_vtable : diag::warn_weak_vtable) 
+          << Class;
+    }
+  }
+  VTableUses.clear();
+
+  return DefinedAnything;
+}
+
+void Sema::MarkVirtualMembersReferenced(SourceLocation Loc,
+                                        const CXXRecordDecl *RD) {
+  for (CXXRecordDecl::method_iterator i = RD->method_begin(), 
+       e = RD->method_end(); i != e; ++i) {
+    CXXMethodDecl *MD = *i;
+
+    // C++ [basic.def.odr]p2:
+    //   [...] A virtual member function is used if it is not pure. [...]
+    if (MD->isVirtual() && !MD->isPure())
+      MarkFunctionReferenced(Loc, MD);
+  }
+
+  // Only classes that have virtual bases need a VTT.
+  if (RD->getNumVBases() == 0)
+    return;
+
+  for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(),
+           e = RD->bases_end(); i != e; ++i) {
+    const CXXRecordDecl *Base =
+        cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl());
+    if (Base->getNumVBases() == 0)
+      continue;
+    MarkVirtualMembersReferenced(Loc, Base);
+  }
+}
+
+/// SetIvarInitializers - This routine builds initialization ASTs for the
+/// Objective-C implementation whose ivars need be initialized.
+void Sema::SetIvarInitializers(ObjCImplementationDecl *ObjCImplementation) {
+  if (!getLangOpts().CPlusPlus)
+    return;
+  if (ObjCInterfaceDecl *OID = ObjCImplementation->getClassInterface()) {
+    SmallVector<ObjCIvarDecl*, 8> ivars;
+    CollectIvarsToConstructOrDestruct(OID, ivars);
+    if (ivars.empty())
+      return;
+    SmallVector<CXXCtorInitializer*, 32> AllToInit;
+    for (unsigned i = 0; i < ivars.size(); i++) {
+      FieldDecl *Field = ivars[i];
+      if (Field->isInvalidDecl())
+        continue;
+      
+      CXXCtorInitializer *Member;
+      InitializedEntity InitEntity = InitializedEntity::InitializeMember(Field);
+      InitializationKind InitKind = 
+        InitializationKind::CreateDefault(ObjCImplementation->getLocation());
+      
+      InitializationSequence InitSeq(*this, InitEntity, InitKind, 0, 0);
+      ExprResult MemberInit = 
+        InitSeq.Perform(*this, InitEntity, InitKind, MultiExprArg());
+      MemberInit = MaybeCreateExprWithCleanups(MemberInit);
+      // Note, MemberInit could actually come back empty if no initialization 
+      // is required (e.g., because it would call a trivial default constructor)
+      if (!MemberInit.get() || MemberInit.isInvalid())
+        continue;
+
+      Member =
+        new (Context) CXXCtorInitializer(Context, Field, SourceLocation(),
+                                         SourceLocation(),
+                                         MemberInit.takeAs<Expr>(),
+                                         SourceLocation());
+      AllToInit.push_back(Member);
+      
+      // Be sure that the destructor is accessible and is marked as referenced.
+      if (const RecordType *RecordTy
+                  = Context.getBaseElementType(Field->getType())
+                                                        ->getAs<RecordType>()) {
+                    CXXRecordDecl *RD = cast<CXXRecordDecl>(RecordTy->getDecl());
+        if (CXXDestructorDecl *Destructor = LookupDestructor(RD)) {
+          MarkFunctionReferenced(Field->getLocation(), Destructor);
+          CheckDestructorAccess(Field->getLocation(), Destructor,
+                            PDiag(diag::err_access_dtor_ivar)
+                              << Context.getBaseElementType(Field->getType()));
+        }
+      }      
+    }
+    ObjCImplementation->setIvarInitializers(Context, 
+                                            AllToInit.data(), AllToInit.size());
+  }
+}
+
+static
+void DelegatingCycleHelper(CXXConstructorDecl* Ctor,
+                           llvm::SmallSet<CXXConstructorDecl*, 4> &Valid,
+                           llvm::SmallSet<CXXConstructorDecl*, 4> &Invalid,
+                           llvm::SmallSet<CXXConstructorDecl*, 4> &Current,
+                           Sema &S) {
+  llvm::SmallSet<CXXConstructorDecl*, 4>::iterator CI = Current.begin(),
+                                                   CE = Current.end();
+  if (Ctor->isInvalidDecl())
+    return;
+
+  const FunctionDecl *FNTarget = 0;
+  CXXConstructorDecl *Target;
+  
+  // We ignore the result here since if we don't have a body, Target will be
+  // null below.
+  (void)Ctor->getTargetConstructor()->hasBody(FNTarget);
+  Target
+= const_cast<CXXConstructorDecl*>(cast_or_null<CXXConstructorDecl>(FNTarget));
+
+  CXXConstructorDecl *Canonical = Ctor->getCanonicalDecl(),
+                     // Avoid dereferencing a null pointer here.
+                     *TCanonical = Target ? Target->getCanonicalDecl() : 0;
+
+  if (!Current.insert(Canonical))
+    return;
+
+  // We know that beyond here, we aren't chaining into a cycle.
+  if (!Target || !Target->isDelegatingConstructor() ||
+      Target->isInvalidDecl() || Valid.count(TCanonical)) {
+    for (CI = Current.begin(), CE = Current.end(); CI != CE; ++CI)
+      Valid.insert(*CI);
+    Current.clear();
+  // We've hit a cycle.
+  } else if (TCanonical == Canonical || Invalid.count(TCanonical) ||
+             Current.count(TCanonical)) {
+    // If we haven't diagnosed this cycle yet, do so now.
+    if (!Invalid.count(TCanonical)) {
+      S.Diag((*Ctor->init_begin())->getSourceLocation(),
+             diag::warn_delegating_ctor_cycle)
+        << Ctor;
+
+      // Don't add a note for a function delegating directo to itself.
+      if (TCanonical != Canonical)
+        S.Diag(Target->getLocation(), diag::note_it_delegates_to);
+
+      CXXConstructorDecl *C = Target;
+      while (C->getCanonicalDecl() != Canonical) {
+        (void)C->getTargetConstructor()->hasBody(FNTarget);
+        assert(FNTarget && "Ctor cycle through bodiless function");
+
+        C
+       = const_cast<CXXConstructorDecl*>(cast<CXXConstructorDecl>(FNTarget));
+        S.Diag(C->getLocation(), diag::note_which_delegates_to);
+      }
+    }
+
+    for (CI = Current.begin(), CE = Current.end(); CI != CE; ++CI)
+      Invalid.insert(*CI);
+    Current.clear();
+  } else {
+    DelegatingCycleHelper(Target, Valid, Invalid, Current, S);
+  }
+}
+   
+
+void Sema::CheckDelegatingCtorCycles() {
+  llvm::SmallSet<CXXConstructorDecl*, 4> Valid, Invalid, Current;
+
+  llvm::SmallSet<CXXConstructorDecl*, 4>::iterator CI = Current.begin(),
+                                                   CE = Current.end();
+
+  for (DelegatingCtorDeclsType::iterator
+         I = DelegatingCtorDecls.begin(ExternalSource),
+         E = DelegatingCtorDecls.end();
+       I != E; ++I) {
+   DelegatingCycleHelper(*I, Valid, Invalid, Current, *this);
+  }
+
+  for (CI = Invalid.begin(), CE = Invalid.end(); CI != CE; ++CI)
+    (*CI)->setInvalidDecl();
+}
+
+namespace {
+  /// \brief AST visitor that finds references to the 'this' expression.
+  class FindCXXThisExpr : public RecursiveASTVisitor<FindCXXThisExpr> {
+    Sema &S;
+    
+  public:
+    explicit FindCXXThisExpr(Sema &S) : S(S) { }
+    
+    bool VisitCXXThisExpr(CXXThisExpr *E) {
+      S.Diag(E->getLocation(), diag::err_this_static_member_func)
+        << E->isImplicit();
+      return false;
+    }
+  };
+}
+
+bool Sema::checkThisInStaticMemberFunctionType(CXXMethodDecl *Method) {
+  TypeSourceInfo *TSInfo = Method->getTypeSourceInfo();
+  if (!TSInfo)
+    return false;
+  
+  TypeLoc TL = TSInfo->getTypeLoc();
+  FunctionProtoTypeLoc *ProtoTL = dyn_cast<FunctionProtoTypeLoc>(&TL);
+  if (!ProtoTL)
+    return false;
+  
+  // C++11 [expr.prim.general]p3:
+  //   [The expression this] shall not appear before the optional 
+  //   cv-qualifier-seq and it shall not appear within the declaration of a 
+  //   static member function (although its type and value category are defined
+  //   within a static member function as they are within a non-static member
+  //   function). [ Note: this is because declaration matching does not occur
+  //  until the complete declarator is known. - end note ]
+  const FunctionProtoType *Proto = ProtoTL->getTypePtr();
+  FindCXXThisExpr Finder(*this);
+  
+  // If the return type came after the cv-qualifier-seq, check it now.
+  if (Proto->hasTrailingReturn() &&
+      !Finder.TraverseTypeLoc(ProtoTL->getResultLoc()))
+    return true;
+
+  // Check the exception specification.
+  if (checkThisInStaticMemberFunctionExceptionSpec(Method))
+    return true;
+  
+  return checkThisInStaticMemberFunctionAttributes(Method);
+}
+
+bool Sema::checkThisInStaticMemberFunctionExceptionSpec(CXXMethodDecl *Method) {
+  TypeSourceInfo *TSInfo = Method->getTypeSourceInfo();
+  if (!TSInfo)
+    return false;
+  
+  TypeLoc TL = TSInfo->getTypeLoc();
+  FunctionProtoTypeLoc *ProtoTL = dyn_cast<FunctionProtoTypeLoc>(&TL);
+  if (!ProtoTL)
+    return false;
+  
+  const FunctionProtoType *Proto = ProtoTL->getTypePtr();
+  FindCXXThisExpr Finder(*this);
+
+  switch (Proto->getExceptionSpecType()) {
+  case EST_Uninstantiated:
+  case EST_BasicNoexcept:
+  case EST_Delayed:
+  case EST_DynamicNone:
+  case EST_MSAny:
+  case EST_None:
+    break;
+    
+  case EST_ComputedNoexcept:
+    if (!Finder.TraverseStmt(Proto->getNoexceptExpr()))
+      return true;
+    
+  case EST_Dynamic:
+    for (FunctionProtoType::exception_iterator E = Proto->exception_begin(),
+         EEnd = Proto->exception_end();
+         E != EEnd; ++E) {
+      if (!Finder.TraverseType(*E))
+        return true;
+    }
+    break;
+  }
+
+  return false;
+}
+
+bool Sema::checkThisInStaticMemberFunctionAttributes(CXXMethodDecl *Method) {
+  FindCXXThisExpr Finder(*this);
+
+  // Check attributes.
+  for (Decl::attr_iterator A = Method->attr_begin(), AEnd = Method->attr_end();
+       A != AEnd; ++A) {
+    // FIXME: This should be emitted by tblgen.
+    Expr *Arg = 0;
+    ArrayRef<Expr *> Args;
+    if (GuardedByAttr *G = dyn_cast<GuardedByAttr>(*A))
+      Arg = G->getArg();
+    else if (PtGuardedByAttr *G = dyn_cast<PtGuardedByAttr>(*A))
+      Arg = G->getArg();
+    else if (AcquiredAfterAttr *AA = dyn_cast<AcquiredAfterAttr>(*A))
+      Args = ArrayRef<Expr *>(AA->args_begin(), AA->args_size());
+    else if (AcquiredBeforeAttr *AB = dyn_cast<AcquiredBeforeAttr>(*A))
+      Args = ArrayRef<Expr *>(AB->args_begin(), AB->args_size());
+    else if (ExclusiveLockFunctionAttr *ELF 
+               = dyn_cast<ExclusiveLockFunctionAttr>(*A))
+      Args = ArrayRef<Expr *>(ELF->args_begin(), ELF->args_size());
+    else if (SharedLockFunctionAttr *SLF 
+               = dyn_cast<SharedLockFunctionAttr>(*A))
+      Args = ArrayRef<Expr *>(SLF->args_begin(), SLF->args_size());
+    else if (ExclusiveTrylockFunctionAttr *ETLF
+               = dyn_cast<ExclusiveTrylockFunctionAttr>(*A)) {
+      Arg = ETLF->getSuccessValue();
+      Args = ArrayRef<Expr *>(ETLF->args_begin(), ETLF->args_size());
+    } else if (SharedTrylockFunctionAttr *STLF
+                 = dyn_cast<SharedTrylockFunctionAttr>(*A)) {
+      Arg = STLF->getSuccessValue();
+      Args = ArrayRef<Expr *>(STLF->args_begin(), STLF->args_size());
+    } else if (UnlockFunctionAttr *UF = dyn_cast<UnlockFunctionAttr>(*A))
+      Args = ArrayRef<Expr *>(UF->args_begin(), UF->args_size());
+    else if (LockReturnedAttr *LR = dyn_cast<LockReturnedAttr>(*A))
+      Arg = LR->getArg();
+    else if (LocksExcludedAttr *LE = dyn_cast<LocksExcludedAttr>(*A))
+      Args = ArrayRef<Expr *>(LE->args_begin(), LE->args_size());
+    else if (ExclusiveLocksRequiredAttr *ELR 
+               = dyn_cast<ExclusiveLocksRequiredAttr>(*A))
+      Args = ArrayRef<Expr *>(ELR->args_begin(), ELR->args_size());
+    else if (SharedLocksRequiredAttr *SLR 
+               = dyn_cast<SharedLocksRequiredAttr>(*A))
+      Args = ArrayRef<Expr *>(SLR->args_begin(), SLR->args_size());
+
+    if (Arg && !Finder.TraverseStmt(Arg))
+      return true;
+    
+    for (unsigned I = 0, N = Args.size(); I != N; ++I) {
+      if (!Finder.TraverseStmt(Args[I]))
+        return true;
+    }
+  }
+  
+  return false;
+}
+
+void
+Sema::checkExceptionSpecification(ExceptionSpecificationType EST,
+                                  ArrayRef<ParsedType> DynamicExceptions,
+                                  ArrayRef<SourceRange> DynamicExceptionRanges,
+                                  Expr *NoexceptExpr,
+                                  llvm::SmallVectorImpl<QualType> &Exceptions,
+                                  FunctionProtoType::ExtProtoInfo &EPI) {
+  Exceptions.clear();
+  EPI.ExceptionSpecType = EST;
+  if (EST == EST_Dynamic) {
+    Exceptions.reserve(DynamicExceptions.size());
+    for (unsigned ei = 0, ee = DynamicExceptions.size(); ei != ee; ++ei) {
+      // FIXME: Preserve type source info.
+      QualType ET = GetTypeFromParser(DynamicExceptions[ei]);
+
+      SmallVector<UnexpandedParameterPack, 2> Unexpanded;
+      collectUnexpandedParameterPacks(ET, Unexpanded);
+      if (!Unexpanded.empty()) {
+        DiagnoseUnexpandedParameterPacks(DynamicExceptionRanges[ei].getBegin(),
+                                         UPPC_ExceptionType,
+                                         Unexpanded);
+        continue;
+      }
+
+      // Check that the type is valid for an exception spec, and
+      // drop it if not.
+      if (!CheckSpecifiedExceptionType(ET, DynamicExceptionRanges[ei]))
+        Exceptions.push_back(ET);
+    }
+    EPI.NumExceptions = Exceptions.size();
+    EPI.Exceptions = Exceptions.data();
+    return;
+  }
+  
+  if (EST == EST_ComputedNoexcept) {
+    // If an error occurred, there's no expression here.
+    if (NoexceptExpr) {
+      assert((NoexceptExpr->isTypeDependent() ||
+              NoexceptExpr->getType()->getCanonicalTypeUnqualified() ==
+              Context.BoolTy) &&
+             "Parser should have made sure that the expression is boolean");
+      if (NoexceptExpr && DiagnoseUnexpandedParameterPack(NoexceptExpr)) {
+        EPI.ExceptionSpecType = EST_BasicNoexcept;
+        return;
+      }
+      
+      if (!NoexceptExpr->isValueDependent())
+        NoexceptExpr = VerifyIntegerConstantExpression(NoexceptExpr, 0,
+                         PDiag(diag::err_noexcept_needs_constant_expression),
+                         /*AllowFold*/ false).take();
+      EPI.NoexceptExpr = NoexceptExpr;
+    }
+    return;
+  }
+}
+
+/// IdentifyCUDATarget - Determine the CUDA compilation target for this function
+Sema::CUDAFunctionTarget Sema::IdentifyCUDATarget(const FunctionDecl *D) {
+  // Implicitly declared functions (e.g. copy constructors) are
+  // __host__ __device__
+  if (D->isImplicit())
+    return CFT_HostDevice;
+
+  if (D->hasAttr<CUDAGlobalAttr>())
+    return CFT_Global;
+
+  if (D->hasAttr<CUDADeviceAttr>()) {
+    if (D->hasAttr<CUDAHostAttr>())
+      return CFT_HostDevice;
+    else
+      return CFT_Device;
+  }
+
+  return CFT_Host;
+}
+
+bool Sema::CheckCUDATarget(CUDAFunctionTarget CallerTarget,
+                           CUDAFunctionTarget CalleeTarget) {
+  // CUDA B.1.1 "The __device__ qualifier declares a function that is...
+  // Callable from the device only."
+  if (CallerTarget == CFT_Host && CalleeTarget == CFT_Device)
+    return true;
+
+  // CUDA B.1.2 "The __global__ qualifier declares a function that is...
+  // Callable from the host only."
+  // CUDA B.1.3 "The __host__ qualifier declares a function that is...
+  // Callable from the host only."
+  if ((CallerTarget == CFT_Device || CallerTarget == CFT_Global) &&
+      (CalleeTarget == CFT_Host || CalleeTarget == CFT_Global))
+    return true;
+
+  if (CallerTarget == CFT_HostDevice && CalleeTarget != CFT_HostDevice)
+    return true;
+
+  return false;
+}
diff --git a/clang/lib/Sema/SemaDeclObjC.cpp b/clang/lib/Sema/SemaDeclObjC.cpp
new file mode 100644
index 0000000..a942d49
--- /dev/null
+++ b/clang/lib/Sema/SemaDeclObjC.cpp
@@ -0,0 +1,3121 @@
+//===--- SemaDeclObjC.cpp - Semantic Analysis for ObjC Declarations -------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+//  This file implements semantic analysis for Objective C declarations.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Sema/SemaInternal.h"
+#include "clang/Sema/Lookup.h"
+#include "clang/Sema/ExternalSemaSource.h"
+#include "clang/Sema/Scope.h"
+#include "clang/Sema/ScopeInfo.h"
+#include "clang/AST/ASTConsumer.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/ExprObjC.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/AST/ASTMutationListener.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Sema/DeclSpec.h"
+#include "clang/Lex/Preprocessor.h"
+#include "llvm/ADT/DenseSet.h"
+
+using namespace clang;
+
+/// Check whether the given method, which must be in the 'init'
+/// family, is a valid member of that family.
+///
+/// \param receiverTypeIfCall - if null, check this as if declaring it;
+///   if non-null, check this as if making a call to it with the given
+///   receiver type
+///
+/// \return true to indicate that there was an error and appropriate
+///   actions were taken
+bool Sema::checkInitMethod(ObjCMethodDecl *method,
+                           QualType receiverTypeIfCall) {
+  if (method->isInvalidDecl()) return true;
+
+  // This castAs is safe: methods that don't return an object
+  // pointer won't be inferred as inits and will reject an explicit
+  // objc_method_family(init).
+
+  // We ignore protocols here.  Should we?  What about Class?
+
+  const ObjCObjectType *result = method->getResultType()
+    ->castAs<ObjCObjectPointerType>()->getObjectType();
+
+  if (result->isObjCId()) {
+    return false;
+  } else if (result->isObjCClass()) {
+    // fall through: always an error
+  } else {
+    ObjCInterfaceDecl *resultClass = result->getInterface();
+    assert(resultClass && "unexpected object type!");
+
+    // It's okay for the result type to still be a forward declaration
+    // if we're checking an interface declaration.
+    if (!resultClass->hasDefinition()) {
+      if (receiverTypeIfCall.isNull() &&
+          !isa<ObjCImplementationDecl>(method->getDeclContext()))
+        return false;
+
+    // Otherwise, we try to compare class types.
+    } else {
+      // If this method was declared in a protocol, we can't check
+      // anything unless we have a receiver type that's an interface.
+      const ObjCInterfaceDecl *receiverClass = 0;
+      if (isa<ObjCProtocolDecl>(method->getDeclContext())) {
+        if (receiverTypeIfCall.isNull())
+          return false;
+
+        receiverClass = receiverTypeIfCall->castAs<ObjCObjectPointerType>()
+          ->getInterfaceDecl();
+
+        // This can be null for calls to e.g. id<Foo>.
+        if (!receiverClass) return false;
+      } else {
+        receiverClass = method->getClassInterface();
+        assert(receiverClass && "method not associated with a class!");
+      }
+
+      // If either class is a subclass of the other, it's fine.
+      if (receiverClass->isSuperClassOf(resultClass) ||
+          resultClass->isSuperClassOf(receiverClass))
+        return false;
+    }
+  }
+
+  SourceLocation loc = method->getLocation();
+
+  // If we're in a system header, and this is not a call, just make
+  // the method unusable.
+  if (receiverTypeIfCall.isNull() && getSourceManager().isInSystemHeader(loc)) {
+    method->addAttr(new (Context) UnavailableAttr(loc, Context,
+                "init method returns a type unrelated to its receiver type"));
+    return true;
+  }
+
+  // Otherwise, it's an error.
+  Diag(loc, diag::err_arc_init_method_unrelated_result_type);
+  method->setInvalidDecl();
+  return true;
+}
+
+void Sema::CheckObjCMethodOverride(ObjCMethodDecl *NewMethod, 
+                                   const ObjCMethodDecl *Overridden,
+                                   bool IsImplementation) {
+  if (Overridden->hasRelatedResultType() && 
+      !NewMethod->hasRelatedResultType()) {
+    // This can only happen when the method follows a naming convention that
+    // implies a related result type, and the original (overridden) method has
+    // a suitable return type, but the new (overriding) method does not have
+    // a suitable return type.
+    QualType ResultType = NewMethod->getResultType();
+    SourceRange ResultTypeRange;
+    if (const TypeSourceInfo *ResultTypeInfo 
+                                        = NewMethod->getResultTypeSourceInfo())
+      ResultTypeRange = ResultTypeInfo->getTypeLoc().getSourceRange();
+    
+    // Figure out which class this method is part of, if any.
+    ObjCInterfaceDecl *CurrentClass 
+      = dyn_cast<ObjCInterfaceDecl>(NewMethod->getDeclContext());
+    if (!CurrentClass) {
+      DeclContext *DC = NewMethod->getDeclContext();
+      if (ObjCCategoryDecl *Cat = dyn_cast<ObjCCategoryDecl>(DC))
+        CurrentClass = Cat->getClassInterface();
+      else if (ObjCImplDecl *Impl = dyn_cast<ObjCImplDecl>(DC))
+        CurrentClass = Impl->getClassInterface();
+      else if (ObjCCategoryImplDecl *CatImpl
+               = dyn_cast<ObjCCategoryImplDecl>(DC))
+        CurrentClass = CatImpl->getClassInterface();
+    }
+    
+    if (CurrentClass) {
+      Diag(NewMethod->getLocation(), 
+           diag::warn_related_result_type_compatibility_class)
+        << Context.getObjCInterfaceType(CurrentClass)
+        << ResultType
+        << ResultTypeRange;
+    } else {
+      Diag(NewMethod->getLocation(), 
+           diag::warn_related_result_type_compatibility_protocol)
+        << ResultType
+        << ResultTypeRange;
+    }
+    
+    if (ObjCMethodFamily Family = Overridden->getMethodFamily())
+      Diag(Overridden->getLocation(), 
+           diag::note_related_result_type_overridden_family)
+        << Family;
+    else
+      Diag(Overridden->getLocation(), 
+           diag::note_related_result_type_overridden);
+  }
+  if (getLangOpts().ObjCAutoRefCount) {
+    if ((NewMethod->hasAttr<NSReturnsRetainedAttr>() !=
+         Overridden->hasAttr<NSReturnsRetainedAttr>())) {
+        Diag(NewMethod->getLocation(),
+             diag::err_nsreturns_retained_attribute_mismatch) << 1;
+        Diag(Overridden->getLocation(), diag::note_previous_decl) 
+        << "method";
+    }
+    if ((NewMethod->hasAttr<NSReturnsNotRetainedAttr>() !=
+              Overridden->hasAttr<NSReturnsNotRetainedAttr>())) {
+        Diag(NewMethod->getLocation(),
+             diag::err_nsreturns_retained_attribute_mismatch) << 0;
+        Diag(Overridden->getLocation(), diag::note_previous_decl) 
+        << "method";
+    }
+    ObjCMethodDecl::param_const_iterator oi = Overridden->param_begin();
+    for (ObjCMethodDecl::param_iterator
+           ni = NewMethod->param_begin(), ne = NewMethod->param_end();
+         ni != ne; ++ni, ++oi) {
+      const ParmVarDecl *oldDecl = (*oi);
+      ParmVarDecl *newDecl = (*ni);
+      if (newDecl->hasAttr<NSConsumedAttr>() != 
+          oldDecl->hasAttr<NSConsumedAttr>()) {
+        Diag(newDecl->getLocation(),
+             diag::err_nsconsumed_attribute_mismatch);
+        Diag(oldDecl->getLocation(), diag::note_previous_decl) 
+          << "parameter";
+      }
+    }
+  }
+}
+
+/// \brief Check a method declaration for compatibility with the Objective-C
+/// ARC conventions.
+static bool CheckARCMethodDecl(Sema &S, ObjCMethodDecl *method) {
+  ObjCMethodFamily family = method->getMethodFamily();
+  switch (family) {
+  case OMF_None:
+  case OMF_dealloc:
+  case OMF_finalize:
+  case OMF_retain:
+  case OMF_release:
+  case OMF_autorelease:
+  case OMF_retainCount:
+  case OMF_self:
+  case OMF_performSelector:
+    return false;
+
+  case OMF_init:
+    // If the method doesn't obey the init rules, don't bother annotating it.
+    if (S.checkInitMethod(method, QualType()))
+      return true;
+
+    method->addAttr(new (S.Context) NSConsumesSelfAttr(SourceLocation(),
+                                                       S.Context));
+
+    // Don't add a second copy of this attribute, but otherwise don't
+    // let it be suppressed.
+    if (method->hasAttr<NSReturnsRetainedAttr>())
+      return false;
+    break;
+
+  case OMF_alloc:
+  case OMF_copy:
+  case OMF_mutableCopy:
+  case OMF_new:
+    if (method->hasAttr<NSReturnsRetainedAttr>() ||
+        method->hasAttr<NSReturnsNotRetainedAttr>() ||
+        method->hasAttr<NSReturnsAutoreleasedAttr>())
+      return false;
+    break;
+  }
+
+  method->addAttr(new (S.Context) NSReturnsRetainedAttr(SourceLocation(),
+                                                        S.Context));
+  return false;
+}
+
+static void DiagnoseObjCImplementedDeprecations(Sema &S,
+                                                NamedDecl *ND,
+                                                SourceLocation ImplLoc,
+                                                int select) {
+  if (ND && ND->isDeprecated()) {
+    S.Diag(ImplLoc, diag::warn_deprecated_def) << select;
+    if (select == 0)
+      S.Diag(ND->getLocation(), diag::note_method_declared_at)
+        << ND->getDeclName();
+    else
+      S.Diag(ND->getLocation(), diag::note_previous_decl) << "class";
+  }
+}
+
+/// AddAnyMethodToGlobalPool - Add any method, instance or factory to global
+/// pool.
+void Sema::AddAnyMethodToGlobalPool(Decl *D) {
+  ObjCMethodDecl *MDecl = dyn_cast_or_null<ObjCMethodDecl>(D);
+    
+  // If we don't have a valid method decl, simply return.
+  if (!MDecl)
+    return;
+  if (MDecl->isInstanceMethod())
+    AddInstanceMethodToGlobalPool(MDecl, true);
+  else
+    AddFactoryMethodToGlobalPool(MDecl, true);
+}
+
+/// ActOnStartOfObjCMethodDef - This routine sets up parameters; invisible
+/// and user declared, in the method definition's AST.
+void Sema::ActOnStartOfObjCMethodDef(Scope *FnBodyScope, Decl *D) {
+  assert(getCurMethodDecl() == 0 && "Method parsing confused");
+  ObjCMethodDecl *MDecl = dyn_cast_or_null<ObjCMethodDecl>(D);
+
+  // If we don't have a valid method decl, simply return.
+  if (!MDecl)
+    return;
+
+  // Allow all of Sema to see that we are entering a method definition.
+  PushDeclContext(FnBodyScope, MDecl);
+  PushFunctionScope();
+  
+  // Create Decl objects for each parameter, entrring them in the scope for
+  // binding to their use.
+
+  // Insert the invisible arguments, self and _cmd!
+  MDecl->createImplicitParams(Context, MDecl->getClassInterface());
+
+  PushOnScopeChains(MDecl->getSelfDecl(), FnBodyScope);
+  PushOnScopeChains(MDecl->getCmdDecl(), FnBodyScope);
+
+  // Introduce all of the other parameters into this scope.
+  for (ObjCMethodDecl::param_iterator PI = MDecl->param_begin(),
+       E = MDecl->param_end(); PI != E; ++PI) {
+    ParmVarDecl *Param = (*PI);
+    if (!Param->isInvalidDecl() &&
+        RequireCompleteType(Param->getLocation(), Param->getType(),
+                            diag::err_typecheck_decl_incomplete_type))
+          Param->setInvalidDecl();
+    if ((*PI)->getIdentifier())
+      PushOnScopeChains(*PI, FnBodyScope);
+  }
+
+  // In ARC, disallow definition of retain/release/autorelease/retainCount
+  if (getLangOpts().ObjCAutoRefCount) {
+    switch (MDecl->getMethodFamily()) {
+    case OMF_retain:
+    case OMF_retainCount:
+    case OMF_release:
+    case OMF_autorelease:
+      Diag(MDecl->getLocation(), diag::err_arc_illegal_method_def)
+        << MDecl->getSelector();
+      break;
+
+    case OMF_None:
+    case OMF_dealloc:
+    case OMF_finalize:
+    case OMF_alloc:
+    case OMF_init:
+    case OMF_mutableCopy:
+    case OMF_copy:
+    case OMF_new:
+    case OMF_self:
+    case OMF_performSelector:
+      break;
+    }
+  }
+
+  // Warn on deprecated methods under -Wdeprecated-implementations,
+  // and prepare for warning on missing super calls.
+  if (ObjCInterfaceDecl *IC = MDecl->getClassInterface()) {
+    if (ObjCMethodDecl *IMD = 
+          IC->lookupMethod(MDecl->getSelector(), MDecl->isInstanceMethod()))
+      DiagnoseObjCImplementedDeprecations(*this, 
+                                          dyn_cast<NamedDecl>(IMD), 
+                                          MDecl->getLocation(), 0);
+
+    // If this is "dealloc" or "finalize", set some bit here.
+    // Then in ActOnSuperMessage() (SemaExprObjC), set it back to false.
+    // Finally, in ActOnFinishFunctionBody() (SemaDecl), warn if flag is set.
+    // Only do this if the current class actually has a superclass.
+    if (IC->getSuperClass()) {
+      ObjCShouldCallSuperDealloc = 
+        !(Context.getLangOpts().ObjCAutoRefCount ||
+          Context.getLangOpts().getGC() == LangOptions::GCOnly) &&
+        MDecl->getMethodFamily() == OMF_dealloc;
+      ObjCShouldCallSuperFinalize =
+        Context.getLangOpts().getGC() != LangOptions::NonGC &&
+        MDecl->getMethodFamily() == OMF_finalize;
+    }
+  }
+}
+
+namespace {
+
+// Callback to only accept typo corrections that are Objective-C classes.
+// If an ObjCInterfaceDecl* is given to the constructor, then the validation
+// function will reject corrections to that class.
+class ObjCInterfaceValidatorCCC : public CorrectionCandidateCallback {
+ public:
+  ObjCInterfaceValidatorCCC() : CurrentIDecl(0) {}
+  explicit ObjCInterfaceValidatorCCC(ObjCInterfaceDecl *IDecl)
+      : CurrentIDecl(IDecl) {}
+
+  virtual bool ValidateCandidate(const TypoCorrection &candidate) {
+    ObjCInterfaceDecl *ID = candidate.getCorrectionDeclAs<ObjCInterfaceDecl>();
+    return ID && !declaresSameEntity(ID, CurrentIDecl);
+  }
+
+ private:
+  ObjCInterfaceDecl *CurrentIDecl;
+};
+
+}
+
+Decl *Sema::
+ActOnStartClassInterface(SourceLocation AtInterfaceLoc,
+                         IdentifierInfo *ClassName, SourceLocation ClassLoc,
+                         IdentifierInfo *SuperName, SourceLocation SuperLoc,
+                         Decl * const *ProtoRefs, unsigned NumProtoRefs,
+                         const SourceLocation *ProtoLocs, 
+                         SourceLocation EndProtoLoc, AttributeList *AttrList) {
+  assert(ClassName && "Missing class identifier");
+
+  // Check for another declaration kind with the same name.
+  NamedDecl *PrevDecl = LookupSingleName(TUScope, ClassName, ClassLoc,
+                                         LookupOrdinaryName, ForRedeclaration);
+
+  if (PrevDecl && !isa<ObjCInterfaceDecl>(PrevDecl)) {
+    Diag(ClassLoc, diag::err_redefinition_different_kind) << ClassName;
+    Diag(PrevDecl->getLocation(), diag::note_previous_definition);
+  }
+
+  // Create a declaration to describe this @interface.
+  ObjCInterfaceDecl* PrevIDecl = dyn_cast_or_null<ObjCInterfaceDecl>(PrevDecl);
+  ObjCInterfaceDecl *IDecl
+    = ObjCInterfaceDecl::Create(Context, CurContext, AtInterfaceLoc, ClassName,
+                                PrevIDecl, ClassLoc);
+  
+  if (PrevIDecl) {
+    // Class already seen. Was it a definition?
+    if (ObjCInterfaceDecl *Def = PrevIDecl->getDefinition()) {
+      Diag(AtInterfaceLoc, diag::err_duplicate_class_def)
+        << PrevIDecl->getDeclName();
+      Diag(Def->getLocation(), diag::note_previous_definition);
+      IDecl->setInvalidDecl();
+    }
+  }
+  
+  if (AttrList)
+    ProcessDeclAttributeList(TUScope, IDecl, AttrList);
+  PushOnScopeChains(IDecl, TUScope);
+
+  // Start the definition of this class. If we're in a redefinition case, there 
+  // may already be a definition, so we'll end up adding to it.
+  if (!IDecl->hasDefinition())
+    IDecl->startDefinition();
+  
+  if (SuperName) {
+    // Check if a different kind of symbol declared in this scope.
+    PrevDecl = LookupSingleName(TUScope, SuperName, SuperLoc,
+                                LookupOrdinaryName);
+
+    if (!PrevDecl) {
+      // Try to correct for a typo in the superclass name without correcting
+      // to the class we're defining.
+      ObjCInterfaceValidatorCCC Validator(IDecl);
+      if (TypoCorrection Corrected = CorrectTypo(
+          DeclarationNameInfo(SuperName, SuperLoc), LookupOrdinaryName, TUScope,
+          NULL, Validator)) {
+        PrevDecl = Corrected.getCorrectionDeclAs<ObjCInterfaceDecl>();
+        Diag(SuperLoc, diag::err_undef_superclass_suggest)
+          << SuperName << ClassName << PrevDecl->getDeclName();
+        Diag(PrevDecl->getLocation(), diag::note_previous_decl)
+          << PrevDecl->getDeclName();
+      }
+    }
+
+    if (declaresSameEntity(PrevDecl, IDecl)) {
+      Diag(SuperLoc, diag::err_recursive_superclass)
+        << SuperName << ClassName << SourceRange(AtInterfaceLoc, ClassLoc);
+      IDecl->setEndOfDefinitionLoc(ClassLoc);
+    } else {
+      ObjCInterfaceDecl *SuperClassDecl =
+                                dyn_cast_or_null<ObjCInterfaceDecl>(PrevDecl);
+
+      // Diagnose classes that inherit from deprecated classes.
+      if (SuperClassDecl)
+        (void)DiagnoseUseOfDecl(SuperClassDecl, SuperLoc);
+
+      if (PrevDecl && SuperClassDecl == 0) {
+        // The previous declaration was not a class decl. Check if we have a
+        // typedef. If we do, get the underlying class type.
+        if (const TypedefNameDecl *TDecl =
+              dyn_cast_or_null<TypedefNameDecl>(PrevDecl)) {
+          QualType T = TDecl->getUnderlyingType();
+          if (T->isObjCObjectType()) {
+            if (NamedDecl *IDecl = T->getAs<ObjCObjectType>()->getInterface())
+              SuperClassDecl = dyn_cast<ObjCInterfaceDecl>(IDecl);
+          }
+        }
+
+        // This handles the following case:
+        //
+        // typedef int SuperClass;
+        // @interface MyClass : SuperClass {} @end
+        //
+        if (!SuperClassDecl) {
+          Diag(SuperLoc, diag::err_redefinition_different_kind) << SuperName;
+          Diag(PrevDecl->getLocation(), diag::note_previous_definition);
+        }
+      }
+
+      if (!dyn_cast_or_null<TypedefNameDecl>(PrevDecl)) {
+        if (!SuperClassDecl)
+          Diag(SuperLoc, diag::err_undef_superclass)
+            << SuperName << ClassName << SourceRange(AtInterfaceLoc, ClassLoc);
+        else if (RequireCompleteType(SuperLoc, 
+                   Context.getObjCInterfaceType(SuperClassDecl),
+                   PDiag(diag::err_forward_superclass)
+                     << SuperClassDecl->getDeclName() 
+                     << ClassName
+                   << SourceRange(AtInterfaceLoc, ClassLoc))) {
+          SuperClassDecl = 0;
+        }
+      }
+      IDecl->setSuperClass(SuperClassDecl);
+      IDecl->setSuperClassLoc(SuperLoc);
+      IDecl->setEndOfDefinitionLoc(SuperLoc);
+    }
+  } else { // we have a root class.
+    IDecl->setEndOfDefinitionLoc(ClassLoc);
+  }
+
+  // Check then save referenced protocols.
+  if (NumProtoRefs) {
+    IDecl->setProtocolList((ObjCProtocolDecl**)ProtoRefs, NumProtoRefs,
+                           ProtoLocs, Context);
+    IDecl->setEndOfDefinitionLoc(EndProtoLoc);
+  }
+
+  CheckObjCDeclScope(IDecl);
+  return ActOnObjCContainerStartDefinition(IDecl);
+}
+
+/// ActOnCompatiblityAlias - this action is called after complete parsing of
+/// @compatibility_alias declaration. It sets up the alias relationships.
+Decl *Sema::ActOnCompatiblityAlias(SourceLocation AtLoc,
+                                        IdentifierInfo *AliasName,
+                                        SourceLocation AliasLocation,
+                                        IdentifierInfo *ClassName,
+                                        SourceLocation ClassLocation) {
+  // Look for previous declaration of alias name
+  NamedDecl *ADecl = LookupSingleName(TUScope, AliasName, AliasLocation,
+                                      LookupOrdinaryName, ForRedeclaration);
+  if (ADecl) {
+    if (isa<ObjCCompatibleAliasDecl>(ADecl))
+      Diag(AliasLocation, diag::warn_previous_alias_decl);
+    else
+      Diag(AliasLocation, diag::err_conflicting_aliasing_type) << AliasName;
+    Diag(ADecl->getLocation(), diag::note_previous_declaration);
+    return 0;
+  }
+  // Check for class declaration
+  NamedDecl *CDeclU = LookupSingleName(TUScope, ClassName, ClassLocation,
+                                       LookupOrdinaryName, ForRedeclaration);
+  if (const TypedefNameDecl *TDecl =
+        dyn_cast_or_null<TypedefNameDecl>(CDeclU)) {
+    QualType T = TDecl->getUnderlyingType();
+    if (T->isObjCObjectType()) {
+      if (NamedDecl *IDecl = T->getAs<ObjCObjectType>()->getInterface()) {
+        ClassName = IDecl->getIdentifier();
+        CDeclU = LookupSingleName(TUScope, ClassName, ClassLocation,
+                                  LookupOrdinaryName, ForRedeclaration);
+      }
+    }
+  }
+  ObjCInterfaceDecl *CDecl = dyn_cast_or_null<ObjCInterfaceDecl>(CDeclU);
+  if (CDecl == 0) {
+    Diag(ClassLocation, diag::warn_undef_interface) << ClassName;
+    if (CDeclU)
+      Diag(CDeclU->getLocation(), diag::note_previous_declaration);
+    return 0;
+  }
+
+  // Everything checked out, instantiate a new alias declaration AST.
+  ObjCCompatibleAliasDecl *AliasDecl =
+    ObjCCompatibleAliasDecl::Create(Context, CurContext, AtLoc, AliasName, CDecl);
+
+  if (!CheckObjCDeclScope(AliasDecl))
+    PushOnScopeChains(AliasDecl, TUScope);
+
+  return AliasDecl;
+}
+
+bool Sema::CheckForwardProtocolDeclarationForCircularDependency(
+  IdentifierInfo *PName,
+  SourceLocation &Ploc, SourceLocation PrevLoc,
+  const ObjCList<ObjCProtocolDecl> &PList) {
+  
+  bool res = false;
+  for (ObjCList<ObjCProtocolDecl>::iterator I = PList.begin(),
+       E = PList.end(); I != E; ++I) {
+    if (ObjCProtocolDecl *PDecl = LookupProtocol((*I)->getIdentifier(),
+                                                 Ploc)) {
+      if (PDecl->getIdentifier() == PName) {
+        Diag(Ploc, diag::err_protocol_has_circular_dependency);
+        Diag(PrevLoc, diag::note_previous_definition);
+        res = true;
+      }
+      
+      if (!PDecl->hasDefinition())
+        continue;
+      
+      if (CheckForwardProtocolDeclarationForCircularDependency(PName, Ploc,
+            PDecl->getLocation(), PDecl->getReferencedProtocols()))
+        res = true;
+    }
+  }
+  return res;
+}
+
+Decl *
+Sema::ActOnStartProtocolInterface(SourceLocation AtProtoInterfaceLoc,
+                                  IdentifierInfo *ProtocolName,
+                                  SourceLocation ProtocolLoc,
+                                  Decl * const *ProtoRefs,
+                                  unsigned NumProtoRefs,
+                                  const SourceLocation *ProtoLocs,
+                                  SourceLocation EndProtoLoc,
+                                  AttributeList *AttrList) {
+  bool err = false;
+  // FIXME: Deal with AttrList.
+  assert(ProtocolName && "Missing protocol identifier");
+  ObjCProtocolDecl *PrevDecl = LookupProtocol(ProtocolName, ProtocolLoc,
+                                              ForRedeclaration);
+  ObjCProtocolDecl *PDecl = 0;
+  if (ObjCProtocolDecl *Def = PrevDecl? PrevDecl->getDefinition() : 0) {
+    // If we already have a definition, complain.
+    Diag(ProtocolLoc, diag::warn_duplicate_protocol_def) << ProtocolName;
+    Diag(Def->getLocation(), diag::note_previous_definition);
+
+    // Create a new protocol that is completely distinct from previous
+    // declarations, and do not make this protocol available for name lookup.
+    // That way, we'll end up completely ignoring the duplicate.
+    // FIXME: Can we turn this into an error?
+    PDecl = ObjCProtocolDecl::Create(Context, CurContext, ProtocolName,
+                                     ProtocolLoc, AtProtoInterfaceLoc,
+                                     /*PrevDecl=*/0);
+    PDecl->startDefinition();
+  } else {
+    if (PrevDecl) {
+      // Check for circular dependencies among protocol declarations. This can
+      // only happen if this protocol was forward-declared.
+      ObjCList<ObjCProtocolDecl> PList;
+      PList.set((ObjCProtocolDecl *const*)ProtoRefs, NumProtoRefs, Context);
+      err = CheckForwardProtocolDeclarationForCircularDependency(
+              ProtocolName, ProtocolLoc, PrevDecl->getLocation(), PList);
+    }
+
+    // Create the new declaration.
+    PDecl = ObjCProtocolDecl::Create(Context, CurContext, ProtocolName,
+                                     ProtocolLoc, AtProtoInterfaceLoc,
+                                     /*PrevDecl=*/PrevDecl);
+    
+    PushOnScopeChains(PDecl, TUScope);
+    PDecl->startDefinition();
+  }
+  
+  if (AttrList)
+    ProcessDeclAttributeList(TUScope, PDecl, AttrList);
+  
+  // Merge attributes from previous declarations.
+  if (PrevDecl)
+    mergeDeclAttributes(PDecl, PrevDecl);
+
+  if (!err && NumProtoRefs ) {
+    /// Check then save referenced protocols.
+    PDecl->setProtocolList((ObjCProtocolDecl**)ProtoRefs, NumProtoRefs,
+                           ProtoLocs, Context);
+  }
+
+  CheckObjCDeclScope(PDecl);
+  return ActOnObjCContainerStartDefinition(PDecl);
+}
+
+/// FindProtocolDeclaration - This routine looks up protocols and
+/// issues an error if they are not declared. It returns list of
+/// protocol declarations in its 'Protocols' argument.
+void
+Sema::FindProtocolDeclaration(bool WarnOnDeclarations,
+                              const IdentifierLocPair *ProtocolId,
+                              unsigned NumProtocols,
+                              SmallVectorImpl<Decl *> &Protocols) {
+  for (unsigned i = 0; i != NumProtocols; ++i) {
+    ObjCProtocolDecl *PDecl = LookupProtocol(ProtocolId[i].first,
+                                             ProtocolId[i].second);
+    if (!PDecl) {
+      DeclFilterCCC<ObjCProtocolDecl> Validator;
+      TypoCorrection Corrected = CorrectTypo(
+          DeclarationNameInfo(ProtocolId[i].first, ProtocolId[i].second),
+          LookupObjCProtocolName, TUScope, NULL, Validator);
+      if ((PDecl = Corrected.getCorrectionDeclAs<ObjCProtocolDecl>())) {
+        Diag(ProtocolId[i].second, diag::err_undeclared_protocol_suggest)
+          << ProtocolId[i].first << Corrected.getCorrection();
+        Diag(PDecl->getLocation(), diag::note_previous_decl)
+          << PDecl->getDeclName();
+      }
+    }
+
+    if (!PDecl) {
+      Diag(ProtocolId[i].second, diag::err_undeclared_protocol)
+        << ProtocolId[i].first;
+      continue;
+    }
+
+    (void)DiagnoseUseOfDecl(PDecl, ProtocolId[i].second);
+
+    // If this is a forward declaration and we are supposed to warn in this
+    // case, do it.
+    if (WarnOnDeclarations && !PDecl->hasDefinition())
+      Diag(ProtocolId[i].second, diag::warn_undef_protocolref)
+        << ProtocolId[i].first;
+    Protocols.push_back(PDecl);
+  }
+}
+
+/// DiagnoseClassExtensionDupMethods - Check for duplicate declaration of
+/// a class method in its extension.
+///
+void Sema::DiagnoseClassExtensionDupMethods(ObjCCategoryDecl *CAT,
+                                            ObjCInterfaceDecl *ID) {
+  if (!ID)
+    return;  // Possibly due to previous error
+
+  llvm::DenseMap<Selector, const ObjCMethodDecl*> MethodMap;
+  for (ObjCInterfaceDecl::method_iterator i = ID->meth_begin(),
+       e =  ID->meth_end(); i != e; ++i) {
+    ObjCMethodDecl *MD = *i;
+    MethodMap[MD->getSelector()] = MD;
+  }
+
+  if (MethodMap.empty())
+    return;
+  for (ObjCCategoryDecl::method_iterator i = CAT->meth_begin(),
+       e =  CAT->meth_end(); i != e; ++i) {
+    ObjCMethodDecl *Method = *i;
+    const ObjCMethodDecl *&PrevMethod = MethodMap[Method->getSelector()];
+    if (PrevMethod && !MatchTwoMethodDeclarations(Method, PrevMethod)) {
+      Diag(Method->getLocation(), diag::err_duplicate_method_decl)
+            << Method->getDeclName();
+      Diag(PrevMethod->getLocation(), diag::note_previous_declaration);
+    }
+  }
+}
+
+/// ActOnForwardProtocolDeclaration - Handle @protocol foo;
+Sema::DeclGroupPtrTy
+Sema::ActOnForwardProtocolDeclaration(SourceLocation AtProtocolLoc,
+                                      const IdentifierLocPair *IdentList,
+                                      unsigned NumElts,
+                                      AttributeList *attrList) {
+  SmallVector<Decl *, 8> DeclsInGroup;
+  for (unsigned i = 0; i != NumElts; ++i) {
+    IdentifierInfo *Ident = IdentList[i].first;
+    ObjCProtocolDecl *PrevDecl = LookupProtocol(Ident, IdentList[i].second,
+                                                ForRedeclaration);
+    ObjCProtocolDecl *PDecl
+      = ObjCProtocolDecl::Create(Context, CurContext, Ident, 
+                                 IdentList[i].second, AtProtocolLoc,
+                                 PrevDecl);
+        
+    PushOnScopeChains(PDecl, TUScope);
+    CheckObjCDeclScope(PDecl);
+    
+    if (attrList)
+      ProcessDeclAttributeList(TUScope, PDecl, attrList);
+    
+    if (PrevDecl)
+      mergeDeclAttributes(PDecl, PrevDecl);
+
+    DeclsInGroup.push_back(PDecl);
+  }
+
+  return BuildDeclaratorGroup(DeclsInGroup.data(), DeclsInGroup.size(), false);
+}
+
+Decl *Sema::
+ActOnStartCategoryInterface(SourceLocation AtInterfaceLoc,
+                            IdentifierInfo *ClassName, SourceLocation ClassLoc,
+                            IdentifierInfo *CategoryName,
+                            SourceLocation CategoryLoc,
+                            Decl * const *ProtoRefs,
+                            unsigned NumProtoRefs,
+                            const SourceLocation *ProtoLocs,
+                            SourceLocation EndProtoLoc) {
+  ObjCCategoryDecl *CDecl;
+  ObjCInterfaceDecl *IDecl = getObjCInterfaceDecl(ClassName, ClassLoc, true);
+
+  /// Check that class of this category is already completely declared.
+
+  if (!IDecl 
+      || RequireCompleteType(ClassLoc, Context.getObjCInterfaceType(IDecl),
+                             PDiag(diag::err_category_forward_interface)
+                               << (CategoryName == 0))) {
+    // Create an invalid ObjCCategoryDecl to serve as context for
+    // the enclosing method declarations.  We mark the decl invalid
+    // to make it clear that this isn't a valid AST.
+    CDecl = ObjCCategoryDecl::Create(Context, CurContext, AtInterfaceLoc,
+                                     ClassLoc, CategoryLoc, CategoryName,IDecl);
+    CDecl->setInvalidDecl();
+    CurContext->addDecl(CDecl);
+        
+    if (!IDecl)
+      Diag(ClassLoc, diag::err_undef_interface) << ClassName;
+    return ActOnObjCContainerStartDefinition(CDecl);
+  }
+
+  if (!CategoryName && IDecl->getImplementation()) {
+    Diag(ClassLoc, diag::err_class_extension_after_impl) << ClassName;
+    Diag(IDecl->getImplementation()->getLocation(), 
+          diag::note_implementation_declared);
+  }
+
+  if (CategoryName) {
+    /// Check for duplicate interface declaration for this category
+    ObjCCategoryDecl *CDeclChain;
+    for (CDeclChain = IDecl->getCategoryList(); CDeclChain;
+         CDeclChain = CDeclChain->getNextClassCategory()) {
+      if (CDeclChain->getIdentifier() == CategoryName) {
+        // Class extensions can be declared multiple times.
+        Diag(CategoryLoc, diag::warn_dup_category_def)
+          << ClassName << CategoryName;
+        Diag(CDeclChain->getLocation(), diag::note_previous_definition);
+        break;
+      }
+    }
+  }
+
+  CDecl = ObjCCategoryDecl::Create(Context, CurContext, AtInterfaceLoc,
+                                   ClassLoc, CategoryLoc, CategoryName, IDecl);
+  // FIXME: PushOnScopeChains?
+  CurContext->addDecl(CDecl);
+
+  if (NumProtoRefs) {
+    CDecl->setProtocolList((ObjCProtocolDecl**)ProtoRefs, NumProtoRefs, 
+                           ProtoLocs, Context);
+    // Protocols in the class extension belong to the class.
+    if (CDecl->IsClassExtension())
+     IDecl->mergeClassExtensionProtocolList((ObjCProtocolDecl**)ProtoRefs, 
+                                            NumProtoRefs, Context); 
+  }
+
+  CheckObjCDeclScope(CDecl);
+  return ActOnObjCContainerStartDefinition(CDecl);
+}
+
+/// ActOnStartCategoryImplementation - Perform semantic checks on the
+/// category implementation declaration and build an ObjCCategoryImplDecl
+/// object.
+Decl *Sema::ActOnStartCategoryImplementation(
+                      SourceLocation AtCatImplLoc,
+                      IdentifierInfo *ClassName, SourceLocation ClassLoc,
+                      IdentifierInfo *CatName, SourceLocation CatLoc) {
+  ObjCInterfaceDecl *IDecl = getObjCInterfaceDecl(ClassName, ClassLoc, true);
+  ObjCCategoryDecl *CatIDecl = 0;
+  if (IDecl && IDecl->hasDefinition()) {
+    CatIDecl = IDecl->FindCategoryDeclaration(CatName);
+    if (!CatIDecl) {
+      // Category @implementation with no corresponding @interface.
+      // Create and install one.
+      CatIDecl = ObjCCategoryDecl::Create(Context, CurContext, AtCatImplLoc,
+                                          ClassLoc, CatLoc,
+                                          CatName, IDecl);
+      CatIDecl->setImplicit();
+    }
+  }
+
+  ObjCCategoryImplDecl *CDecl =
+    ObjCCategoryImplDecl::Create(Context, CurContext, CatName, IDecl,
+                                 ClassLoc, AtCatImplLoc, CatLoc);
+  /// Check that class of this category is already completely declared.
+  if (!IDecl) {
+    Diag(ClassLoc, diag::err_undef_interface) << ClassName;
+    CDecl->setInvalidDecl();
+  } else if (RequireCompleteType(ClassLoc, Context.getObjCInterfaceType(IDecl),
+                                 diag::err_undef_interface)) {
+    CDecl->setInvalidDecl();
+  }
+
+  // FIXME: PushOnScopeChains?
+  CurContext->addDecl(CDecl);
+
+  // If the interface is deprecated/unavailable, warn/error about it.
+  if (IDecl)
+    DiagnoseUseOfDecl(IDecl, ClassLoc);
+
+  /// Check that CatName, category name, is not used in another implementation.
+  if (CatIDecl) {
+    if (CatIDecl->getImplementation()) {
+      Diag(ClassLoc, diag::err_dup_implementation_category) << ClassName
+        << CatName;
+      Diag(CatIDecl->getImplementation()->getLocation(),
+           diag::note_previous_definition);
+    } else {
+      CatIDecl->setImplementation(CDecl);
+      // Warn on implementating category of deprecated class under 
+      // -Wdeprecated-implementations flag.
+      DiagnoseObjCImplementedDeprecations(*this, 
+                                          dyn_cast<NamedDecl>(IDecl), 
+                                          CDecl->getLocation(), 2);
+    }
+  }
+
+  CheckObjCDeclScope(CDecl);
+  return ActOnObjCContainerStartDefinition(CDecl);
+}
+
+Decl *Sema::ActOnStartClassImplementation(
+                      SourceLocation AtClassImplLoc,
+                      IdentifierInfo *ClassName, SourceLocation ClassLoc,
+                      IdentifierInfo *SuperClassname,
+                      SourceLocation SuperClassLoc) {
+  ObjCInterfaceDecl* IDecl = 0;
+  // Check for another declaration kind with the same name.
+  NamedDecl *PrevDecl
+    = LookupSingleName(TUScope, ClassName, ClassLoc, LookupOrdinaryName,
+                       ForRedeclaration);
+  if (PrevDecl && !isa<ObjCInterfaceDecl>(PrevDecl)) {
+    Diag(ClassLoc, diag::err_redefinition_different_kind) << ClassName;
+    Diag(PrevDecl->getLocation(), diag::note_previous_definition);
+  } else if ((IDecl = dyn_cast_or_null<ObjCInterfaceDecl>(PrevDecl))) {
+    RequireCompleteType(ClassLoc, Context.getObjCInterfaceType(IDecl),
+                        diag::warn_undef_interface);
+  } else {
+    // We did not find anything with the name ClassName; try to correct for 
+    // typos in the class name.
+    ObjCInterfaceValidatorCCC Validator;
+    if (TypoCorrection Corrected = CorrectTypo(
+        DeclarationNameInfo(ClassName, ClassLoc), LookupOrdinaryName, TUScope,
+        NULL, Validator)) {
+      // Suggest the (potentially) correct interface name. However, put the
+      // fix-it hint itself in a separate note, since changing the name in 
+      // the warning would make the fix-it change semantics.However, don't
+      // provide a code-modification hint or use the typo name for recovery,
+      // because this is just a warning. The program may actually be correct.
+      IDecl = Corrected.getCorrectionDeclAs<ObjCInterfaceDecl>();
+      DeclarationName CorrectedName = Corrected.getCorrection();
+      Diag(ClassLoc, diag::warn_undef_interface_suggest)
+        << ClassName << CorrectedName;
+      Diag(IDecl->getLocation(), diag::note_previous_decl) << CorrectedName
+        << FixItHint::CreateReplacement(ClassLoc, CorrectedName.getAsString());
+      IDecl = 0;
+    } else {
+      Diag(ClassLoc, diag::warn_undef_interface) << ClassName;
+    }
+  }
+
+  // Check that super class name is valid class name
+  ObjCInterfaceDecl* SDecl = 0;
+  if (SuperClassname) {
+    // Check if a different kind of symbol declared in this scope.
+    PrevDecl = LookupSingleName(TUScope, SuperClassname, SuperClassLoc,
+                                LookupOrdinaryName);
+    if (PrevDecl && !isa<ObjCInterfaceDecl>(PrevDecl)) {
+      Diag(SuperClassLoc, diag::err_redefinition_different_kind)
+        << SuperClassname;
+      Diag(PrevDecl->getLocation(), diag::note_previous_definition);
+    } else {
+      SDecl = dyn_cast_or_null<ObjCInterfaceDecl>(PrevDecl);
+      if (SDecl && !SDecl->hasDefinition())
+        SDecl = 0;
+      if (!SDecl)
+        Diag(SuperClassLoc, diag::err_undef_superclass)
+          << SuperClassname << ClassName;
+      else if (IDecl && !declaresSameEntity(IDecl->getSuperClass(), SDecl)) {
+        // This implementation and its interface do not have the same
+        // super class.
+        Diag(SuperClassLoc, diag::err_conflicting_super_class)
+          << SDecl->getDeclName();
+        Diag(SDecl->getLocation(), diag::note_previous_definition);
+      }
+    }
+  }
+
+  if (!IDecl) {
+    // Legacy case of @implementation with no corresponding @interface.
+    // Build, chain & install the interface decl into the identifier.
+
+    // FIXME: Do we support attributes on the @implementation? If so we should
+    // copy them over.
+    IDecl = ObjCInterfaceDecl::Create(Context, CurContext, AtClassImplLoc,
+                                      ClassName, /*PrevDecl=*/0, ClassLoc, 
+                                      true);
+    IDecl->startDefinition();
+    if (SDecl) {
+      IDecl->setSuperClass(SDecl);
+      IDecl->setSuperClassLoc(SuperClassLoc);
+      IDecl->setEndOfDefinitionLoc(SuperClassLoc);
+    } else {
+      IDecl->setEndOfDefinitionLoc(ClassLoc);
+    }
+    
+    PushOnScopeChains(IDecl, TUScope);
+  } else {
+    // Mark the interface as being completed, even if it was just as
+    //   @class ....;
+    // declaration; the user cannot reopen it.
+    if (!IDecl->hasDefinition())
+      IDecl->startDefinition();
+  }
+
+  ObjCImplementationDecl* IMPDecl =
+    ObjCImplementationDecl::Create(Context, CurContext, IDecl, SDecl,
+                                   ClassLoc, AtClassImplLoc);
+
+  if (CheckObjCDeclScope(IMPDecl))
+    return ActOnObjCContainerStartDefinition(IMPDecl);
+
+  // Check that there is no duplicate implementation of this class.
+  if (IDecl->getImplementation()) {
+    // FIXME: Don't leak everything!
+    Diag(ClassLoc, diag::err_dup_implementation_class) << ClassName;
+    Diag(IDecl->getImplementation()->getLocation(),
+         diag::note_previous_definition);
+  } else { // add it to the list.
+    IDecl->setImplementation(IMPDecl);
+    PushOnScopeChains(IMPDecl, TUScope);
+    // Warn on implementating deprecated class under 
+    // -Wdeprecated-implementations flag.
+    DiagnoseObjCImplementedDeprecations(*this, 
+                                        dyn_cast<NamedDecl>(IDecl), 
+                                        IMPDecl->getLocation(), 1);
+  }
+  return ActOnObjCContainerStartDefinition(IMPDecl);
+}
+
+Sema::DeclGroupPtrTy
+Sema::ActOnFinishObjCImplementation(Decl *ObjCImpDecl, ArrayRef<Decl *> Decls) {
+  SmallVector<Decl *, 64> DeclsInGroup;
+  DeclsInGroup.reserve(Decls.size() + 1);
+
+  for (unsigned i = 0, e = Decls.size(); i != e; ++i) {
+    Decl *Dcl = Decls[i];
+    if (!Dcl)
+      continue;
+    if (Dcl->getDeclContext()->isFileContext())
+      Dcl->setTopLevelDeclInObjCContainer();
+    DeclsInGroup.push_back(Dcl);
+  }
+
+  DeclsInGroup.push_back(ObjCImpDecl);
+
+  return BuildDeclaratorGroup(DeclsInGroup.data(), DeclsInGroup.size(), false);
+}
+
+void Sema::CheckImplementationIvars(ObjCImplementationDecl *ImpDecl,
+                                    ObjCIvarDecl **ivars, unsigned numIvars,
+                                    SourceLocation RBrace) {
+  assert(ImpDecl && "missing implementation decl");
+  ObjCInterfaceDecl* IDecl = ImpDecl->getClassInterface();
+  if (!IDecl)
+    return;
+  /// Check case of non-existing @interface decl.
+  /// (legacy objective-c @implementation decl without an @interface decl).
+  /// Add implementations's ivar to the synthesize class's ivar list.
+  if (IDecl->isImplicitInterfaceDecl()) {
+    IDecl->setEndOfDefinitionLoc(RBrace);
+    // Add ivar's to class's DeclContext.
+    for (unsigned i = 0, e = numIvars; i != e; ++i) {
+      ivars[i]->setLexicalDeclContext(ImpDecl);
+      IDecl->makeDeclVisibleInContext(ivars[i]);
+      ImpDecl->addDecl(ivars[i]);
+    }
+    
+    return;
+  }
+  // If implementation has empty ivar list, just return.
+  if (numIvars == 0)
+    return;
+
+  assert(ivars && "missing @implementation ivars");
+  if (LangOpts.ObjCNonFragileABI2) {
+    if (ImpDecl->getSuperClass())
+      Diag(ImpDecl->getLocation(), diag::warn_on_superclass_use);
+    for (unsigned i = 0; i < numIvars; i++) {
+      ObjCIvarDecl* ImplIvar = ivars[i];
+      if (const ObjCIvarDecl *ClsIvar = 
+            IDecl->getIvarDecl(ImplIvar->getIdentifier())) {
+        Diag(ImplIvar->getLocation(), diag::err_duplicate_ivar_declaration); 
+        Diag(ClsIvar->getLocation(), diag::note_previous_definition);
+        continue;
+      }
+      // Instance ivar to Implementation's DeclContext.
+      ImplIvar->setLexicalDeclContext(ImpDecl);
+      IDecl->makeDeclVisibleInContext(ImplIvar);
+      ImpDecl->addDecl(ImplIvar);
+    }
+    return;
+  }
+  // Check interface's Ivar list against those in the implementation.
+  // names and types must match.
+  //
+  unsigned j = 0;
+  ObjCInterfaceDecl::ivar_iterator
+    IVI = IDecl->ivar_begin(), IVE = IDecl->ivar_end();
+  for (; numIvars > 0 && IVI != IVE; ++IVI) {
+    ObjCIvarDecl* ImplIvar = ivars[j++];
+    ObjCIvarDecl* ClsIvar = *IVI;
+    assert (ImplIvar && "missing implementation ivar");
+    assert (ClsIvar && "missing class ivar");
+
+    // First, make sure the types match.
+    if (!Context.hasSameType(ImplIvar->getType(), ClsIvar->getType())) {
+      Diag(ImplIvar->getLocation(), diag::err_conflicting_ivar_type)
+        << ImplIvar->getIdentifier()
+        << ImplIvar->getType() << ClsIvar->getType();
+      Diag(ClsIvar->getLocation(), diag::note_previous_definition);
+    } else if (ImplIvar->isBitField() && ClsIvar->isBitField() &&
+               ImplIvar->getBitWidthValue(Context) !=
+               ClsIvar->getBitWidthValue(Context)) {
+      Diag(ImplIvar->getBitWidth()->getLocStart(),
+           diag::err_conflicting_ivar_bitwidth) << ImplIvar->getIdentifier();
+      Diag(ClsIvar->getBitWidth()->getLocStart(),
+           diag::note_previous_definition);
+    }
+    // Make sure the names are identical.
+    if (ImplIvar->getIdentifier() != ClsIvar->getIdentifier()) {
+      Diag(ImplIvar->getLocation(), diag::err_conflicting_ivar_name)
+        << ImplIvar->getIdentifier() << ClsIvar->getIdentifier();
+      Diag(ClsIvar->getLocation(), diag::note_previous_definition);
+    }
+    --numIvars;
+  }
+
+  if (numIvars > 0)
+    Diag(ivars[j]->getLocation(), diag::err_inconsistant_ivar_count);
+  else if (IVI != IVE)
+    Diag((*IVI)->getLocation(), diag::err_inconsistant_ivar_count);
+}
+
+void Sema::WarnUndefinedMethod(SourceLocation ImpLoc, ObjCMethodDecl *method,
+                               bool &IncompleteImpl, unsigned DiagID) {
+  // No point warning no definition of method which is 'unavailable'.
+  if (method->hasAttr<UnavailableAttr>())
+    return;
+  if (!IncompleteImpl) {
+    Diag(ImpLoc, diag::warn_incomplete_impl);
+    IncompleteImpl = true;
+  }
+  if (DiagID == diag::warn_unimplemented_protocol_method)
+    Diag(ImpLoc, DiagID) << method->getDeclName();
+  else
+    Diag(method->getLocation(), DiagID) << method->getDeclName();
+}
+
+/// Determines if type B can be substituted for type A.  Returns true if we can
+/// guarantee that anything that the user will do to an object of type A can 
+/// also be done to an object of type B.  This is trivially true if the two 
+/// types are the same, or if B is a subclass of A.  It becomes more complex
+/// in cases where protocols are involved.
+///
+/// Object types in Objective-C describe the minimum requirements for an
+/// object, rather than providing a complete description of a type.  For
+/// example, if A is a subclass of B, then B* may refer to an instance of A.
+/// The principle of substitutability means that we may use an instance of A
+/// anywhere that we may use an instance of B - it will implement all of the
+/// ivars of B and all of the methods of B.  
+///
+/// This substitutability is important when type checking methods, because 
+/// the implementation may have stricter type definitions than the interface.
+/// The interface specifies minimum requirements, but the implementation may
+/// have more accurate ones.  For example, a method may privately accept 
+/// instances of B, but only publish that it accepts instances of A.  Any
+/// object passed to it will be type checked against B, and so will implicitly
+/// by a valid A*.  Similarly, a method may return a subclass of the class that
+/// it is declared as returning.
+///
+/// This is most important when considering subclassing.  A method in a
+/// subclass must accept any object as an argument that its superclass's
+/// implementation accepts.  It may, however, accept a more general type
+/// without breaking substitutability (i.e. you can still use the subclass
+/// anywhere that you can use the superclass, but not vice versa).  The
+/// converse requirement applies to return types: the return type for a
+/// subclass method must be a valid object of the kind that the superclass
+/// advertises, but it may be specified more accurately.  This avoids the need
+/// for explicit down-casting by callers.
+///
+/// Note: This is a stricter requirement than for assignment.  
+static bool isObjCTypeSubstitutable(ASTContext &Context,
+                                    const ObjCObjectPointerType *A,
+                                    const ObjCObjectPointerType *B,
+                                    bool rejectId) {
+  // Reject a protocol-unqualified id.
+  if (rejectId && B->isObjCIdType()) return false;
+
+  // If B is a qualified id, then A must also be a qualified id and it must
+  // implement all of the protocols in B.  It may not be a qualified class.
+  // For example, MyClass<A> can be assigned to id<A>, but MyClass<A> is a
+  // stricter definition so it is not substitutable for id<A>.
+  if (B->isObjCQualifiedIdType()) {
+    return A->isObjCQualifiedIdType() &&
+           Context.ObjCQualifiedIdTypesAreCompatible(QualType(A, 0),
+                                                     QualType(B,0),
+                                                     false);
+  }
+
+  /*
+  // id is a special type that bypasses type checking completely.  We want a
+  // warning when it is used in one place but not another.
+  if (C.isObjCIdType(A) || C.isObjCIdType(B)) return false;
+
+
+  // If B is a qualified id, then A must also be a qualified id (which it isn't
+  // if we've got this far)
+  if (B->isObjCQualifiedIdType()) return false;
+  */
+
+  // Now we know that A and B are (potentially-qualified) class types.  The
+  // normal rules for assignment apply.
+  return Context.canAssignObjCInterfaces(A, B);
+}
+
+static SourceRange getTypeRange(TypeSourceInfo *TSI) {
+  return (TSI ? TSI->getTypeLoc().getSourceRange() : SourceRange());
+}
+
+static bool CheckMethodOverrideReturn(Sema &S,
+                                      ObjCMethodDecl *MethodImpl,
+                                      ObjCMethodDecl *MethodDecl,
+                                      bool IsProtocolMethodDecl,
+                                      bool IsOverridingMode,
+                                      bool Warn) {
+  if (IsProtocolMethodDecl &&
+      (MethodDecl->getObjCDeclQualifier() !=
+       MethodImpl->getObjCDeclQualifier())) {
+    if (Warn) {
+        S.Diag(MethodImpl->getLocation(), 
+               (IsOverridingMode ? 
+                 diag::warn_conflicting_overriding_ret_type_modifiers 
+                 : diag::warn_conflicting_ret_type_modifiers))
+          << MethodImpl->getDeclName()
+          << getTypeRange(MethodImpl->getResultTypeSourceInfo());
+        S.Diag(MethodDecl->getLocation(), diag::note_previous_declaration)
+          << getTypeRange(MethodDecl->getResultTypeSourceInfo());
+    }
+    else
+      return false;
+  }
+  
+  if (S.Context.hasSameUnqualifiedType(MethodImpl->getResultType(),
+                                       MethodDecl->getResultType()))
+    return true;
+  if (!Warn)
+    return false;
+
+  unsigned DiagID = 
+    IsOverridingMode ? diag::warn_conflicting_overriding_ret_types 
+                     : diag::warn_conflicting_ret_types;
+
+  // Mismatches between ObjC pointers go into a different warning
+  // category, and sometimes they're even completely whitelisted.
+  if (const ObjCObjectPointerType *ImplPtrTy =
+        MethodImpl->getResultType()->getAs<ObjCObjectPointerType>()) {
+    if (const ObjCObjectPointerType *IfacePtrTy =
+          MethodDecl->getResultType()->getAs<ObjCObjectPointerType>()) {
+      // Allow non-matching return types as long as they don't violate
+      // the principle of substitutability.  Specifically, we permit
+      // return types that are subclasses of the declared return type,
+      // or that are more-qualified versions of the declared type.
+      if (isObjCTypeSubstitutable(S.Context, IfacePtrTy, ImplPtrTy, false))
+        return false;
+
+      DiagID = 
+        IsOverridingMode ? diag::warn_non_covariant_overriding_ret_types 
+                          : diag::warn_non_covariant_ret_types;
+    }
+  }
+
+  S.Diag(MethodImpl->getLocation(), DiagID)
+    << MethodImpl->getDeclName()
+    << MethodDecl->getResultType()
+    << MethodImpl->getResultType()
+    << getTypeRange(MethodImpl->getResultTypeSourceInfo());
+  S.Diag(MethodDecl->getLocation(), 
+         IsOverridingMode ? diag::note_previous_declaration 
+                          : diag::note_previous_definition)
+    << getTypeRange(MethodDecl->getResultTypeSourceInfo());
+  return false;
+}
+
+static bool CheckMethodOverrideParam(Sema &S,
+                                     ObjCMethodDecl *MethodImpl,
+                                     ObjCMethodDecl *MethodDecl,
+                                     ParmVarDecl *ImplVar,
+                                     ParmVarDecl *IfaceVar,
+                                     bool IsProtocolMethodDecl,
+                                     bool IsOverridingMode,
+                                     bool Warn) {
+  if (IsProtocolMethodDecl &&
+      (ImplVar->getObjCDeclQualifier() !=
+       IfaceVar->getObjCDeclQualifier())) {
+    if (Warn) {
+      if (IsOverridingMode)
+        S.Diag(ImplVar->getLocation(), 
+               diag::warn_conflicting_overriding_param_modifiers)
+            << getTypeRange(ImplVar->getTypeSourceInfo())
+            << MethodImpl->getDeclName();
+      else S.Diag(ImplVar->getLocation(), 
+             diag::warn_conflicting_param_modifiers)
+          << getTypeRange(ImplVar->getTypeSourceInfo())
+          << MethodImpl->getDeclName();
+      S.Diag(IfaceVar->getLocation(), diag::note_previous_declaration)
+          << getTypeRange(IfaceVar->getTypeSourceInfo());   
+    }
+    else
+      return false;
+  }
+      
+  QualType ImplTy = ImplVar->getType();
+  QualType IfaceTy = IfaceVar->getType();
+  
+  if (S.Context.hasSameUnqualifiedType(ImplTy, IfaceTy))
+    return true;
+  
+  if (!Warn)
+    return false;
+  unsigned DiagID = 
+    IsOverridingMode ? diag::warn_conflicting_overriding_param_types 
+                     : diag::warn_conflicting_param_types;
+
+  // Mismatches between ObjC pointers go into a different warning
+  // category, and sometimes they're even completely whitelisted.
+  if (const ObjCObjectPointerType *ImplPtrTy =
+        ImplTy->getAs<ObjCObjectPointerType>()) {
+    if (const ObjCObjectPointerType *IfacePtrTy =
+          IfaceTy->getAs<ObjCObjectPointerType>()) {
+      // Allow non-matching argument types as long as they don't
+      // violate the principle of substitutability.  Specifically, the
+      // implementation must accept any objects that the superclass
+      // accepts, however it may also accept others.
+      if (isObjCTypeSubstitutable(S.Context, ImplPtrTy, IfacePtrTy, true))
+        return false;
+
+      DiagID = 
+      IsOverridingMode ? diag::warn_non_contravariant_overriding_param_types 
+                       :  diag::warn_non_contravariant_param_types;
+    }
+  }
+
+  S.Diag(ImplVar->getLocation(), DiagID)
+    << getTypeRange(ImplVar->getTypeSourceInfo())
+    << MethodImpl->getDeclName() << IfaceTy << ImplTy;
+  S.Diag(IfaceVar->getLocation(), 
+         (IsOverridingMode ? diag::note_previous_declaration 
+                        : diag::note_previous_definition))
+    << getTypeRange(IfaceVar->getTypeSourceInfo());
+  return false;
+}
+
+/// In ARC, check whether the conventional meanings of the two methods
+/// match.  If they don't, it's a hard error.
+static bool checkMethodFamilyMismatch(Sema &S, ObjCMethodDecl *impl,
+                                      ObjCMethodDecl *decl) {
+  ObjCMethodFamily implFamily = impl->getMethodFamily();
+  ObjCMethodFamily declFamily = decl->getMethodFamily();
+  if (implFamily == declFamily) return false;
+
+  // Since conventions are sorted by selector, the only possibility is
+  // that the types differ enough to cause one selector or the other
+  // to fall out of the family.
+  assert(implFamily == OMF_None || declFamily == OMF_None);
+
+  // No further diagnostics required on invalid declarations.
+  if (impl->isInvalidDecl() || decl->isInvalidDecl()) return true;
+
+  const ObjCMethodDecl *unmatched = impl;
+  ObjCMethodFamily family = declFamily;
+  unsigned errorID = diag::err_arc_lost_method_convention;
+  unsigned noteID = diag::note_arc_lost_method_convention;
+  if (declFamily == OMF_None) {
+    unmatched = decl;
+    family = implFamily;
+    errorID = diag::err_arc_gained_method_convention;
+    noteID = diag::note_arc_gained_method_convention;
+  }
+
+  // Indexes into a %select clause in the diagnostic.
+  enum FamilySelector {
+    F_alloc, F_copy, F_mutableCopy = F_copy, F_init, F_new
+  };
+  FamilySelector familySelector = FamilySelector();
+
+  switch (family) {
+  case OMF_None: llvm_unreachable("logic error, no method convention");
+  case OMF_retain:
+  case OMF_release:
+  case OMF_autorelease:
+  case OMF_dealloc:
+  case OMF_finalize:
+  case OMF_retainCount:
+  case OMF_self:
+  case OMF_performSelector:
+    // Mismatches for these methods don't change ownership
+    // conventions, so we don't care.
+    return false;
+
+  case OMF_init: familySelector = F_init; break;
+  case OMF_alloc: familySelector = F_alloc; break;
+  case OMF_copy: familySelector = F_copy; break;
+  case OMF_mutableCopy: familySelector = F_mutableCopy; break;
+  case OMF_new: familySelector = F_new; break;
+  }
+
+  enum ReasonSelector { R_NonObjectReturn, R_UnrelatedReturn };
+  ReasonSelector reasonSelector;
+
+  // The only reason these methods don't fall within their families is
+  // due to unusual result types.
+  if (unmatched->getResultType()->isObjCObjectPointerType()) {
+    reasonSelector = R_UnrelatedReturn;
+  } else {
+    reasonSelector = R_NonObjectReturn;
+  }
+
+  S.Diag(impl->getLocation(), errorID) << familySelector << reasonSelector;
+  S.Diag(decl->getLocation(), noteID) << familySelector << reasonSelector;
+
+  return true;
+}
+
+void Sema::WarnConflictingTypedMethods(ObjCMethodDecl *ImpMethodDecl,
+                                       ObjCMethodDecl *MethodDecl,
+                                       bool IsProtocolMethodDecl) {
+  if (getLangOpts().ObjCAutoRefCount &&
+      checkMethodFamilyMismatch(*this, ImpMethodDecl, MethodDecl))
+    return;
+
+  CheckMethodOverrideReturn(*this, ImpMethodDecl, MethodDecl, 
+                            IsProtocolMethodDecl, false, 
+                            true);
+
+  for (ObjCMethodDecl::param_iterator IM = ImpMethodDecl->param_begin(),
+       IF = MethodDecl->param_begin(), EM = ImpMethodDecl->param_end();
+       IM != EM; ++IM, ++IF) {
+    CheckMethodOverrideParam(*this, ImpMethodDecl, MethodDecl, *IM, *IF,
+                             IsProtocolMethodDecl, false, true);
+  }
+
+  if (ImpMethodDecl->isVariadic() != MethodDecl->isVariadic()) {
+    Diag(ImpMethodDecl->getLocation(), 
+         diag::warn_conflicting_variadic);
+    Diag(MethodDecl->getLocation(), diag::note_previous_declaration);
+  }
+}
+
+void Sema::CheckConflictingOverridingMethod(ObjCMethodDecl *Method,
+                                       ObjCMethodDecl *Overridden,
+                                       bool IsProtocolMethodDecl) {
+  
+  CheckMethodOverrideReturn(*this, Method, Overridden, 
+                            IsProtocolMethodDecl, true, 
+                            true);
+  
+  for (ObjCMethodDecl::param_iterator IM = Method->param_begin(),
+       IF = Overridden->param_begin(), EM = Method->param_end();
+       IM != EM; ++IM, ++IF) {
+    CheckMethodOverrideParam(*this, Method, Overridden, *IM, *IF,
+                             IsProtocolMethodDecl, true, true);
+  }
+  
+  if (Method->isVariadic() != Overridden->isVariadic()) {
+    Diag(Method->getLocation(), 
+         diag::warn_conflicting_overriding_variadic);
+    Diag(Overridden->getLocation(), diag::note_previous_declaration);
+  }
+}
+
+/// WarnExactTypedMethods - This routine issues a warning if method
+/// implementation declaration matches exactly that of its declaration.
+void Sema::WarnExactTypedMethods(ObjCMethodDecl *ImpMethodDecl,
+                                 ObjCMethodDecl *MethodDecl,
+                                 bool IsProtocolMethodDecl) {
+  // don't issue warning when protocol method is optional because primary
+  // class is not required to implement it and it is safe for protocol
+  // to implement it.
+  if (MethodDecl->getImplementationControl() == ObjCMethodDecl::Optional)
+    return;
+  // don't issue warning when primary class's method is 
+  // depecated/unavailable.
+  if (MethodDecl->hasAttr<UnavailableAttr>() ||
+      MethodDecl->hasAttr<DeprecatedAttr>())
+    return;
+  
+  bool match = CheckMethodOverrideReturn(*this, ImpMethodDecl, MethodDecl, 
+                                      IsProtocolMethodDecl, false, false);
+  if (match)
+    for (ObjCMethodDecl::param_iterator IM = ImpMethodDecl->param_begin(),
+         IF = MethodDecl->param_begin(), EM = ImpMethodDecl->param_end();
+         IM != EM; ++IM, ++IF) {
+      match = CheckMethodOverrideParam(*this, ImpMethodDecl, MethodDecl, 
+                                       *IM, *IF,
+                                       IsProtocolMethodDecl, false, false);
+      if (!match)
+        break;
+    }
+  if (match)
+    match = (ImpMethodDecl->isVariadic() == MethodDecl->isVariadic());
+  if (match)
+    match = !(MethodDecl->isClassMethod() &&
+              MethodDecl->getSelector() == GetNullarySelector("load", Context));
+  
+  if (match) {
+    Diag(ImpMethodDecl->getLocation(), 
+         diag::warn_category_method_impl_match);
+    Diag(MethodDecl->getLocation(), diag::note_method_declared_at)
+      << MethodDecl->getDeclName();
+  }
+}
+
+/// FIXME: Type hierarchies in Objective-C can be deep. We could most likely
+/// improve the efficiency of selector lookups and type checking by associating
+/// with each protocol / interface / category the flattened instance tables. If
+/// we used an immutable set to keep the table then it wouldn't add significant
+/// memory cost and it would be handy for lookups.
+
+/// CheckProtocolMethodDefs - This routine checks unimplemented methods
+/// Declared in protocol, and those referenced by it.
+void Sema::CheckProtocolMethodDefs(SourceLocation ImpLoc,
+                                   ObjCProtocolDecl *PDecl,
+                                   bool& IncompleteImpl,
+                                   const llvm::DenseSet<Selector> &InsMap,
+                                   const llvm::DenseSet<Selector> &ClsMap,
+                                   ObjCContainerDecl *CDecl) {
+  ObjCCategoryDecl *C = dyn_cast<ObjCCategoryDecl>(CDecl);
+  ObjCInterfaceDecl *IDecl = C ? C->getClassInterface() 
+                               : dyn_cast<ObjCInterfaceDecl>(CDecl);
+  assert (IDecl && "CheckProtocolMethodDefs - IDecl is null");
+  
+  ObjCInterfaceDecl *Super = IDecl->getSuperClass();
+  ObjCInterfaceDecl *NSIDecl = 0;
+  if (getLangOpts().NeXTRuntime) {
+    // check to see if class implements forwardInvocation method and objects
+    // of this class are derived from 'NSProxy' so that to forward requests
+    // from one object to another.
+    // Under such conditions, which means that every method possible is
+    // implemented in the class, we should not issue "Method definition not
+    // found" warnings.
+    // FIXME: Use a general GetUnarySelector method for this.
+    IdentifierInfo* II = &Context.Idents.get("forwardInvocation");
+    Selector fISelector = Context.Selectors.getSelector(1, &II);
+    if (InsMap.count(fISelector))
+      // Is IDecl derived from 'NSProxy'? If so, no instance methods
+      // need be implemented in the implementation.
+      NSIDecl = IDecl->lookupInheritedClass(&Context.Idents.get("NSProxy"));
+  }
+
+  // If a method lookup fails locally we still need to look and see if
+  // the method was implemented by a base class or an inherited
+  // protocol. This lookup is slow, but occurs rarely in correct code
+  // and otherwise would terminate in a warning.
+
+  // check unimplemented instance methods.
+  if (!NSIDecl)
+    for (ObjCProtocolDecl::instmeth_iterator I = PDecl->instmeth_begin(),
+         E = PDecl->instmeth_end(); I != E; ++I) {
+      ObjCMethodDecl *method = *I;
+      if (method->getImplementationControl() != ObjCMethodDecl::Optional &&
+          !method->isSynthesized() && !InsMap.count(method->getSelector()) &&
+          (!Super ||
+           !Super->lookupInstanceMethod(method->getSelector()))) {
+            // If a method is not implemented in the category implementation but
+            // has been declared in its primary class, superclass,
+            // or in one of their protocols, no need to issue the warning. 
+            // This is because method will be implemented in the primary class 
+            // or one of its super class implementation.
+            
+            // Ugly, but necessary. Method declared in protcol might have
+            // have been synthesized due to a property declared in the class which
+            // uses the protocol.
+            if (ObjCMethodDecl *MethodInClass =
+                  IDecl->lookupInstanceMethod(method->getSelector(), 
+                                              true /*shallowCategoryLookup*/))
+              if (C || MethodInClass->isSynthesized())
+                continue;
+            unsigned DIAG = diag::warn_unimplemented_protocol_method;
+            if (Diags.getDiagnosticLevel(DIAG, ImpLoc)
+                != DiagnosticsEngine::Ignored) {
+              WarnUndefinedMethod(ImpLoc, method, IncompleteImpl, DIAG);
+              Diag(method->getLocation(), diag::note_method_declared_at)
+                << method->getDeclName();
+              Diag(CDecl->getLocation(), diag::note_required_for_protocol_at)
+                << PDecl->getDeclName();
+            }
+          }
+    }
+  // check unimplemented class methods
+  for (ObjCProtocolDecl::classmeth_iterator
+         I = PDecl->classmeth_begin(), E = PDecl->classmeth_end();
+       I != E; ++I) {
+    ObjCMethodDecl *method = *I;
+    if (method->getImplementationControl() != ObjCMethodDecl::Optional &&
+        !ClsMap.count(method->getSelector()) &&
+        (!Super || !Super->lookupClassMethod(method->getSelector()))) {
+      // See above comment for instance method lookups.
+      if (C && IDecl->lookupClassMethod(method->getSelector(), 
+                                        true /*shallowCategoryLookup*/))
+        continue;
+      unsigned DIAG = diag::warn_unimplemented_protocol_method;
+      if (Diags.getDiagnosticLevel(DIAG, ImpLoc) !=
+            DiagnosticsEngine::Ignored) {
+        WarnUndefinedMethod(ImpLoc, method, IncompleteImpl, DIAG);
+        Diag(method->getLocation(), diag::note_method_declared_at)
+          << method->getDeclName();
+        Diag(IDecl->getLocation(), diag::note_required_for_protocol_at) <<
+          PDecl->getDeclName();
+      }
+    }
+  }
+  // Check on this protocols's referenced protocols, recursively.
+  for (ObjCProtocolDecl::protocol_iterator PI = PDecl->protocol_begin(),
+       E = PDecl->protocol_end(); PI != E; ++PI)
+    CheckProtocolMethodDefs(ImpLoc, *PI, IncompleteImpl, InsMap, ClsMap, CDecl);
+}
+
+/// MatchAllMethodDeclarations - Check methods declared in interface
+/// or protocol against those declared in their implementations.
+///
+void Sema::MatchAllMethodDeclarations(const llvm::DenseSet<Selector> &InsMap,
+                                      const llvm::DenseSet<Selector> &ClsMap,
+                                      llvm::DenseSet<Selector> &InsMapSeen,
+                                      llvm::DenseSet<Selector> &ClsMapSeen,
+                                      ObjCImplDecl* IMPDecl,
+                                      ObjCContainerDecl* CDecl,
+                                      bool &IncompleteImpl,
+                                      bool ImmediateClass,
+                                      bool WarnCategoryMethodImpl) {
+  // Check and see if instance methods in class interface have been
+  // implemented in the implementation class. If so, their types match.
+  for (ObjCInterfaceDecl::instmeth_iterator I = CDecl->instmeth_begin(),
+       E = CDecl->instmeth_end(); I != E; ++I) {
+    if (InsMapSeen.count((*I)->getSelector()))
+        continue;
+    InsMapSeen.insert((*I)->getSelector());
+    if (!(*I)->isSynthesized() &&
+        !InsMap.count((*I)->getSelector())) {
+      if (ImmediateClass)
+        WarnUndefinedMethod(IMPDecl->getLocation(), *I, IncompleteImpl,
+                            diag::note_undef_method_impl);
+      continue;
+    } else {
+      ObjCMethodDecl *ImpMethodDecl =
+        IMPDecl->getInstanceMethod((*I)->getSelector());
+      assert(CDecl->getInstanceMethod((*I)->getSelector()) &&
+             "Expected to find the method through lookup as well");
+      ObjCMethodDecl *MethodDecl = *I;
+      // ImpMethodDecl may be null as in a @dynamic property.
+      if (ImpMethodDecl) {
+        if (!WarnCategoryMethodImpl)
+          WarnConflictingTypedMethods(ImpMethodDecl, MethodDecl,
+                                      isa<ObjCProtocolDecl>(CDecl));
+        else if (!MethodDecl->isSynthesized())
+          WarnExactTypedMethods(ImpMethodDecl, MethodDecl,
+                                isa<ObjCProtocolDecl>(CDecl));
+      }
+    }
+  }
+
+  // Check and see if class methods in class interface have been
+  // implemented in the implementation class. If so, their types match.
+   for (ObjCInterfaceDecl::classmeth_iterator
+       I = CDecl->classmeth_begin(), E = CDecl->classmeth_end(); I != E; ++I) {
+     if (ClsMapSeen.count((*I)->getSelector()))
+       continue;
+     ClsMapSeen.insert((*I)->getSelector());
+    if (!ClsMap.count((*I)->getSelector())) {
+      if (ImmediateClass)
+        WarnUndefinedMethod(IMPDecl->getLocation(), *I, IncompleteImpl,
+                            diag::note_undef_method_impl);
+    } else {
+      ObjCMethodDecl *ImpMethodDecl =
+        IMPDecl->getClassMethod((*I)->getSelector());
+      assert(CDecl->getClassMethod((*I)->getSelector()) &&
+             "Expected to find the method through lookup as well");
+      ObjCMethodDecl *MethodDecl = *I;
+      if (!WarnCategoryMethodImpl)
+        WarnConflictingTypedMethods(ImpMethodDecl, MethodDecl, 
+                                    isa<ObjCProtocolDecl>(CDecl));
+      else
+        WarnExactTypedMethods(ImpMethodDecl, MethodDecl,
+                              isa<ObjCProtocolDecl>(CDecl));
+    }
+  }
+  
+  if (ObjCInterfaceDecl *I = dyn_cast<ObjCInterfaceDecl> (CDecl)) {
+    // Also methods in class extensions need be looked at next.
+    for (const ObjCCategoryDecl *ClsExtDecl = I->getFirstClassExtension(); 
+         ClsExtDecl; ClsExtDecl = ClsExtDecl->getNextClassExtension())
+      MatchAllMethodDeclarations(InsMap, ClsMap, InsMapSeen, ClsMapSeen,
+                                 IMPDecl,
+                                 const_cast<ObjCCategoryDecl *>(ClsExtDecl), 
+                                 IncompleteImpl, false, 
+                                 WarnCategoryMethodImpl);
+    
+    // Check for any implementation of a methods declared in protocol.
+    for (ObjCInterfaceDecl::all_protocol_iterator
+          PI = I->all_referenced_protocol_begin(),
+          E = I->all_referenced_protocol_end(); PI != E; ++PI)
+      MatchAllMethodDeclarations(InsMap, ClsMap, InsMapSeen, ClsMapSeen,
+                                 IMPDecl,
+                                 (*PI), IncompleteImpl, false, 
+                                 WarnCategoryMethodImpl);
+    
+    // FIXME. For now, we are not checking for extact match of methods 
+    // in category implementation and its primary class's super class. 
+    if (!WarnCategoryMethodImpl && I->getSuperClass())
+      MatchAllMethodDeclarations(InsMap, ClsMap, InsMapSeen, ClsMapSeen,
+                                 IMPDecl,
+                                 I->getSuperClass(), IncompleteImpl, false);
+  }
+}
+
+/// CheckCategoryVsClassMethodMatches - Checks that methods implemented in
+/// category matches with those implemented in its primary class and
+/// warns each time an exact match is found. 
+void Sema::CheckCategoryVsClassMethodMatches(
+                                  ObjCCategoryImplDecl *CatIMPDecl) {
+  llvm::DenseSet<Selector> InsMap, ClsMap;
+  
+  for (ObjCImplementationDecl::instmeth_iterator
+       I = CatIMPDecl->instmeth_begin(), 
+       E = CatIMPDecl->instmeth_end(); I!=E; ++I)
+    InsMap.insert((*I)->getSelector());
+  
+  for (ObjCImplementationDecl::classmeth_iterator
+       I = CatIMPDecl->classmeth_begin(),
+       E = CatIMPDecl->classmeth_end(); I != E; ++I)
+    ClsMap.insert((*I)->getSelector());
+  if (InsMap.empty() && ClsMap.empty())
+    return;
+  
+  // Get category's primary class.
+  ObjCCategoryDecl *CatDecl = CatIMPDecl->getCategoryDecl();
+  if (!CatDecl)
+    return;
+  ObjCInterfaceDecl *IDecl = CatDecl->getClassInterface();
+  if (!IDecl)
+    return;
+  llvm::DenseSet<Selector> InsMapSeen, ClsMapSeen;
+  bool IncompleteImpl = false;
+  MatchAllMethodDeclarations(InsMap, ClsMap, InsMapSeen, ClsMapSeen,
+                             CatIMPDecl, IDecl,
+                             IncompleteImpl, false, 
+                             true /*WarnCategoryMethodImpl*/);
+}
+
+void Sema::ImplMethodsVsClassMethods(Scope *S, ObjCImplDecl* IMPDecl,
+                                     ObjCContainerDecl* CDecl,
+                                     bool IncompleteImpl) {
+  llvm::DenseSet<Selector> InsMap;
+  // Check and see if instance methods in class interface have been
+  // implemented in the implementation class.
+  for (ObjCImplementationDecl::instmeth_iterator
+         I = IMPDecl->instmeth_begin(), E = IMPDecl->instmeth_end(); I!=E; ++I)
+    InsMap.insert((*I)->getSelector());
+
+  // Check and see if properties declared in the interface have either 1)
+  // an implementation or 2) there is a @synthesize/@dynamic implementation
+  // of the property in the @implementation.
+  if (const ObjCInterfaceDecl *IDecl = dyn_cast<ObjCInterfaceDecl>(CDecl))
+    if  (!(LangOpts.ObjCDefaultSynthProperties && LangOpts.ObjCNonFragileABI2) ||
+      IDecl->isObjCRequiresPropertyDefs())
+      DiagnoseUnimplementedProperties(S, IMPDecl, CDecl, InsMap);
+      
+  llvm::DenseSet<Selector> ClsMap;
+  for (ObjCImplementationDecl::classmeth_iterator
+       I = IMPDecl->classmeth_begin(),
+       E = IMPDecl->classmeth_end(); I != E; ++I)
+    ClsMap.insert((*I)->getSelector());
+
+  // Check for type conflict of methods declared in a class/protocol and
+  // its implementation; if any.
+  llvm::DenseSet<Selector> InsMapSeen, ClsMapSeen;
+  MatchAllMethodDeclarations(InsMap, ClsMap, InsMapSeen, ClsMapSeen,
+                             IMPDecl, CDecl,
+                             IncompleteImpl, true);
+  
+  // check all methods implemented in category against those declared
+  // in its primary class.
+  if (ObjCCategoryImplDecl *CatDecl = 
+        dyn_cast<ObjCCategoryImplDecl>(IMPDecl))
+    CheckCategoryVsClassMethodMatches(CatDecl);
+
+  // Check the protocol list for unimplemented methods in the @implementation
+  // class.
+  // Check and see if class methods in class interface have been
+  // implemented in the implementation class.
+
+  if (ObjCInterfaceDecl *I = dyn_cast<ObjCInterfaceDecl> (CDecl)) {
+    for (ObjCInterfaceDecl::all_protocol_iterator
+          PI = I->all_referenced_protocol_begin(),
+          E = I->all_referenced_protocol_end(); PI != E; ++PI)
+      CheckProtocolMethodDefs(IMPDecl->getLocation(), *PI, IncompleteImpl,
+                              InsMap, ClsMap, I);
+    // Check class extensions (unnamed categories)
+    for (const ObjCCategoryDecl *Categories = I->getFirstClassExtension();
+         Categories; Categories = Categories->getNextClassExtension())
+      ImplMethodsVsClassMethods(S, IMPDecl, 
+                                const_cast<ObjCCategoryDecl*>(Categories), 
+                                IncompleteImpl);
+  } else if (ObjCCategoryDecl *C = dyn_cast<ObjCCategoryDecl>(CDecl)) {
+    // For extended class, unimplemented methods in its protocols will
+    // be reported in the primary class.
+    if (!C->IsClassExtension()) {
+      for (ObjCCategoryDecl::protocol_iterator PI = C->protocol_begin(),
+           E = C->protocol_end(); PI != E; ++PI)
+        CheckProtocolMethodDefs(IMPDecl->getLocation(), *PI, IncompleteImpl,
+                                InsMap, ClsMap, CDecl);
+      // Report unimplemented properties in the category as well.
+      // When reporting on missing setter/getters, do not report when
+      // setter/getter is implemented in category's primary class 
+      // implementation.
+      if (ObjCInterfaceDecl *ID = C->getClassInterface())
+        if (ObjCImplDecl *IMP = ID->getImplementation()) {
+          for (ObjCImplementationDecl::instmeth_iterator
+               I = IMP->instmeth_begin(), E = IMP->instmeth_end(); I!=E; ++I)
+            InsMap.insert((*I)->getSelector());
+        }
+      DiagnoseUnimplementedProperties(S, IMPDecl, CDecl, InsMap);      
+    } 
+  } else
+    llvm_unreachable("invalid ObjCContainerDecl type.");
+}
+
+/// ActOnForwardClassDeclaration -
+Sema::DeclGroupPtrTy
+Sema::ActOnForwardClassDeclaration(SourceLocation AtClassLoc,
+                                   IdentifierInfo **IdentList,
+                                   SourceLocation *IdentLocs,
+                                   unsigned NumElts) {
+  SmallVector<Decl *, 8> DeclsInGroup;
+  for (unsigned i = 0; i != NumElts; ++i) {
+    // Check for another declaration kind with the same name.
+    NamedDecl *PrevDecl
+      = LookupSingleName(TUScope, IdentList[i], IdentLocs[i], 
+                         LookupOrdinaryName, ForRedeclaration);
+    if (PrevDecl && PrevDecl->isTemplateParameter()) {
+      // Maybe we will complain about the shadowed template parameter.
+      DiagnoseTemplateParameterShadow(AtClassLoc, PrevDecl);
+      // Just pretend that we didn't see the previous declaration.
+      PrevDecl = 0;
+    }
+
+    if (PrevDecl && !isa<ObjCInterfaceDecl>(PrevDecl)) {
+      // GCC apparently allows the following idiom:
+      //
+      // typedef NSObject < XCElementTogglerP > XCElementToggler;
+      // @class XCElementToggler;
+      //
+      // Here we have chosen to ignore the forward class declaration
+      // with a warning. Since this is the implied behavior.
+      TypedefNameDecl *TDD = dyn_cast<TypedefNameDecl>(PrevDecl);
+      if (!TDD || !TDD->getUnderlyingType()->isObjCObjectType()) {
+        Diag(AtClassLoc, diag::err_redefinition_different_kind) << IdentList[i];
+        Diag(PrevDecl->getLocation(), diag::note_previous_definition);
+      } else {
+        // a forward class declaration matching a typedef name of a class refers
+        // to the underlying class. Just ignore the forward class with a warning
+        // as this will force the intended behavior which is to lookup the typedef
+        // name.
+        if (isa<ObjCObjectType>(TDD->getUnderlyingType())) {
+          Diag(AtClassLoc, diag::warn_forward_class_redefinition) << IdentList[i];
+          Diag(PrevDecl->getLocation(), diag::note_previous_definition);
+          continue;
+        }
+      }
+    }
+    
+    // Create a declaration to describe this forward declaration.
+    ObjCInterfaceDecl *PrevIDecl
+      = dyn_cast_or_null<ObjCInterfaceDecl>(PrevDecl);
+    ObjCInterfaceDecl *IDecl
+      = ObjCInterfaceDecl::Create(Context, CurContext, AtClassLoc,
+                                  IdentList[i], PrevIDecl, IdentLocs[i]);
+    IDecl->setAtEndRange(IdentLocs[i]);
+    
+    PushOnScopeChains(IDecl, TUScope);
+    CheckObjCDeclScope(IDecl);
+    DeclsInGroup.push_back(IDecl);
+  }
+  
+  return BuildDeclaratorGroup(DeclsInGroup.data(), DeclsInGroup.size(), false);
+}
+
+static bool tryMatchRecordTypes(ASTContext &Context,
+                                Sema::MethodMatchStrategy strategy,
+                                const Type *left, const Type *right);
+
+static bool matchTypes(ASTContext &Context, Sema::MethodMatchStrategy strategy,
+                       QualType leftQT, QualType rightQT) {
+  const Type *left =
+    Context.getCanonicalType(leftQT).getUnqualifiedType().getTypePtr();
+  const Type *right =
+    Context.getCanonicalType(rightQT).getUnqualifiedType().getTypePtr();
+
+  if (left == right) return true;
+
+  // If we're doing a strict match, the types have to match exactly.
+  if (strategy == Sema::MMS_strict) return false;
+
+  if (left->isIncompleteType() || right->isIncompleteType()) return false;
+
+  // Otherwise, use this absurdly complicated algorithm to try to
+  // validate the basic, low-level compatibility of the two types.
+
+  // As a minimum, require the sizes and alignments to match.
+  if (Context.getTypeInfo(left) != Context.getTypeInfo(right))
+    return false;
+
+  // Consider all the kinds of non-dependent canonical types:
+  // - functions and arrays aren't possible as return and parameter types
+  
+  // - vector types of equal size can be arbitrarily mixed
+  if (isa<VectorType>(left)) return isa<VectorType>(right);
+  if (isa<VectorType>(right)) return false;
+
+  // - references should only match references of identical type
+  // - structs, unions, and Objective-C objects must match more-or-less
+  //   exactly
+  // - everything else should be a scalar
+  if (!left->isScalarType() || !right->isScalarType())
+    return tryMatchRecordTypes(Context, strategy, left, right);
+
+  // Make scalars agree in kind, except count bools as chars, and group
+  // all non-member pointers together.
+  Type::ScalarTypeKind leftSK = left->getScalarTypeKind();
+  Type::ScalarTypeKind rightSK = right->getScalarTypeKind();
+  if (leftSK == Type::STK_Bool) leftSK = Type::STK_Integral;
+  if (rightSK == Type::STK_Bool) rightSK = Type::STK_Integral;
+  if (leftSK == Type::STK_CPointer || leftSK == Type::STK_BlockPointer)
+    leftSK = Type::STK_ObjCObjectPointer;
+  if (rightSK == Type::STK_CPointer || rightSK == Type::STK_BlockPointer)
+    rightSK = Type::STK_ObjCObjectPointer;
+
+  // Note that data member pointers and function member pointers don't
+  // intermix because of the size differences.
+
+  return (leftSK == rightSK);
+}
+
+static bool tryMatchRecordTypes(ASTContext &Context,
+                                Sema::MethodMatchStrategy strategy,
+                                const Type *lt, const Type *rt) {
+  assert(lt && rt && lt != rt);
+
+  if (!isa<RecordType>(lt) || !isa<RecordType>(rt)) return false;
+  RecordDecl *left = cast<RecordType>(lt)->getDecl();
+  RecordDecl *right = cast<RecordType>(rt)->getDecl();
+
+  // Require union-hood to match.
+  if (left->isUnion() != right->isUnion()) return false;
+
+  // Require an exact match if either is non-POD.
+  if ((isa<CXXRecordDecl>(left) && !cast<CXXRecordDecl>(left)->isPOD()) ||
+      (isa<CXXRecordDecl>(right) && !cast<CXXRecordDecl>(right)->isPOD()))
+    return false;
+
+  // Require size and alignment to match.
+  if (Context.getTypeInfo(lt) != Context.getTypeInfo(rt)) return false;
+
+  // Require fields to match.
+  RecordDecl::field_iterator li = left->field_begin(), le = left->field_end();
+  RecordDecl::field_iterator ri = right->field_begin(), re = right->field_end();
+  for (; li != le && ri != re; ++li, ++ri) {
+    if (!matchTypes(Context, strategy, li->getType(), ri->getType()))
+      return false;
+  }
+  return (li == le && ri == re);
+}
+
+/// MatchTwoMethodDeclarations - Checks that two methods have matching type and
+/// returns true, or false, accordingly.
+/// TODO: Handle protocol list; such as id<p1,p2> in type comparisons
+bool Sema::MatchTwoMethodDeclarations(const ObjCMethodDecl *left,
+                                      const ObjCMethodDecl *right,
+                                      MethodMatchStrategy strategy) {
+  if (!matchTypes(Context, strategy,
+                  left->getResultType(), right->getResultType()))
+    return false;
+
+  if (getLangOpts().ObjCAutoRefCount &&
+      (left->hasAttr<NSReturnsRetainedAttr>()
+         != right->hasAttr<NSReturnsRetainedAttr>() ||
+       left->hasAttr<NSConsumesSelfAttr>()
+         != right->hasAttr<NSConsumesSelfAttr>()))
+    return false;
+
+  ObjCMethodDecl::param_const_iterator
+    li = left->param_begin(), le = left->param_end(), ri = right->param_begin();
+
+  for (; li != le; ++li, ++ri) {
+    assert(ri != right->param_end() && "Param mismatch");
+    const ParmVarDecl *lparm = *li, *rparm = *ri;
+
+    if (!matchTypes(Context, strategy, lparm->getType(), rparm->getType()))
+      return false;
+
+    if (getLangOpts().ObjCAutoRefCount &&
+        lparm->hasAttr<NSConsumedAttr>() != rparm->hasAttr<NSConsumedAttr>())
+      return false;
+  }
+  return true;
+}
+
+void Sema::addMethodToGlobalList(ObjCMethodList *List, ObjCMethodDecl *Method) {
+  // If the list is empty, make it a singleton list.
+  if (List->Method == 0) {
+    List->Method = Method;
+    List->Next = 0;
+    return;
+  }
+  
+  // We've seen a method with this name, see if we have already seen this type
+  // signature.
+  ObjCMethodList *Previous = List;
+  for (; List; Previous = List, List = List->Next) {
+    if (!MatchTwoMethodDeclarations(Method, List->Method))
+      continue;
+    
+    ObjCMethodDecl *PrevObjCMethod = List->Method;
+
+    // Propagate the 'defined' bit.
+    if (Method->isDefined())
+      PrevObjCMethod->setDefined(true);
+    
+    // If a method is deprecated, push it in the global pool.
+    // This is used for better diagnostics.
+    if (Method->isDeprecated()) {
+      if (!PrevObjCMethod->isDeprecated())
+        List->Method = Method;
+    }
+    // If new method is unavailable, push it into global pool
+    // unless previous one is deprecated.
+    if (Method->isUnavailable()) {
+      if (PrevObjCMethod->getAvailability() < AR_Deprecated)
+        List->Method = Method;
+    }
+    
+    return;
+  }
+  
+  // We have a new signature for an existing method - add it.
+  // This is extremely rare. Only 1% of Cocoa selectors are "overloaded".
+  ObjCMethodList *Mem = BumpAlloc.Allocate<ObjCMethodList>();
+  Previous->Next = new (Mem) ObjCMethodList(Method, 0);
+}
+
+/// \brief Read the contents of the method pool for a given selector from
+/// external storage.
+void Sema::ReadMethodPool(Selector Sel) {
+  assert(ExternalSource && "We need an external AST source");
+  ExternalSource->ReadMethodPool(Sel);
+}
+
+void Sema::AddMethodToGlobalPool(ObjCMethodDecl *Method, bool impl,
+                                 bool instance) {
+  // Ignore methods of invalid containers.
+  if (cast<Decl>(Method->getDeclContext())->isInvalidDecl())
+    return;
+
+  if (ExternalSource)
+    ReadMethodPool(Method->getSelector());
+  
+  GlobalMethodPool::iterator Pos = MethodPool.find(Method->getSelector());
+  if (Pos == MethodPool.end())
+    Pos = MethodPool.insert(std::make_pair(Method->getSelector(),
+                                           GlobalMethods())).first;
+  
+  Method->setDefined(impl);
+  
+  ObjCMethodList &Entry = instance ? Pos->second.first : Pos->second.second;
+  addMethodToGlobalList(&Entry, Method);
+}
+
+/// Determines if this is an "acceptable" loose mismatch in the global
+/// method pool.  This exists mostly as a hack to get around certain
+/// global mismatches which we can't afford to make warnings / errors.
+/// Really, what we want is a way to take a method out of the global
+/// method pool.
+static bool isAcceptableMethodMismatch(ObjCMethodDecl *chosen,
+                                       ObjCMethodDecl *other) {
+  if (!chosen->isInstanceMethod())
+    return false;
+
+  Selector sel = chosen->getSelector();
+  if (!sel.isUnarySelector() || sel.getNameForSlot(0) != "length")
+    return false;
+
+  // Don't complain about mismatches for -length if the method we
+  // chose has an integral result type.
+  return (chosen->getResultType()->isIntegerType());
+}
+
+ObjCMethodDecl *Sema::LookupMethodInGlobalPool(Selector Sel, SourceRange R,
+                                               bool receiverIdOrClass,
+                                               bool warn, bool instance) {
+  if (ExternalSource)
+    ReadMethodPool(Sel);
+    
+  GlobalMethodPool::iterator Pos = MethodPool.find(Sel);
+  if (Pos == MethodPool.end())
+    return 0;
+
+  ObjCMethodList &MethList = instance ? Pos->second.first : Pos->second.second;
+
+  if (warn && MethList.Method && MethList.Next) {
+    bool issueDiagnostic = false, issueError = false;
+
+    // We support a warning which complains about *any* difference in
+    // method signature.
+    bool strictSelectorMatch =
+      (receiverIdOrClass && warn &&
+       (Diags.getDiagnosticLevel(diag::warn_strict_multiple_method_decl,
+                                 R.getBegin()) != 
+      DiagnosticsEngine::Ignored));
+    if (strictSelectorMatch)
+      for (ObjCMethodList *Next = MethList.Next; Next; Next = Next->Next) {
+        if (!MatchTwoMethodDeclarations(MethList.Method, Next->Method,
+                                        MMS_strict)) {
+          issueDiagnostic = true;
+          break;
+        }
+      }
+
+    // If we didn't see any strict differences, we won't see any loose
+    // differences.  In ARC, however, we also need to check for loose
+    // mismatches, because most of them are errors.
+    if (!strictSelectorMatch ||
+        (issueDiagnostic && getLangOpts().ObjCAutoRefCount))
+      for (ObjCMethodList *Next = MethList.Next; Next; Next = Next->Next) {
+        // This checks if the methods differ in type mismatch.
+        if (!MatchTwoMethodDeclarations(MethList.Method, Next->Method,
+                                        MMS_loose) &&
+            !isAcceptableMethodMismatch(MethList.Method, Next->Method)) {
+          issueDiagnostic = true;
+          if (getLangOpts().ObjCAutoRefCount)
+            issueError = true;
+          break;
+        }
+      }
+
+    if (issueDiagnostic) {
+      if (issueError)
+        Diag(R.getBegin(), diag::err_arc_multiple_method_decl) << Sel << R;
+      else if (strictSelectorMatch)
+        Diag(R.getBegin(), diag::warn_strict_multiple_method_decl) << Sel << R;
+      else
+        Diag(R.getBegin(), diag::warn_multiple_method_decl) << Sel << R;
+
+      Diag(MethList.Method->getLocStart(), 
+           issueError ? diag::note_possibility : diag::note_using)
+        << MethList.Method->getSourceRange();
+      for (ObjCMethodList *Next = MethList.Next; Next; Next = Next->Next)
+        Diag(Next->Method->getLocStart(), diag::note_also_found)
+          << Next->Method->getSourceRange();
+    }
+  }
+  return MethList.Method;
+}
+
+ObjCMethodDecl *Sema::LookupImplementedMethodInGlobalPool(Selector Sel) {
+  GlobalMethodPool::iterator Pos = MethodPool.find(Sel);
+  if (Pos == MethodPool.end())
+    return 0;
+
+  GlobalMethods &Methods = Pos->second;
+
+  if (Methods.first.Method && Methods.first.Method->isDefined())
+    return Methods.first.Method;
+  if (Methods.second.Method && Methods.second.Method->isDefined())
+    return Methods.second.Method;
+  return 0;
+}
+
+/// CompareMethodParamsInBaseAndSuper - This routine compares methods with
+/// identical selector names in current and its super classes and issues
+/// a warning if any of their argument types are incompatible.
+void Sema::CompareMethodParamsInBaseAndSuper(Decl *ClassDecl,
+                                             ObjCMethodDecl *Method,
+                                             bool IsInstance)  {
+  ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(ClassDecl);
+  if (ID == 0) return;
+
+  while (ObjCInterfaceDecl *SD = ID->getSuperClass()) {
+    ObjCMethodDecl *SuperMethodDecl =
+        SD->lookupMethod(Method->getSelector(), IsInstance);
+    if (SuperMethodDecl == 0) {
+      ID = SD;
+      continue;
+    }
+    ObjCMethodDecl::param_iterator ParamI = Method->param_begin(),
+      E = Method->param_end();
+    ObjCMethodDecl::param_iterator PrevI = SuperMethodDecl->param_begin();
+    for (; ParamI != E; ++ParamI, ++PrevI) {
+      // Number of parameters are the same and is guaranteed by selector match.
+      assert(PrevI != SuperMethodDecl->param_end() && "Param mismatch");
+      QualType T1 = Context.getCanonicalType((*ParamI)->getType());
+      QualType T2 = Context.getCanonicalType((*PrevI)->getType());
+      // If type of argument of method in this class does not match its
+      // respective argument type in the super class method, issue warning;
+      if (!Context.typesAreCompatible(T1, T2)) {
+        Diag((*ParamI)->getLocation(), diag::ext_typecheck_base_super)
+          << T1 << T2;
+        Diag(SuperMethodDecl->getLocation(), diag::note_previous_declaration);
+        return;
+      }
+    }
+    ID = SD;
+  }
+}
+
+/// DiagnoseDuplicateIvars - 
+/// Check for duplicate ivars in the entire class at the start of 
+/// @implementation. This becomes necesssary because class extension can
+/// add ivars to a class in random order which will not be known until
+/// class's @implementation is seen.
+void Sema::DiagnoseDuplicateIvars(ObjCInterfaceDecl *ID, 
+                                  ObjCInterfaceDecl *SID) {
+  for (ObjCInterfaceDecl::ivar_iterator IVI = ID->ivar_begin(),
+       IVE = ID->ivar_end(); IVI != IVE; ++IVI) {
+    ObjCIvarDecl* Ivar = (*IVI);
+    if (Ivar->isInvalidDecl())
+      continue;
+    if (IdentifierInfo *II = Ivar->getIdentifier()) {
+      ObjCIvarDecl* prevIvar = SID->lookupInstanceVariable(II);
+      if (prevIvar) {
+        Diag(Ivar->getLocation(), diag::err_duplicate_member) << II;
+        Diag(prevIvar->getLocation(), diag::note_previous_declaration);
+        Ivar->setInvalidDecl();
+      }
+    }
+  }
+}
+
+Sema::ObjCContainerKind Sema::getObjCContainerKind() const {
+  switch (CurContext->getDeclKind()) {
+    case Decl::ObjCInterface:
+      return Sema::OCK_Interface;
+    case Decl::ObjCProtocol:
+      return Sema::OCK_Protocol;
+    case Decl::ObjCCategory:
+      if (dyn_cast<ObjCCategoryDecl>(CurContext)->IsClassExtension())
+        return Sema::OCK_ClassExtension;
+      else
+        return Sema::OCK_Category;
+    case Decl::ObjCImplementation:
+      return Sema::OCK_Implementation;
+    case Decl::ObjCCategoryImpl:
+      return Sema::OCK_CategoryImplementation;
+
+    default:
+      return Sema::OCK_None;
+  }
+}
+
+// Note: For class/category implemenations, allMethods/allProperties is
+// always null.
+Decl *Sema::ActOnAtEnd(Scope *S, SourceRange AtEnd,
+                       Decl **allMethods, unsigned allNum,
+                       Decl **allProperties, unsigned pNum,
+                       DeclGroupPtrTy *allTUVars, unsigned tuvNum) {
+
+  if (getObjCContainerKind() == Sema::OCK_None)
+    return 0;
+
+  assert(AtEnd.isValid() && "Invalid location for '@end'");
+
+  ObjCContainerDecl *OCD = dyn_cast<ObjCContainerDecl>(CurContext);
+  Decl *ClassDecl = cast<Decl>(OCD);
+  
+  bool isInterfaceDeclKind =
+        isa<ObjCInterfaceDecl>(ClassDecl) || isa<ObjCCategoryDecl>(ClassDecl)
+         || isa<ObjCProtocolDecl>(ClassDecl);
+  bool checkIdenticalMethods = isa<ObjCImplementationDecl>(ClassDecl);
+
+  // FIXME: Remove these and use the ObjCContainerDecl/DeclContext.
+  llvm::DenseMap<Selector, const ObjCMethodDecl*> InsMap;
+  llvm::DenseMap<Selector, const ObjCMethodDecl*> ClsMap;
+
+  for (unsigned i = 0; i < allNum; i++ ) {
+    ObjCMethodDecl *Method =
+      cast_or_null<ObjCMethodDecl>(allMethods[i]);
+
+    if (!Method) continue;  // Already issued a diagnostic.
+    if (Method->isInstanceMethod()) {
+      /// Check for instance method of the same name with incompatible types
+      const ObjCMethodDecl *&PrevMethod = InsMap[Method->getSelector()];
+      bool match = PrevMethod ? MatchTwoMethodDeclarations(Method, PrevMethod)
+                              : false;
+      if ((isInterfaceDeclKind && PrevMethod && !match)
+          || (checkIdenticalMethods && match)) {
+          Diag(Method->getLocation(), diag::err_duplicate_method_decl)
+            << Method->getDeclName();
+          Diag(PrevMethod->getLocation(), diag::note_previous_declaration);
+        Method->setInvalidDecl();
+      } else {
+        if (PrevMethod) {
+          Method->setAsRedeclaration(PrevMethod);
+          if (!Context.getSourceManager().isInSystemHeader(
+                 Method->getLocation()))
+            Diag(Method->getLocation(), diag::warn_duplicate_method_decl)
+              << Method->getDeclName();
+          Diag(PrevMethod->getLocation(), diag::note_previous_declaration);
+        }
+        InsMap[Method->getSelector()] = Method;
+        /// The following allows us to typecheck messages to "id".
+        AddInstanceMethodToGlobalPool(Method);
+        // verify that the instance method conforms to the same definition of
+        // parent methods if it shadows one.
+        CompareMethodParamsInBaseAndSuper(ClassDecl, Method, true);
+      }
+    } else {
+      /// Check for class method of the same name with incompatible types
+      const ObjCMethodDecl *&PrevMethod = ClsMap[Method->getSelector()];
+      bool match = PrevMethod ? MatchTwoMethodDeclarations(Method, PrevMethod)
+                              : false;
+      if ((isInterfaceDeclKind && PrevMethod && !match)
+          || (checkIdenticalMethods && match)) {
+        Diag(Method->getLocation(), diag::err_duplicate_method_decl)
+          << Method->getDeclName();
+        Diag(PrevMethod->getLocation(), diag::note_previous_declaration);
+        Method->setInvalidDecl();
+      } else {
+        if (PrevMethod) {
+          Method->setAsRedeclaration(PrevMethod);
+          if (!Context.getSourceManager().isInSystemHeader(
+                 Method->getLocation()))
+            Diag(Method->getLocation(), diag::warn_duplicate_method_decl)
+              << Method->getDeclName();
+          Diag(PrevMethod->getLocation(), diag::note_previous_declaration);
+        }
+        ClsMap[Method->getSelector()] = Method;
+        /// The following allows us to typecheck messages to "Class".
+        AddFactoryMethodToGlobalPool(Method);
+        // verify that the class method conforms to the same definition of
+        // parent methods if it shadows one.
+        CompareMethodParamsInBaseAndSuper(ClassDecl, Method, false);
+      }
+    }
+  }
+  if (ObjCInterfaceDecl *I = dyn_cast<ObjCInterfaceDecl>(ClassDecl)) {
+    // Compares properties declared in this class to those of its
+    // super class.
+    ComparePropertiesInBaseAndSuper(I);
+    CompareProperties(I, I);
+  } else if (ObjCCategoryDecl *C = dyn_cast<ObjCCategoryDecl>(ClassDecl)) {
+    // Categories are used to extend the class by declaring new methods.
+    // By the same token, they are also used to add new properties. No
+    // need to compare the added property to those in the class.
+
+    // Compare protocol properties with those in category
+    CompareProperties(C, C);
+    if (C->IsClassExtension()) {
+      ObjCInterfaceDecl *CCPrimary = C->getClassInterface();
+      DiagnoseClassExtensionDupMethods(C, CCPrimary);
+    }
+  }
+  if (ObjCContainerDecl *CDecl = dyn_cast<ObjCContainerDecl>(ClassDecl)) {
+    if (CDecl->getIdentifier())
+      // ProcessPropertyDecl is responsible for diagnosing conflicts with any
+      // user-defined setter/getter. It also synthesizes setter/getter methods
+      // and adds them to the DeclContext and global method pools.
+      for (ObjCContainerDecl::prop_iterator I = CDecl->prop_begin(),
+                                            E = CDecl->prop_end();
+           I != E; ++I)
+        ProcessPropertyDecl(*I, CDecl);
+    CDecl->setAtEndRange(AtEnd);
+  }
+  if (ObjCImplementationDecl *IC=dyn_cast<ObjCImplementationDecl>(ClassDecl)) {
+    IC->setAtEndRange(AtEnd);
+    if (ObjCInterfaceDecl* IDecl = IC->getClassInterface()) {
+      // Any property declared in a class extension might have user
+      // declared setter or getter in current class extension or one
+      // of the other class extensions. Mark them as synthesized as
+      // property will be synthesized when property with same name is
+      // seen in the @implementation.
+      for (const ObjCCategoryDecl *ClsExtDecl =
+           IDecl->getFirstClassExtension();
+           ClsExtDecl; ClsExtDecl = ClsExtDecl->getNextClassExtension()) {
+        for (ObjCContainerDecl::prop_iterator I = ClsExtDecl->prop_begin(),
+             E = ClsExtDecl->prop_end(); I != E; ++I) {
+          ObjCPropertyDecl *Property = (*I);
+          // Skip over properties declared @dynamic
+          if (const ObjCPropertyImplDecl *PIDecl
+              = IC->FindPropertyImplDecl(Property->getIdentifier()))
+            if (PIDecl->getPropertyImplementation() 
+                  == ObjCPropertyImplDecl::Dynamic)
+              continue;
+          
+          for (const ObjCCategoryDecl *CExtDecl =
+               IDecl->getFirstClassExtension();
+               CExtDecl; CExtDecl = CExtDecl->getNextClassExtension()) {
+            if (ObjCMethodDecl *GetterMethod =
+                CExtDecl->getInstanceMethod(Property->getGetterName()))
+              GetterMethod->setSynthesized(true);
+            if (!Property->isReadOnly())
+              if (ObjCMethodDecl *SetterMethod =
+                  CExtDecl->getInstanceMethod(Property->getSetterName()))
+                SetterMethod->setSynthesized(true);
+          }        
+        }
+      }
+      ImplMethodsVsClassMethods(S, IC, IDecl);
+      AtomicPropertySetterGetterRules(IC, IDecl);
+      DiagnoseOwningPropertyGetterSynthesis(IC);
+  
+      bool HasRootClassAttr = IDecl->hasAttr<ObjCRootClassAttr>();
+      if (IDecl->getSuperClass() == NULL) {
+        // This class has no superclass, so check that it has been marked with
+        // __attribute((objc_root_class)).
+        if (!HasRootClassAttr) {
+          SourceLocation DeclLoc(IDecl->getLocation());
+          SourceLocation SuperClassLoc(PP.getLocForEndOfToken(DeclLoc));
+          Diag(DeclLoc, diag::warn_objc_root_class_missing)
+            << IDecl->getIdentifier();
+          // See if NSObject is in the current scope, and if it is, suggest
+          // adding " : NSObject " to the class declaration.
+          NamedDecl *IF = LookupSingleName(TUScope,
+                                           NSAPIObj->getNSClassId(NSAPI::ClassId_NSObject),
+                                           DeclLoc, LookupOrdinaryName);
+          ObjCInterfaceDecl *NSObjectDecl = dyn_cast_or_null<ObjCInterfaceDecl>(IF);
+          if (NSObjectDecl && NSObjectDecl->getDefinition()) {
+            Diag(SuperClassLoc, diag::note_objc_needs_superclass)
+              << FixItHint::CreateInsertion(SuperClassLoc, " : NSObject ");
+          } else {
+            Diag(SuperClassLoc, diag::note_objc_needs_superclass);
+          }
+        }
+      } else if (HasRootClassAttr) {
+        // Complain that only root classes may have this attribute.
+        Diag(IDecl->getLocation(), diag::err_objc_root_class_subclass);
+      }
+
+      if (LangOpts.ObjCNonFragileABI2) {
+        while (IDecl->getSuperClass()) {
+          DiagnoseDuplicateIvars(IDecl, IDecl->getSuperClass());
+          IDecl = IDecl->getSuperClass();
+        }
+      }
+    }
+    SetIvarInitializers(IC);
+  } else if (ObjCCategoryImplDecl* CatImplClass =
+                                   dyn_cast<ObjCCategoryImplDecl>(ClassDecl)) {
+    CatImplClass->setAtEndRange(AtEnd);
+
+    // Find category interface decl and then check that all methods declared
+    // in this interface are implemented in the category @implementation.
+    if (ObjCInterfaceDecl* IDecl = CatImplClass->getClassInterface()) {
+      for (ObjCCategoryDecl *Categories = IDecl->getCategoryList();
+           Categories; Categories = Categories->getNextClassCategory()) {
+        if (Categories->getIdentifier() == CatImplClass->getIdentifier()) {
+          ImplMethodsVsClassMethods(S, CatImplClass, Categories);
+          break;
+        }
+      }
+    }
+  }
+  if (isInterfaceDeclKind) {
+    // Reject invalid vardecls.
+    for (unsigned i = 0; i != tuvNum; i++) {
+      DeclGroupRef DG = allTUVars[i].getAsVal<DeclGroupRef>();
+      for (DeclGroupRef::iterator I = DG.begin(), E = DG.end(); I != E; ++I)
+        if (VarDecl *VDecl = dyn_cast<VarDecl>(*I)) {
+          if (!VDecl->hasExternalStorage())
+            Diag(VDecl->getLocation(), diag::err_objc_var_decl_inclass);
+        }
+    }
+  }
+  ActOnObjCContainerFinishDefinition();
+
+  for (unsigned i = 0; i != tuvNum; i++) {
+    DeclGroupRef DG = allTUVars[i].getAsVal<DeclGroupRef>();
+    for (DeclGroupRef::iterator I = DG.begin(), E = DG.end(); I != E; ++I)
+      (*I)->setTopLevelDeclInObjCContainer();
+    Consumer.HandleTopLevelDeclInObjCContainer(DG);
+  }
+
+  return ClassDecl;
+}
+
+
+/// CvtQTToAstBitMask - utility routine to produce an AST bitmask for
+/// objective-c's type qualifier from the parser version of the same info.
+static Decl::ObjCDeclQualifier
+CvtQTToAstBitMask(ObjCDeclSpec::ObjCDeclQualifier PQTVal) {
+  return (Decl::ObjCDeclQualifier) (unsigned) PQTVal;
+}
+
+static inline
+bool containsInvalidMethodImplAttribute(ObjCMethodDecl *IMD,
+                                        const AttrVec &A) {
+  // If method is only declared in implementation (private method),
+  // No need to issue any diagnostics on method definition with attributes.
+  if (!IMD)
+    return false;
+
+  // method declared in interface has no attribute. 
+  // But implementation has attributes. This is invalid
+  if (!IMD->hasAttrs())
+    return true;
+
+  const AttrVec &D = IMD->getAttrs();
+  if (D.size() != A.size())
+    return true;
+
+  // attributes on method declaration and definition must match exactly.
+  // Note that we have at most a couple of attributes on methods, so this
+  // n*n search is good enough.
+  for (AttrVec::const_iterator i = A.begin(), e = A.end(); i != e; ++i) {
+    bool match = false;
+    for (AttrVec::const_iterator i1 = D.begin(), e1 = D.end(); i1 != e1; ++i1) {
+      if ((*i)->getKind() == (*i1)->getKind()) {
+        match = true;
+        break;
+      }
+    }
+    if (!match)
+      return true;
+  }
+  return false;
+}
+
+namespace  {
+  /// \brief Describes the compatibility of a result type with its method.
+  enum ResultTypeCompatibilityKind {
+    RTC_Compatible,
+    RTC_Incompatible,
+    RTC_Unknown
+  };
+}
+
+/// \brief Check whether the declared result type of the given Objective-C
+/// method declaration is compatible with the method's class.
+///
+static ResultTypeCompatibilityKind 
+CheckRelatedResultTypeCompatibility(Sema &S, ObjCMethodDecl *Method,
+                                    ObjCInterfaceDecl *CurrentClass) {
+  QualType ResultType = Method->getResultType();
+  
+  // If an Objective-C method inherits its related result type, then its 
+  // declared result type must be compatible with its own class type. The
+  // declared result type is compatible if:
+  if (const ObjCObjectPointerType *ResultObjectType
+                                = ResultType->getAs<ObjCObjectPointerType>()) {
+    //   - it is id or qualified id, or
+    if (ResultObjectType->isObjCIdType() ||
+        ResultObjectType->isObjCQualifiedIdType())
+      return RTC_Compatible;
+  
+    if (CurrentClass) {
+      if (ObjCInterfaceDecl *ResultClass 
+                                      = ResultObjectType->getInterfaceDecl()) {
+        //   - it is the same as the method's class type, or
+        if (declaresSameEntity(CurrentClass, ResultClass))
+          return RTC_Compatible;
+        
+        //   - it is a superclass of the method's class type
+        if (ResultClass->isSuperClassOf(CurrentClass))
+          return RTC_Compatible;
+      }      
+    } else {
+      // Any Objective-C pointer type might be acceptable for a protocol
+      // method; we just don't know.
+      return RTC_Unknown;
+    }
+  }
+  
+  return RTC_Incompatible;
+}
+
+namespace {
+/// A helper class for searching for methods which a particular method
+/// overrides.
+class OverrideSearch {
+public:
+  Sema &S;
+  ObjCMethodDecl *Method;
+  llvm::SmallPtrSet<ObjCContainerDecl*, 128> Searched;
+  llvm::SmallPtrSet<ObjCMethodDecl*, 4> Overridden;
+  bool Recursive;
+
+public:
+  OverrideSearch(Sema &S, ObjCMethodDecl *method) : S(S), Method(method) {
+    Selector selector = method->getSelector();
+
+    // Bypass this search if we've never seen an instance/class method
+    // with this selector before.
+    Sema::GlobalMethodPool::iterator it = S.MethodPool.find(selector);
+    if (it == S.MethodPool.end()) {
+      if (!S.ExternalSource) return;
+      S.ReadMethodPool(selector);
+      
+      it = S.MethodPool.find(selector);
+      if (it == S.MethodPool.end())
+        return;
+    }
+    ObjCMethodList &list =
+      method->isInstanceMethod() ? it->second.first : it->second.second;
+    if (!list.Method) return;
+
+    ObjCContainerDecl *container
+      = cast<ObjCContainerDecl>(method->getDeclContext());
+
+    // Prevent the search from reaching this container again.  This is
+    // important with categories, which override methods from the
+    // interface and each other.
+    Searched.insert(container);
+    searchFromContainer(container);
+  }
+
+  typedef llvm::SmallPtrSet<ObjCMethodDecl*, 128>::iterator iterator;
+  iterator begin() const { return Overridden.begin(); }
+  iterator end() const { return Overridden.end(); }
+
+private:
+  void searchFromContainer(ObjCContainerDecl *container) {
+    if (container->isInvalidDecl()) return;
+
+    switch (container->getDeclKind()) {
+#define OBJCCONTAINER(type, base) \
+    case Decl::type: \
+      searchFrom(cast<type##Decl>(container)); \
+      break;
+#define ABSTRACT_DECL(expansion)
+#define DECL(type, base) \
+    case Decl::type:
+#include "clang/AST/DeclNodes.inc"
+      llvm_unreachable("not an ObjC container!");
+    }
+  }
+
+  void searchFrom(ObjCProtocolDecl *protocol) {
+    if (!protocol->hasDefinition())
+      return;
+    
+    // A method in a protocol declaration overrides declarations from
+    // referenced ("parent") protocols.
+    search(protocol->getReferencedProtocols());
+  }
+
+  void searchFrom(ObjCCategoryDecl *category) {
+    // A method in a category declaration overrides declarations from
+    // the main class and from protocols the category references.
+    search(category->getClassInterface());
+    search(category->getReferencedProtocols());
+  }
+
+  void searchFrom(ObjCCategoryImplDecl *impl) {
+    // A method in a category definition that has a category
+    // declaration overrides declarations from the category
+    // declaration.
+    if (ObjCCategoryDecl *category = impl->getCategoryDecl()) {
+      search(category);
+
+    // Otherwise it overrides declarations from the class.
+    } else {
+      search(impl->getClassInterface());
+    }
+  }
+
+  void searchFrom(ObjCInterfaceDecl *iface) {
+    // A method in a class declaration overrides declarations from
+    if (!iface->hasDefinition())
+      return;
+    
+    //   - categories,
+    for (ObjCCategoryDecl *category = iface->getCategoryList();
+           category; category = category->getNextClassCategory())
+      search(category);
+
+    //   - the super class, and
+    if (ObjCInterfaceDecl *super = iface->getSuperClass())
+      search(super);
+
+    //   - any referenced protocols.
+    search(iface->getReferencedProtocols());
+  }
+
+  void searchFrom(ObjCImplementationDecl *impl) {
+    // A method in a class implementation overrides declarations from
+    // the class interface.
+    search(impl->getClassInterface());
+  }
+
+
+  void search(const ObjCProtocolList &protocols) {
+    for (ObjCProtocolList::iterator i = protocols.begin(), e = protocols.end();
+         i != e; ++i)
+      search(*i);
+  }
+
+  void search(ObjCContainerDecl *container) {
+    // Abort if we've already searched this container.
+    if (!Searched.insert(container)) return;
+
+    // Check for a method in this container which matches this selector.
+    ObjCMethodDecl *meth = container->getMethod(Method->getSelector(),
+                                                Method->isInstanceMethod());
+
+    // If we find one, record it and bail out.
+    if (meth) {
+      Overridden.insert(meth);
+      return;
+    }
+
+    // Otherwise, search for methods that a hypothetical method here
+    // would have overridden.
+
+    // Note that we're now in a recursive case.
+    Recursive = true;
+
+    searchFromContainer(container);
+  }
+};
+}
+
+Decl *Sema::ActOnMethodDeclaration(
+    Scope *S,
+    SourceLocation MethodLoc, SourceLocation EndLoc,
+    tok::TokenKind MethodType, 
+    ObjCDeclSpec &ReturnQT, ParsedType ReturnType,
+    ArrayRef<SourceLocation> SelectorLocs,
+    Selector Sel,
+    // optional arguments. The number of types/arguments is obtained
+    // from the Sel.getNumArgs().
+    ObjCArgInfo *ArgInfo,
+    DeclaratorChunk::ParamInfo *CParamInfo, unsigned CNumArgs, // c-style args
+    AttributeList *AttrList, tok::ObjCKeywordKind MethodDeclKind,
+    bool isVariadic, bool MethodDefinition) {
+  // Make sure we can establish a context for the method.
+  if (!CurContext->isObjCContainer()) {
+    Diag(MethodLoc, diag::error_missing_method_context);
+    return 0;
+  }
+  ObjCContainerDecl *OCD = dyn_cast<ObjCContainerDecl>(CurContext);
+  Decl *ClassDecl = cast<Decl>(OCD); 
+  QualType resultDeclType;
+
+  bool HasRelatedResultType = false;
+  TypeSourceInfo *ResultTInfo = 0;
+  if (ReturnType) {
+    resultDeclType = GetTypeFromParser(ReturnType, &ResultTInfo);
+
+    // Methods cannot return interface types. All ObjC objects are
+    // passed by reference.
+    if (resultDeclType->isObjCObjectType()) {
+      Diag(MethodLoc, diag::err_object_cannot_be_passed_returned_by_value)
+        << 0 << resultDeclType;
+      return 0;
+    }    
+    
+    HasRelatedResultType = (resultDeclType == Context.getObjCInstanceType());
+  } else { // get the type for "id".
+    resultDeclType = Context.getObjCIdType();
+    Diag(MethodLoc, diag::warn_missing_method_return_type)
+      << FixItHint::CreateInsertion(SelectorLocs.front(), "(id)");
+  }
+
+  ObjCMethodDecl* ObjCMethod =
+    ObjCMethodDecl::Create(Context, MethodLoc, EndLoc, Sel,
+                           resultDeclType,
+                           ResultTInfo,
+                           CurContext,
+                           MethodType == tok::minus, isVariadic,
+                           /*isSynthesized=*/false,
+                           /*isImplicitlyDeclared=*/false, /*isDefined=*/false,
+                           MethodDeclKind == tok::objc_optional 
+                             ? ObjCMethodDecl::Optional
+                             : ObjCMethodDecl::Required,
+                           HasRelatedResultType);
+
+  SmallVector<ParmVarDecl*, 16> Params;
+
+  for (unsigned i = 0, e = Sel.getNumArgs(); i != e; ++i) {
+    QualType ArgType;
+    TypeSourceInfo *DI;
+
+    if (ArgInfo[i].Type == 0) {
+      ArgType = Context.getObjCIdType();
+      DI = 0;
+    } else {
+      ArgType = GetTypeFromParser(ArgInfo[i].Type, &DI);
+      // Perform the default array/function conversions (C99 6.7.5.3p[7,8]).
+      ArgType = Context.getAdjustedParameterType(ArgType);
+    }
+
+    LookupResult R(*this, ArgInfo[i].Name, ArgInfo[i].NameLoc, 
+                   LookupOrdinaryName, ForRedeclaration);
+    LookupName(R, S);
+    if (R.isSingleResult()) {
+      NamedDecl *PrevDecl = R.getFoundDecl();
+      if (S->isDeclScope(PrevDecl)) {
+        Diag(ArgInfo[i].NameLoc, 
+             (MethodDefinition ? diag::warn_method_param_redefinition 
+                               : diag::warn_method_param_declaration)) 
+          << ArgInfo[i].Name;
+        Diag(PrevDecl->getLocation(), 
+             diag::note_previous_declaration);
+      }
+    }
+
+    SourceLocation StartLoc = DI
+      ? DI->getTypeLoc().getBeginLoc()
+      : ArgInfo[i].NameLoc;
+
+    ParmVarDecl* Param = CheckParameter(ObjCMethod, StartLoc,
+                                        ArgInfo[i].NameLoc, ArgInfo[i].Name,
+                                        ArgType, DI, SC_None, SC_None);
+
+    Param->setObjCMethodScopeInfo(i);
+
+    Param->setObjCDeclQualifier(
+      CvtQTToAstBitMask(ArgInfo[i].DeclSpec.getObjCDeclQualifier()));
+
+    // Apply the attributes to the parameter.
+    ProcessDeclAttributeList(TUScope, Param, ArgInfo[i].ArgAttrs);
+
+    if (Param->hasAttr<BlocksAttr>()) {
+      Diag(Param->getLocation(), diag::err_block_on_nonlocal);
+      Param->setInvalidDecl();
+    }
+    S->AddDecl(Param);
+    IdResolver.AddDecl(Param);
+
+    Params.push_back(Param);
+  }
+  
+  for (unsigned i = 0, e = CNumArgs; i != e; ++i) {
+    ParmVarDecl *Param = cast<ParmVarDecl>(CParamInfo[i].Param);
+    QualType ArgType = Param->getType();
+    if (ArgType.isNull())
+      ArgType = Context.getObjCIdType();
+    else
+      // Perform the default array/function conversions (C99 6.7.5.3p[7,8]).
+      ArgType = Context.getAdjustedParameterType(ArgType);
+    if (ArgType->isObjCObjectType()) {
+      Diag(Param->getLocation(),
+           diag::err_object_cannot_be_passed_returned_by_value)
+      << 1 << ArgType;
+      Param->setInvalidDecl();
+    }
+    Param->setDeclContext(ObjCMethod);
+    
+    Params.push_back(Param);
+  }
+  
+  ObjCMethod->setMethodParams(Context, Params, SelectorLocs);
+  ObjCMethod->setObjCDeclQualifier(
+    CvtQTToAstBitMask(ReturnQT.getObjCDeclQualifier()));
+
+  if (AttrList)
+    ProcessDeclAttributeList(TUScope, ObjCMethod, AttrList);
+
+  // Add the method now.
+  const ObjCMethodDecl *PrevMethod = 0;
+  if (ObjCImplDecl *ImpDecl = dyn_cast<ObjCImplDecl>(ClassDecl)) {
+    if (MethodType == tok::minus) {
+      PrevMethod = ImpDecl->getInstanceMethod(Sel);
+      ImpDecl->addInstanceMethod(ObjCMethod);
+    } else {
+      PrevMethod = ImpDecl->getClassMethod(Sel);
+      ImpDecl->addClassMethod(ObjCMethod);
+    }
+
+    ObjCMethodDecl *IMD = 0;
+    if (ObjCInterfaceDecl *IDecl = ImpDecl->getClassInterface())
+      IMD = IDecl->lookupMethod(ObjCMethod->getSelector(), 
+                                ObjCMethod->isInstanceMethod());
+    if (ObjCMethod->hasAttrs() &&
+        containsInvalidMethodImplAttribute(IMD, ObjCMethod->getAttrs())) {
+      SourceLocation MethodLoc = IMD->getLocation();
+      if (!getSourceManager().isInSystemHeader(MethodLoc)) {
+        Diag(EndLoc, diag::warn_attribute_method_def);
+        Diag(MethodLoc, diag::note_method_declared_at)
+          << ObjCMethod->getDeclName();
+      }
+    }
+  } else {
+    cast<DeclContext>(ClassDecl)->addDecl(ObjCMethod);
+  }
+
+  if (PrevMethod) {
+    // You can never have two method definitions with the same name.
+    Diag(ObjCMethod->getLocation(), diag::err_duplicate_method_decl)
+      << ObjCMethod->getDeclName();
+    Diag(PrevMethod->getLocation(), diag::note_previous_declaration);
+  }
+
+  // If this Objective-C method does not have a related result type, but we
+  // are allowed to infer related result types, try to do so based on the
+  // method family.
+  ObjCInterfaceDecl *CurrentClass = dyn_cast<ObjCInterfaceDecl>(ClassDecl);
+  if (!CurrentClass) {
+    if (ObjCCategoryDecl *Cat = dyn_cast<ObjCCategoryDecl>(ClassDecl))
+      CurrentClass = Cat->getClassInterface();
+    else if (ObjCImplDecl *Impl = dyn_cast<ObjCImplDecl>(ClassDecl))
+      CurrentClass = Impl->getClassInterface();
+    else if (ObjCCategoryImplDecl *CatImpl
+                                   = dyn_cast<ObjCCategoryImplDecl>(ClassDecl))
+      CurrentClass = CatImpl->getClassInterface();
+  }
+
+  ResultTypeCompatibilityKind RTC
+    = CheckRelatedResultTypeCompatibility(*this, ObjCMethod, CurrentClass);
+
+  // Search for overridden methods and merge information down from them.
+  OverrideSearch overrides(*this, ObjCMethod);
+  for (OverrideSearch::iterator
+         i = overrides.begin(), e = overrides.end(); i != e; ++i) {
+    ObjCMethodDecl *overridden = *i;
+
+    // Propagate down the 'related result type' bit from overridden methods.
+    if (RTC != RTC_Incompatible && overridden->hasRelatedResultType())
+      ObjCMethod->SetRelatedResultType();
+
+    // Then merge the declarations.
+    mergeObjCMethodDecls(ObjCMethod, overridden);
+    
+    // Check for overriding methods
+    if (isa<ObjCInterfaceDecl>(ObjCMethod->getDeclContext()) || 
+        isa<ObjCImplementationDecl>(ObjCMethod->getDeclContext()))
+      CheckConflictingOverridingMethod(ObjCMethod, overridden,
+              isa<ObjCProtocolDecl>(overridden->getDeclContext()));
+  }
+  
+  bool ARCError = false;
+  if (getLangOpts().ObjCAutoRefCount)
+    ARCError = CheckARCMethodDecl(*this, ObjCMethod);
+
+  // Infer the related result type when possible.
+  if (!ARCError && RTC == RTC_Compatible &&
+      !ObjCMethod->hasRelatedResultType() &&
+      LangOpts.ObjCInferRelatedResultType) {
+    bool InferRelatedResultType = false;
+    switch (ObjCMethod->getMethodFamily()) {
+    case OMF_None:
+    case OMF_copy:
+    case OMF_dealloc:
+    case OMF_finalize:
+    case OMF_mutableCopy:
+    case OMF_release:
+    case OMF_retainCount:
+    case OMF_performSelector:
+      break;
+      
+    case OMF_alloc:
+    case OMF_new:
+      InferRelatedResultType = ObjCMethod->isClassMethod();
+      break;
+        
+    case OMF_init:
+    case OMF_autorelease:
+    case OMF_retain:
+    case OMF_self:
+      InferRelatedResultType = ObjCMethod->isInstanceMethod();
+      break;
+    }
+    
+    if (InferRelatedResultType)
+      ObjCMethod->SetRelatedResultType();
+  }
+    
+  return ObjCMethod;
+}
+
+bool Sema::CheckObjCDeclScope(Decl *D) {
+  // Following is also an error. But it is caused by a missing @end
+  // and diagnostic is issued elsewhere.
+  if (isa<ObjCContainerDecl>(CurContext->getRedeclContext()))
+    return false;
+
+  // If we switched context to translation unit while we are still lexically in
+  // an objc container, it means the parser missed emitting an error.
+  if (isa<TranslationUnitDecl>(getCurLexicalContext()->getRedeclContext()))
+    return false;
+  
+  Diag(D->getLocation(), diag::err_objc_decls_may_only_appear_in_global_scope);
+  D->setInvalidDecl();
+
+  return true;
+}
+
+/// Called whenever @defs(ClassName) is encountered in the source.  Inserts the
+/// instance variables of ClassName into Decls.
+void Sema::ActOnDefs(Scope *S, Decl *TagD, SourceLocation DeclStart,
+                     IdentifierInfo *ClassName,
+                     SmallVectorImpl<Decl*> &Decls) {
+  // Check that ClassName is a valid class
+  ObjCInterfaceDecl *Class = getObjCInterfaceDecl(ClassName, DeclStart);
+  if (!Class) {
+    Diag(DeclStart, diag::err_undef_interface) << ClassName;
+    return;
+  }
+  if (LangOpts.ObjCNonFragileABI) {
+    Diag(DeclStart, diag::err_atdef_nonfragile_interface);
+    return;
+  }
+
+  // Collect the instance variables
+  SmallVector<const ObjCIvarDecl*, 32> Ivars;
+  Context.DeepCollectObjCIvars(Class, true, Ivars);
+  // For each ivar, create a fresh ObjCAtDefsFieldDecl.
+  for (unsigned i = 0; i < Ivars.size(); i++) {
+    const FieldDecl* ID = cast<FieldDecl>(Ivars[i]);
+    RecordDecl *Record = dyn_cast<RecordDecl>(TagD);
+    Decl *FD = ObjCAtDefsFieldDecl::Create(Context, Record,
+                                           /*FIXME: StartL=*/ID->getLocation(),
+                                           ID->getLocation(),
+                                           ID->getIdentifier(), ID->getType(),
+                                           ID->getBitWidth());
+    Decls.push_back(FD);
+  }
+
+  // Introduce all of these fields into the appropriate scope.
+  for (SmallVectorImpl<Decl*>::iterator D = Decls.begin();
+       D != Decls.end(); ++D) {
+    FieldDecl *FD = cast<FieldDecl>(*D);
+    if (getLangOpts().CPlusPlus)
+      PushOnScopeChains(cast<FieldDecl>(FD), S);
+    else if (RecordDecl *Record = dyn_cast<RecordDecl>(TagD))
+      Record->addDecl(FD);
+  }
+}
+
+/// \brief Build a type-check a new Objective-C exception variable declaration.
+VarDecl *Sema::BuildObjCExceptionDecl(TypeSourceInfo *TInfo, QualType T,
+                                      SourceLocation StartLoc,
+                                      SourceLocation IdLoc,
+                                      IdentifierInfo *Id,
+                                      bool Invalid) {
+  // ISO/IEC TR 18037 S6.7.3: "The type of an object with automatic storage 
+  // duration shall not be qualified by an address-space qualifier."
+  // Since all parameters have automatic store duration, they can not have
+  // an address space.
+  if (T.getAddressSpace() != 0) {
+    Diag(IdLoc, diag::err_arg_with_address_space);
+    Invalid = true;
+  }
+  
+  // An @catch parameter must be an unqualified object pointer type;
+  // FIXME: Recover from "NSObject foo" by inserting the * in "NSObject *foo"?
+  if (Invalid) {
+    // Don't do any further checking.
+  } else if (T->isDependentType()) {
+    // Okay: we don't know what this type will instantiate to.
+  } else if (!T->isObjCObjectPointerType()) {
+    Invalid = true;
+    Diag(IdLoc ,diag::err_catch_param_not_objc_type);
+  } else if (T->isObjCQualifiedIdType()) {
+    Invalid = true;
+    Diag(IdLoc, diag::err_illegal_qualifiers_on_catch_parm);
+  }
+  
+  VarDecl *New = VarDecl::Create(Context, CurContext, StartLoc, IdLoc, Id,
+                                 T, TInfo, SC_None, SC_None);
+  New->setExceptionVariable(true);
+  
+  // In ARC, infer 'retaining' for variables of retainable type.
+  if (getLangOpts().ObjCAutoRefCount && inferObjCARCLifetime(New))
+    Invalid = true;
+
+  if (Invalid)
+    New->setInvalidDecl();
+  return New;
+}
+
+Decl *Sema::ActOnObjCExceptionDecl(Scope *S, Declarator &D) {
+  const DeclSpec &DS = D.getDeclSpec();
+  
+  // We allow the "register" storage class on exception variables because
+  // GCC did, but we drop it completely. Any other storage class is an error.
+  if (DS.getStorageClassSpec() == DeclSpec::SCS_register) {
+    Diag(DS.getStorageClassSpecLoc(), diag::warn_register_objc_catch_parm)
+      << FixItHint::CreateRemoval(SourceRange(DS.getStorageClassSpecLoc()));
+  } else if (DS.getStorageClassSpec() != DeclSpec::SCS_unspecified) {
+    Diag(DS.getStorageClassSpecLoc(), diag::err_storage_spec_on_catch_parm)
+      << DS.getStorageClassSpec();
+  }  
+  if (D.getDeclSpec().isThreadSpecified())
+    Diag(D.getDeclSpec().getThreadSpecLoc(), diag::err_invalid_thread);
+  D.getMutableDeclSpec().ClearStorageClassSpecs();
+
+  DiagnoseFunctionSpecifiers(D);
+  
+  // Check that there are no default arguments inside the type of this
+  // exception object (C++ only).
+  if (getLangOpts().CPlusPlus)
+    CheckExtraCXXDefaultArguments(D);
+  
+  TypeSourceInfo *TInfo = GetTypeForDeclarator(D, S);
+  QualType ExceptionType = TInfo->getType();
+
+  VarDecl *New = BuildObjCExceptionDecl(TInfo, ExceptionType,
+                                        D.getSourceRange().getBegin(),
+                                        D.getIdentifierLoc(),
+                                        D.getIdentifier(),
+                                        D.isInvalidType());
+  
+  // Parameter declarators cannot be qualified (C++ [dcl.meaning]p1).
+  if (D.getCXXScopeSpec().isSet()) {
+    Diag(D.getIdentifierLoc(), diag::err_qualified_objc_catch_parm)
+      << D.getCXXScopeSpec().getRange();
+    New->setInvalidDecl();
+  }
+  
+  // Add the parameter declaration into this scope.
+  S->AddDecl(New);
+  if (D.getIdentifier())
+    IdResolver.AddDecl(New);
+  
+  ProcessDeclAttributes(S, New, D);
+  
+  if (New->hasAttr<BlocksAttr>())
+    Diag(New->getLocation(), diag::err_block_on_nonlocal);
+  return New;
+}
+
+/// CollectIvarsToConstructOrDestruct - Collect those ivars which require
+/// initialization.
+void Sema::CollectIvarsToConstructOrDestruct(ObjCInterfaceDecl *OI,
+                                SmallVectorImpl<ObjCIvarDecl*> &Ivars) {
+  for (ObjCIvarDecl *Iv = OI->all_declared_ivar_begin(); Iv; 
+       Iv= Iv->getNextIvar()) {
+    QualType QT = Context.getBaseElementType(Iv->getType());
+    if (QT->isRecordType())
+      Ivars.push_back(Iv);
+  }
+}
+
+void Sema::DiagnoseUseOfUnimplementedSelectors() {
+  // Load referenced selectors from the external source.
+  if (ExternalSource) {
+    SmallVector<std::pair<Selector, SourceLocation>, 4> Sels;
+    ExternalSource->ReadReferencedSelectors(Sels);
+    for (unsigned I = 0, N = Sels.size(); I != N; ++I)
+      ReferencedSelectors[Sels[I].first] = Sels[I].second;
+  }
+  
+  // Warning will be issued only when selector table is
+  // generated (which means there is at lease one implementation
+  // in the TU). This is to match gcc's behavior.
+  if (ReferencedSelectors.empty() || 
+      !Context.AnyObjCImplementation())
+    return;
+  for (llvm::DenseMap<Selector, SourceLocation>::iterator S = 
+        ReferencedSelectors.begin(),
+       E = ReferencedSelectors.end(); S != E; ++S) {
+    Selector Sel = (*S).first;
+    if (!LookupImplementedMethodInGlobalPool(Sel))
+      Diag((*S).second, diag::warn_unimplemented_selector) << Sel;
+  }
+  return;
+}
diff --git a/clang/lib/Sema/SemaExceptionSpec.cpp b/clang/lib/Sema/SemaExceptionSpec.cpp
new file mode 100644
index 0000000..14b2434
--- /dev/null
+++ b/clang/lib/Sema/SemaExceptionSpec.cpp
@@ -0,0 +1,1086 @@
+//===--- SemaExceptionSpec.cpp - C++ Exception Specifications ---*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file provides Sema routines for C++ exception specification testing.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Sema/SemaInternal.h"
+#include "clang/AST/CXXInheritance.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/ExprCXX.h"
+#include "clang/AST/TypeLoc.h"
+#include "clang/Lex/Preprocessor.h"
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/SourceManager.h"
+#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/SmallString.h"
+
+namespace clang {
+
+static const FunctionProtoType *GetUnderlyingFunction(QualType T)
+{
+  if (const PointerType *PtrTy = T->getAs<PointerType>())
+    T = PtrTy->getPointeeType();
+  else if (const ReferenceType *RefTy = T->getAs<ReferenceType>())
+    T = RefTy->getPointeeType();
+  else if (const MemberPointerType *MPTy = T->getAs<MemberPointerType>())
+    T = MPTy->getPointeeType();
+  return T->getAs<FunctionProtoType>();
+}
+
+/// CheckSpecifiedExceptionType - Check if the given type is valid in an
+/// exception specification. Incomplete types, or pointers to incomplete types
+/// other than void are not allowed.
+bool Sema::CheckSpecifiedExceptionType(QualType T, const SourceRange &Range) {
+
+  // This check (and the similar one below) deals with issue 437, that changes
+  // C++ 9.2p2 this way:
+  // Within the class member-specification, the class is regarded as complete
+  // within function bodies, default arguments, exception-specifications, and
+  // constructor ctor-initializers (including such things in nested classes).
+  if (T->isRecordType() && T->getAs<RecordType>()->isBeingDefined())
+    return false;
+    
+  // C++ 15.4p2: A type denoted in an exception-specification shall not denote
+  //   an incomplete type.
+  if (RequireCompleteType(Range.getBegin(), T,
+      PDiag(diag::err_incomplete_in_exception_spec) << /*direct*/0 << Range))
+    return true;
+
+  // C++ 15.4p2: A type denoted in an exception-specification shall not denote
+  //   an incomplete type a pointer or reference to an incomplete type, other
+  //   than (cv) void*.
+  int kind;
+  if (const PointerType* IT = T->getAs<PointerType>()) {
+    T = IT->getPointeeType();
+    kind = 1;
+  } else if (const ReferenceType* IT = T->getAs<ReferenceType>()) {
+    T = IT->getPointeeType();
+    kind = 2;
+  } else
+    return false;
+
+  // Again as before
+  if (T->isRecordType() && T->getAs<RecordType>()->isBeingDefined())
+    return false;
+    
+  if (!T->isVoidType() && RequireCompleteType(Range.getBegin(), T,
+      PDiag(diag::err_incomplete_in_exception_spec) << kind << Range))
+    return true;
+
+  return false;
+}
+
+/// CheckDistantExceptionSpec - Check if the given type is a pointer or pointer
+/// to member to a function with an exception specification. This means that
+/// it is invalid to add another level of indirection.
+bool Sema::CheckDistantExceptionSpec(QualType T) {
+  if (const PointerType *PT = T->getAs<PointerType>())
+    T = PT->getPointeeType();
+  else if (const MemberPointerType *PT = T->getAs<MemberPointerType>())
+    T = PT->getPointeeType();
+  else
+    return false;
+
+  const FunctionProtoType *FnT = T->getAs<FunctionProtoType>();
+  if (!FnT)
+    return false;
+
+  return FnT->hasExceptionSpec();
+}
+
+const FunctionProtoType *
+Sema::ResolveExceptionSpec(SourceLocation Loc, const FunctionProtoType *FPT) {
+  // FIXME: If FD is a special member, we should delay computing its exception
+  // specification until this point.
+  if (FPT->getExceptionSpecType() != EST_Uninstantiated)
+    return FPT;
+
+  FunctionDecl *SourceDecl = FPT->getExceptionSpecDecl();
+  const FunctionProtoType *SourceFPT =
+      SourceDecl->getType()->castAs<FunctionProtoType>();
+
+  if (SourceFPT->getExceptionSpecType() != EST_Uninstantiated)
+    return SourceFPT;
+
+  // Instantiate the exception specification now.
+  InstantiateExceptionSpec(Loc, SourceDecl);
+
+  return SourceDecl->getType()->castAs<FunctionProtoType>();
+}
+
+bool Sema::CheckEquivalentExceptionSpec(FunctionDecl *Old, FunctionDecl *New) {
+  OverloadedOperatorKind OO = New->getDeclName().getCXXOverloadedOperator();
+  bool IsOperatorNew = OO == OO_New || OO == OO_Array_New;
+  bool MissingExceptionSpecification = false;
+  bool MissingEmptyExceptionSpecification = false;
+  unsigned DiagID = diag::err_mismatched_exception_spec;
+  if (getLangOpts().MicrosoftExt)
+    DiagID = diag::warn_mismatched_exception_spec; 
+
+  if (!CheckEquivalentExceptionSpec(PDiag(DiagID),
+                                    PDiag(diag::note_previous_declaration),
+                                    Old->getType()->getAs<FunctionProtoType>(),
+                                    Old->getLocation(),
+                                    New->getType()->getAs<FunctionProtoType>(),
+                                    New->getLocation(),
+                                    &MissingExceptionSpecification,
+                                    &MissingEmptyExceptionSpecification,
+                                    /*AllowNoexceptAllMatchWithNoSpec=*/true,
+                                    IsOperatorNew))
+    return false;
+
+  // The failure was something other than an empty exception
+  // specification; return an error.
+  if (!MissingExceptionSpecification && !MissingEmptyExceptionSpecification)
+    return true;
+
+  const FunctionProtoType *NewProto 
+    = New->getType()->getAs<FunctionProtoType>();
+
+  // The new function declaration is only missing an empty exception
+  // specification "throw()". If the throw() specification came from a
+  // function in a system header that has C linkage, just add an empty
+  // exception specification to the "new" declaration. This is an
+  // egregious workaround for glibc, which adds throw() specifications
+  // to many libc functions as an optimization. Unfortunately, that
+  // optimization isn't permitted by the C++ standard, so we're forced
+  // to work around it here.
+  if (MissingEmptyExceptionSpecification && NewProto &&
+      (Old->getLocation().isInvalid() ||
+       Context.getSourceManager().isInSystemHeader(Old->getLocation())) &&
+      Old->isExternC()) {
+    FunctionProtoType::ExtProtoInfo EPI = NewProto->getExtProtoInfo();
+    EPI.ExceptionSpecType = EST_DynamicNone;
+    QualType NewType = Context.getFunctionType(NewProto->getResultType(),
+                                               NewProto->arg_type_begin(),
+                                               NewProto->getNumArgs(),
+                                               EPI);
+    New->setType(NewType);
+    return false;
+  }
+
+  if (MissingExceptionSpecification && NewProto) {
+    const FunctionProtoType *OldProto
+      = Old->getType()->getAs<FunctionProtoType>();
+
+    FunctionProtoType::ExtProtoInfo EPI = NewProto->getExtProtoInfo();
+    EPI.ExceptionSpecType = OldProto->getExceptionSpecType();
+    if (EPI.ExceptionSpecType == EST_Dynamic) {
+      EPI.NumExceptions = OldProto->getNumExceptions();
+      EPI.Exceptions = OldProto->exception_begin();
+    } else if (EPI.ExceptionSpecType == EST_ComputedNoexcept) {
+      // FIXME: We can't just take the expression from the old prototype. It
+      // likely contains references to the old prototype's parameters.
+    }
+
+    // Update the type of the function with the appropriate exception
+    // specification.
+    QualType NewType = Context.getFunctionType(NewProto->getResultType(),
+                                               NewProto->arg_type_begin(),
+                                               NewProto->getNumArgs(),
+                                               EPI);
+    New->setType(NewType);
+
+    // If exceptions are disabled, suppress the warning about missing
+    // exception specifications for new and delete operators.
+    if (!getLangOpts().CXXExceptions) {
+      switch (New->getDeclName().getCXXOverloadedOperator()) {
+      case OO_New:
+      case OO_Array_New:
+      case OO_Delete:
+      case OO_Array_Delete:
+        if (New->getDeclContext()->isTranslationUnit())
+          return false;
+        break;
+
+      default:
+        break;
+      }
+    } 
+
+    // Warn about the lack of exception specification.
+    SmallString<128> ExceptionSpecString;
+    llvm::raw_svector_ostream OS(ExceptionSpecString);
+    switch (OldProto->getExceptionSpecType()) {
+    case EST_DynamicNone:
+      OS << "throw()";
+      break;
+
+    case EST_Dynamic: {
+      OS << "throw(";
+      bool OnFirstException = true;
+      for (FunctionProtoType::exception_iterator E = OldProto->exception_begin(),
+                                              EEnd = OldProto->exception_end();
+           E != EEnd;
+           ++E) {
+        if (OnFirstException)
+          OnFirstException = false;
+        else
+          OS << ", ";
+        
+        OS << E->getAsString(getPrintingPolicy());
+      }
+      OS << ")";
+      break;
+    }
+
+    case EST_BasicNoexcept:
+      OS << "noexcept";
+      break;
+
+    case EST_ComputedNoexcept:
+      OS << "noexcept(";
+      OldProto->getNoexceptExpr()->printPretty(OS, Context, 0, 
+                                               getPrintingPolicy());
+      OS << ")";
+      break;
+
+    default:
+      llvm_unreachable("This spec type is compatible with none.");
+    }
+    OS.flush();
+
+    SourceLocation FixItLoc;
+    if (TypeSourceInfo *TSInfo = New->getTypeSourceInfo()) {
+      TypeLoc TL = TSInfo->getTypeLoc().IgnoreParens();
+      if (const FunctionTypeLoc *FTLoc = dyn_cast<FunctionTypeLoc>(&TL))
+        FixItLoc = PP.getLocForEndOfToken(FTLoc->getLocalRangeEnd());
+    }
+
+    if (FixItLoc.isInvalid())
+      Diag(New->getLocation(), diag::warn_missing_exception_specification)
+        << New << OS.str();
+    else {
+      // FIXME: This will get more complicated with C++0x
+      // late-specified return types.
+      Diag(New->getLocation(), diag::warn_missing_exception_specification)
+        << New << OS.str()
+        << FixItHint::CreateInsertion(FixItLoc, " " + OS.str().str());
+    }
+
+    if (!Old->getLocation().isInvalid())
+      Diag(Old->getLocation(), diag::note_previous_declaration);
+
+    return false;    
+  }
+
+  Diag(New->getLocation(), DiagID);
+  Diag(Old->getLocation(), diag::note_previous_declaration);
+  return true;
+}
+
+/// CheckEquivalentExceptionSpec - Check if the two types have equivalent
+/// exception specifications. Exception specifications are equivalent if
+/// they allow exactly the same set of exception types. It does not matter how
+/// that is achieved. See C++ [except.spec]p2.
+bool Sema::CheckEquivalentExceptionSpec(
+    const FunctionProtoType *Old, SourceLocation OldLoc,
+    const FunctionProtoType *New, SourceLocation NewLoc) {
+  unsigned DiagID = diag::err_mismatched_exception_spec;
+  if (getLangOpts().MicrosoftExt)
+    DiagID = diag::warn_mismatched_exception_spec; 
+  return CheckEquivalentExceptionSpec(
+                                      PDiag(DiagID),
+                                      PDiag(diag::note_previous_declaration),
+                                      Old, OldLoc, New, NewLoc);
+}
+
+/// CheckEquivalentExceptionSpec - Check if the two types have compatible
+/// exception specifications. See C++ [except.spec]p3.
+bool Sema::CheckEquivalentExceptionSpec(const PartialDiagnostic &DiagID,
+                                        const PartialDiagnostic & NoteID,
+                                        const FunctionProtoType *Old,
+                                        SourceLocation OldLoc,
+                                        const FunctionProtoType *New,
+                                        SourceLocation NewLoc,
+                                        bool *MissingExceptionSpecification,
+                                        bool*MissingEmptyExceptionSpecification,
+                                        bool AllowNoexceptAllMatchWithNoSpec,
+                                        bool IsOperatorNew) {
+  // Just completely ignore this under -fno-exceptions.
+  if (!getLangOpts().CXXExceptions)
+    return false;
+
+  if (MissingExceptionSpecification)
+    *MissingExceptionSpecification = false;
+
+  if (MissingEmptyExceptionSpecification)
+    *MissingEmptyExceptionSpecification = false;
+
+  Old = ResolveExceptionSpec(NewLoc, Old);
+  if (!Old)
+    return false;
+  New = ResolveExceptionSpec(NewLoc, New);
+  if (!New)
+    return false;
+
+  // C++0x [except.spec]p3: Two exception-specifications are compatible if:
+  //   - both are non-throwing, regardless of their form,
+  //   - both have the form noexcept(constant-expression) and the constant-
+  //     expressions are equivalent,
+  //   - both are dynamic-exception-specifications that have the same set of
+  //     adjusted types.
+  //
+  // C++0x [except.spec]p12: An exception-specifcation is non-throwing if it is
+  //   of the form throw(), noexcept, or noexcept(constant-expression) where the
+  //   constant-expression yields true.
+  //
+  // C++0x [except.spec]p4: If any declaration of a function has an exception-
+  //   specifier that is not a noexcept-specification allowing all exceptions,
+  //   all declarations [...] of that function shall have a compatible
+  //   exception-specification.
+  //
+  // That last point basically means that noexcept(false) matches no spec.
+  // It's considered when AllowNoexceptAllMatchWithNoSpec is true.
+
+  ExceptionSpecificationType OldEST = Old->getExceptionSpecType();
+  ExceptionSpecificationType NewEST = New->getExceptionSpecType();
+
+  assert(OldEST != EST_Delayed && NewEST != EST_Delayed &&
+         OldEST != EST_Uninstantiated && NewEST != EST_Uninstantiated &&
+         "Shouldn't see unknown exception specifications here");
+
+  // Shortcut the case where both have no spec.
+  if (OldEST == EST_None && NewEST == EST_None)
+    return false;
+
+  FunctionProtoType::NoexceptResult OldNR = Old->getNoexceptSpec(Context);
+  FunctionProtoType::NoexceptResult NewNR = New->getNoexceptSpec(Context);
+  if (OldNR == FunctionProtoType::NR_BadNoexcept ||
+      NewNR == FunctionProtoType::NR_BadNoexcept)
+    return false;
+
+  // Dependent noexcept specifiers are compatible with each other, but nothing
+  // else.
+  // One noexcept is compatible with another if the argument is the same
+  if (OldNR == NewNR &&
+      OldNR != FunctionProtoType::NR_NoNoexcept &&
+      NewNR != FunctionProtoType::NR_NoNoexcept)
+    return false;
+  if (OldNR != NewNR &&
+      OldNR != FunctionProtoType::NR_NoNoexcept &&
+      NewNR != FunctionProtoType::NR_NoNoexcept) {
+    Diag(NewLoc, DiagID);
+    if (NoteID.getDiagID() != 0)
+      Diag(OldLoc, NoteID);
+    return true;
+  }
+
+  // The MS extension throw(...) is compatible with itself.
+  if (OldEST == EST_MSAny && NewEST == EST_MSAny)
+    return false;
+
+  // It's also compatible with no spec.
+  if ((OldEST == EST_None && NewEST == EST_MSAny) ||
+      (OldEST == EST_MSAny && NewEST == EST_None))
+    return false;
+
+  // It's also compatible with noexcept(false).
+  if (OldEST == EST_MSAny && NewNR == FunctionProtoType::NR_Throw)
+    return false;
+  if (NewEST == EST_MSAny && OldNR == FunctionProtoType::NR_Throw)
+    return false;
+
+  // As described above, noexcept(false) matches no spec only for functions.
+  if (AllowNoexceptAllMatchWithNoSpec) {
+    if (OldEST == EST_None && NewNR == FunctionProtoType::NR_Throw)
+      return false;
+    if (NewEST == EST_None && OldNR == FunctionProtoType::NR_Throw)
+      return false;
+  }
+
+  // Any non-throwing specifications are compatible.
+  bool OldNonThrowing = OldNR == FunctionProtoType::NR_Nothrow ||
+                        OldEST == EST_DynamicNone;
+  bool NewNonThrowing = NewNR == FunctionProtoType::NR_Nothrow ||
+                        NewEST == EST_DynamicNone;
+  if (OldNonThrowing && NewNonThrowing)
+    return false;
+
+  // As a special compatibility feature, under C++0x we accept no spec and
+  // throw(std::bad_alloc) as equivalent for operator new and operator new[].
+  // This is because the implicit declaration changed, but old code would break.
+  if (getLangOpts().CPlusPlus0x && IsOperatorNew) {
+    const FunctionProtoType *WithExceptions = 0;
+    if (OldEST == EST_None && NewEST == EST_Dynamic)
+      WithExceptions = New;
+    else if (OldEST == EST_Dynamic && NewEST == EST_None)
+      WithExceptions = Old;
+    if (WithExceptions && WithExceptions->getNumExceptions() == 1) {
+      // One has no spec, the other throw(something). If that something is
+      // std::bad_alloc, all conditions are met.
+      QualType Exception = *WithExceptions->exception_begin();
+      if (CXXRecordDecl *ExRecord = Exception->getAsCXXRecordDecl()) {
+        IdentifierInfo* Name = ExRecord->getIdentifier();
+        if (Name && Name->getName() == "bad_alloc") {
+          // It's called bad_alloc, but is it in std?
+          DeclContext* DC = ExRecord->getDeclContext();
+          DC = DC->getEnclosingNamespaceContext();
+          if (NamespaceDecl* NS = dyn_cast<NamespaceDecl>(DC)) {
+            IdentifierInfo* NSName = NS->getIdentifier();
+            DC = DC->getParent();
+            if (NSName && NSName->getName() == "std" &&
+                DC->getEnclosingNamespaceContext()->isTranslationUnit()) {
+              return false;
+            }
+          }
+        }
+      }
+    }
+  }
+
+  // At this point, the only remaining valid case is two matching dynamic
+  // specifications. We return here unless both specifications are dynamic.
+  if (OldEST != EST_Dynamic || NewEST != EST_Dynamic) {
+    if (MissingExceptionSpecification && Old->hasExceptionSpec() &&
+        !New->hasExceptionSpec()) {
+      // The old type has an exception specification of some sort, but
+      // the new type does not.
+      *MissingExceptionSpecification = true;
+
+      if (MissingEmptyExceptionSpecification && OldNonThrowing) {
+        // The old type has a throw() or noexcept(true) exception specification
+        // and the new type has no exception specification, and the caller asked
+        // to handle this itself.
+        *MissingEmptyExceptionSpecification = true;
+      }
+
+      return true;
+    }
+
+    Diag(NewLoc, DiagID);
+    if (NoteID.getDiagID() != 0)
+      Diag(OldLoc, NoteID);
+    return true;
+  }
+
+  assert(OldEST == EST_Dynamic && NewEST == EST_Dynamic &&
+      "Exception compatibility logic error: non-dynamic spec slipped through.");
+
+  bool Success = true;
+  // Both have a dynamic exception spec. Collect the first set, then compare
+  // to the second.
+  llvm::SmallPtrSet<CanQualType, 8> OldTypes, NewTypes;
+  for (FunctionProtoType::exception_iterator I = Old->exception_begin(),
+       E = Old->exception_end(); I != E; ++I)
+    OldTypes.insert(Context.getCanonicalType(*I).getUnqualifiedType());
+
+  for (FunctionProtoType::exception_iterator I = New->exception_begin(),
+       E = New->exception_end(); I != E && Success; ++I) {
+    CanQualType TypePtr = Context.getCanonicalType(*I).getUnqualifiedType();
+    if(OldTypes.count(TypePtr))
+      NewTypes.insert(TypePtr);
+    else
+      Success = false;
+  }
+
+  Success = Success && OldTypes.size() == NewTypes.size();
+
+  if (Success) {
+    return false;
+  }
+  Diag(NewLoc, DiagID);
+  if (NoteID.getDiagID() != 0)
+    Diag(OldLoc, NoteID);
+  return true;
+}
+
+/// CheckExceptionSpecSubset - Check whether the second function type's
+/// exception specification is a subset (or equivalent) of the first function
+/// type. This is used by override and pointer assignment checks.
+bool Sema::CheckExceptionSpecSubset(
+    const PartialDiagnostic &DiagID, const PartialDiagnostic & NoteID,
+    const FunctionProtoType *Superset, SourceLocation SuperLoc,
+    const FunctionProtoType *Subset, SourceLocation SubLoc) {
+
+  // Just auto-succeed under -fno-exceptions.
+  if (!getLangOpts().CXXExceptions)
+    return false;
+
+  // FIXME: As usual, we could be more specific in our error messages, but
+  // that better waits until we've got types with source locations.
+
+  if (!SubLoc.isValid())
+    SubLoc = SuperLoc;
+
+  // Resolve the exception specifications, if needed.
+  Superset = ResolveExceptionSpec(SuperLoc, Superset);
+  if (!Superset)
+    return false;
+  Subset = ResolveExceptionSpec(SubLoc, Subset);
+  if (!Subset)
+    return false;
+
+  ExceptionSpecificationType SuperEST = Superset->getExceptionSpecType();
+
+  // If superset contains everything, we're done.
+  if (SuperEST == EST_None || SuperEST == EST_MSAny)
+    return CheckParamExceptionSpec(NoteID, Superset, SuperLoc, Subset, SubLoc);
+
+  // If there are dependent noexcept specs, assume everything is fine. Unlike
+  // with the equivalency check, this is safe in this case, because we don't
+  // want to merge declarations. Checks after instantiation will catch any
+  // omissions we make here.
+  // We also shortcut checking if a noexcept expression was bad.
+
+  FunctionProtoType::NoexceptResult SuperNR =Superset->getNoexceptSpec(Context);
+  if (SuperNR == FunctionProtoType::NR_BadNoexcept ||
+      SuperNR == FunctionProtoType::NR_Dependent)
+    return false;
+
+  // Another case of the superset containing everything.
+  if (SuperNR == FunctionProtoType::NR_Throw)
+    return CheckParamExceptionSpec(NoteID, Superset, SuperLoc, Subset, SubLoc);
+
+  ExceptionSpecificationType SubEST = Subset->getExceptionSpecType();
+
+  assert(SuperEST != EST_Delayed && SubEST != EST_Delayed &&
+         SuperEST != EST_Uninstantiated && SubEST != EST_Uninstantiated &&
+         "Shouldn't see unknown exception specifications here");
+
+  // It does not. If the subset contains everything, we've failed.
+  if (SubEST == EST_None || SubEST == EST_MSAny) {
+    Diag(SubLoc, DiagID);
+    if (NoteID.getDiagID() != 0)
+      Diag(SuperLoc, NoteID);
+    return true;
+  }
+
+  FunctionProtoType::NoexceptResult SubNR = Subset->getNoexceptSpec(Context);
+  if (SubNR == FunctionProtoType::NR_BadNoexcept ||
+      SubNR == FunctionProtoType::NR_Dependent)
+    return false;
+
+  // Another case of the subset containing everything.
+  if (SubNR == FunctionProtoType::NR_Throw) {
+    Diag(SubLoc, DiagID);
+    if (NoteID.getDiagID() != 0)
+      Diag(SuperLoc, NoteID);
+    return true;
+  }
+
+  // If the subset contains nothing, we're done.
+  if (SubEST == EST_DynamicNone || SubNR == FunctionProtoType::NR_Nothrow)
+    return CheckParamExceptionSpec(NoteID, Superset, SuperLoc, Subset, SubLoc);
+
+  // Otherwise, if the superset contains nothing, we've failed.
+  if (SuperEST == EST_DynamicNone || SuperNR == FunctionProtoType::NR_Nothrow) {
+    Diag(SubLoc, DiagID);
+    if (NoteID.getDiagID() != 0)
+      Diag(SuperLoc, NoteID);
+    return true;
+  }
+
+  assert(SuperEST == EST_Dynamic && SubEST == EST_Dynamic &&
+         "Exception spec subset: non-dynamic case slipped through.");
+
+  // Neither contains everything or nothing. Do a proper comparison.
+  for (FunctionProtoType::exception_iterator SubI = Subset->exception_begin(),
+       SubE = Subset->exception_end(); SubI != SubE; ++SubI) {
+    // Take one type from the subset.
+    QualType CanonicalSubT = Context.getCanonicalType(*SubI);
+    // Unwrap pointers and references so that we can do checks within a class
+    // hierarchy. Don't unwrap member pointers; they don't have hierarchy
+    // conversions on the pointee.
+    bool SubIsPointer = false;
+    if (const ReferenceType *RefTy = CanonicalSubT->getAs<ReferenceType>())
+      CanonicalSubT = RefTy->getPointeeType();
+    if (const PointerType *PtrTy = CanonicalSubT->getAs<PointerType>()) {
+      CanonicalSubT = PtrTy->getPointeeType();
+      SubIsPointer = true;
+    }
+    bool SubIsClass = CanonicalSubT->isRecordType();
+    CanonicalSubT = CanonicalSubT.getLocalUnqualifiedType();
+
+    CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
+                       /*DetectVirtual=*/false);
+
+    bool Contained = false;
+    // Make sure it's in the superset.
+    for (FunctionProtoType::exception_iterator SuperI =
+           Superset->exception_begin(), SuperE = Superset->exception_end();
+         SuperI != SuperE; ++SuperI) {
+      QualType CanonicalSuperT = Context.getCanonicalType(*SuperI);
+      // SubT must be SuperT or derived from it, or pointer or reference to
+      // such types.
+      if (const ReferenceType *RefTy = CanonicalSuperT->getAs<ReferenceType>())
+        CanonicalSuperT = RefTy->getPointeeType();
+      if (SubIsPointer) {
+        if (const PointerType *PtrTy = CanonicalSuperT->getAs<PointerType>())
+          CanonicalSuperT = PtrTy->getPointeeType();
+        else {
+          continue;
+        }
+      }
+      CanonicalSuperT = CanonicalSuperT.getLocalUnqualifiedType();
+      // If the types are the same, move on to the next type in the subset.
+      if (CanonicalSubT == CanonicalSuperT) {
+        Contained = true;
+        break;
+      }
+
+      // Otherwise we need to check the inheritance.
+      if (!SubIsClass || !CanonicalSuperT->isRecordType())
+        continue;
+
+      Paths.clear();
+      if (!IsDerivedFrom(CanonicalSubT, CanonicalSuperT, Paths))
+        continue;
+
+      if (Paths.isAmbiguous(Context.getCanonicalType(CanonicalSuperT)))
+        continue;
+
+      // Do this check from a context without privileges.
+      switch (CheckBaseClassAccess(SourceLocation(),
+                                   CanonicalSuperT, CanonicalSubT,
+                                   Paths.front(),
+                                   /*Diagnostic*/ 0,
+                                   /*ForceCheck*/ true,
+                                   /*ForceUnprivileged*/ true)) {
+      case AR_accessible: break;
+      case AR_inaccessible: continue;
+      case AR_dependent:
+        llvm_unreachable("access check dependent for unprivileged context");
+      case AR_delayed:
+        llvm_unreachable("access check delayed in non-declaration");
+      }
+
+      Contained = true;
+      break;
+    }
+    if (!Contained) {
+      Diag(SubLoc, DiagID);
+      if (NoteID.getDiagID() != 0)
+        Diag(SuperLoc, NoteID);
+      return true;
+    }
+  }
+  // We've run half the gauntlet.
+  return CheckParamExceptionSpec(NoteID, Superset, SuperLoc, Subset, SubLoc);
+}
+
+static bool CheckSpecForTypesEquivalent(Sema &S,
+    const PartialDiagnostic &DiagID, const PartialDiagnostic & NoteID,
+    QualType Target, SourceLocation TargetLoc,
+    QualType Source, SourceLocation SourceLoc)
+{
+  const FunctionProtoType *TFunc = GetUnderlyingFunction(Target);
+  if (!TFunc)
+    return false;
+  const FunctionProtoType *SFunc = GetUnderlyingFunction(Source);
+  if (!SFunc)
+    return false;
+
+  return S.CheckEquivalentExceptionSpec(DiagID, NoteID, TFunc, TargetLoc,
+                                        SFunc, SourceLoc);
+}
+
+/// CheckParamExceptionSpec - Check if the parameter and return types of the
+/// two functions have equivalent exception specs. This is part of the
+/// assignment and override compatibility check. We do not check the parameters
+/// of parameter function pointers recursively, as no sane programmer would
+/// even be able to write such a function type.
+bool Sema::CheckParamExceptionSpec(const PartialDiagnostic & NoteID,
+    const FunctionProtoType *Target, SourceLocation TargetLoc,
+    const FunctionProtoType *Source, SourceLocation SourceLoc)
+{
+  if (CheckSpecForTypesEquivalent(*this,
+                           PDiag(diag::err_deep_exception_specs_differ) << 0, 
+                                  PDiag(),
+                                  Target->getResultType(), TargetLoc,
+                                  Source->getResultType(), SourceLoc))
+    return true;
+
+  // We shouldn't even be testing this unless the arguments are otherwise
+  // compatible.
+  assert(Target->getNumArgs() == Source->getNumArgs() &&
+         "Functions have different argument counts.");
+  for (unsigned i = 0, E = Target->getNumArgs(); i != E; ++i) {
+    if (CheckSpecForTypesEquivalent(*this,
+                           PDiag(diag::err_deep_exception_specs_differ) << 1, 
+                                    PDiag(),
+                                    Target->getArgType(i), TargetLoc,
+                                    Source->getArgType(i), SourceLoc))
+      return true;
+  }
+  return false;
+}
+
+bool Sema::CheckExceptionSpecCompatibility(Expr *From, QualType ToType)
+{
+  // First we check for applicability.
+  // Target type must be a function, function pointer or function reference.
+  const FunctionProtoType *ToFunc = GetUnderlyingFunction(ToType);
+  if (!ToFunc)
+    return false;
+
+  // SourceType must be a function or function pointer.
+  const FunctionProtoType *FromFunc = GetUnderlyingFunction(From->getType());
+  if (!FromFunc)
+    return false;
+
+  // Now we've got the correct types on both sides, check their compatibility.
+  // This means that the source of the conversion can only throw a subset of
+  // the exceptions of the target, and any exception specs on arguments or
+  // return types must be equivalent.
+  return CheckExceptionSpecSubset(PDiag(diag::err_incompatible_exception_specs),
+                                  PDiag(), ToFunc, 
+                                  From->getSourceRange().getBegin(),
+                                  FromFunc, SourceLocation());
+}
+
+bool Sema::CheckOverridingFunctionExceptionSpec(const CXXMethodDecl *New,
+                                                const CXXMethodDecl *Old) {
+  if (getLangOpts().CPlusPlus0x && isa<CXXDestructorDecl>(New)) {
+    // Don't check uninstantiated template destructors at all. We can only
+    // synthesize correct specs after the template is instantiated.
+    if (New->getParent()->isDependentType())
+      return false;
+    if (New->getParent()->isBeingDefined()) {
+      // The destructor might be updated once the definition is finished. So
+      // remember it and check later.
+      DelayedDestructorExceptionSpecChecks.push_back(std::make_pair(
+        cast<CXXDestructorDecl>(New), cast<CXXDestructorDecl>(Old)));
+      return false;
+    }
+  }
+  unsigned DiagID = diag::err_override_exception_spec;
+  if (getLangOpts().MicrosoftExt)
+    DiagID = diag::warn_override_exception_spec;
+  return CheckExceptionSpecSubset(PDiag(DiagID),
+                                  PDiag(diag::note_overridden_virtual_function),
+                                  Old->getType()->getAs<FunctionProtoType>(),
+                                  Old->getLocation(),
+                                  New->getType()->getAs<FunctionProtoType>(),
+                                  New->getLocation());
+}
+
+static CanThrowResult canSubExprsThrow(Sema &S, const Expr *CE) {
+  Expr *E = const_cast<Expr*>(CE);
+  CanThrowResult R = CT_Cannot;
+  for (Expr::child_range I = E->children(); I && R != CT_Can; ++I)
+    R = mergeCanThrow(R, S.canThrow(cast<Expr>(*I)));
+  return R;
+}
+
+static CanThrowResult canCalleeThrow(Sema &S, const Expr *E,
+                                           const Decl *D,
+                                           bool NullThrows = true) {
+  if (!D)
+    return NullThrows ? CT_Can : CT_Cannot;
+
+  // See if we can get a function type from the decl somehow.
+  const ValueDecl *VD = dyn_cast<ValueDecl>(D);
+  if (!VD) // If we have no clue what we're calling, assume the worst.
+    return CT_Can;
+
+  // As an extension, we assume that __attribute__((nothrow)) functions don't
+  // throw.
+  if (isa<FunctionDecl>(D) && D->hasAttr<NoThrowAttr>())
+    return CT_Cannot;
+
+  QualType T = VD->getType();
+  const FunctionProtoType *FT;
+  if ((FT = T->getAs<FunctionProtoType>())) {
+  } else if (const PointerType *PT = T->getAs<PointerType>())
+    FT = PT->getPointeeType()->getAs<FunctionProtoType>();
+  else if (const ReferenceType *RT = T->getAs<ReferenceType>())
+    FT = RT->getPointeeType()->getAs<FunctionProtoType>();
+  else if (const MemberPointerType *MT = T->getAs<MemberPointerType>())
+    FT = MT->getPointeeType()->getAs<FunctionProtoType>();
+  else if (const BlockPointerType *BT = T->getAs<BlockPointerType>())
+    FT = BT->getPointeeType()->getAs<FunctionProtoType>();
+
+  if (!FT)
+    return CT_Can;
+
+  FT = S.ResolveExceptionSpec(E->getLocStart(), FT);
+  if (!FT)
+    return CT_Can;
+
+  if (FT->getExceptionSpecType() == EST_Delayed) {
+    // FIXME: Try to resolve a delayed exception spec in ResolveExceptionSpec.
+    assert(isa<CXXConstructorDecl>(D) &&
+           "only constructor exception specs can be unknown");
+    S.Diag(E->getLocStart(), diag::err_exception_spec_unknown)
+      << E->getSourceRange();
+    return CT_Can;
+  }
+
+  return FT->isNothrow(S.Context) ? CT_Cannot : CT_Can;
+}
+
+static CanThrowResult canDynamicCastThrow(const CXXDynamicCastExpr *DC) {
+  if (DC->isTypeDependent())
+    return CT_Dependent;
+
+  if (!DC->getTypeAsWritten()->isReferenceType())
+    return CT_Cannot;
+
+  if (DC->getSubExpr()->isTypeDependent())
+    return CT_Dependent;
+
+  return DC->getCastKind() == clang::CK_Dynamic? CT_Can : CT_Cannot;
+}
+
+static CanThrowResult canTypeidThrow(Sema &S, const CXXTypeidExpr *DC) {
+  if (DC->isTypeOperand())
+    return CT_Cannot;
+
+  Expr *Op = DC->getExprOperand();
+  if (Op->isTypeDependent())
+    return CT_Dependent;
+
+  const RecordType *RT = Op->getType()->getAs<RecordType>();
+  if (!RT)
+    return CT_Cannot;
+
+  if (!cast<CXXRecordDecl>(RT->getDecl())->isPolymorphic())
+    return CT_Cannot;
+
+  if (Op->Classify(S.Context).isPRValue())
+    return CT_Cannot;
+
+  return CT_Can;
+}
+
+CanThrowResult Sema::canThrow(const Expr *E) {
+  // C++ [expr.unary.noexcept]p3:
+  //   [Can throw] if in a potentially-evaluated context the expression would
+  //   contain:
+  switch (E->getStmtClass()) {
+  case Expr::CXXThrowExprClass:
+    //   - a potentially evaluated throw-expression
+    return CT_Can;
+
+  case Expr::CXXDynamicCastExprClass: {
+    //   - a potentially evaluated dynamic_cast expression dynamic_cast<T>(v),
+    //     where T is a reference type, that requires a run-time check
+    CanThrowResult CT = canDynamicCastThrow(cast<CXXDynamicCastExpr>(E));
+    if (CT == CT_Can)
+      return CT;
+    return mergeCanThrow(CT, canSubExprsThrow(*this, E));
+  }
+
+  case Expr::CXXTypeidExprClass:
+    //   - a potentially evaluated typeid expression applied to a glvalue
+    //     expression whose type is a polymorphic class type
+    return canTypeidThrow(*this, cast<CXXTypeidExpr>(E));
+
+    //   - a potentially evaluated call to a function, member function, function
+    //     pointer, or member function pointer that does not have a non-throwing
+    //     exception-specification
+  case Expr::CallExprClass:
+  case Expr::CXXMemberCallExprClass:
+  case Expr::CXXOperatorCallExprClass:
+  case Expr::UserDefinedLiteralClass: {
+    const CallExpr *CE = cast<CallExpr>(E);
+    CanThrowResult CT;
+    if (E->isTypeDependent())
+      CT = CT_Dependent;
+    else if (isa<CXXPseudoDestructorExpr>(CE->getCallee()->IgnoreParens()))
+      CT = CT_Cannot;
+    else
+      CT = canCalleeThrow(*this, E, CE->getCalleeDecl());
+    if (CT == CT_Can)
+      return CT;
+    return mergeCanThrow(CT, canSubExprsThrow(*this, E));
+  }
+
+  case Expr::CXXConstructExprClass:
+  case Expr::CXXTemporaryObjectExprClass: {
+    CanThrowResult CT = canCalleeThrow(*this, E,
+        cast<CXXConstructExpr>(E)->getConstructor());
+    if (CT == CT_Can)
+      return CT;
+    return mergeCanThrow(CT, canSubExprsThrow(*this, E));
+  }
+
+  case Expr::LambdaExprClass: {
+    const LambdaExpr *Lambda = cast<LambdaExpr>(E);
+    CanThrowResult CT = CT_Cannot;
+    for (LambdaExpr::capture_init_iterator Cap = Lambda->capture_init_begin(),
+                                        CapEnd = Lambda->capture_init_end();
+         Cap != CapEnd; ++Cap)
+      CT = mergeCanThrow(CT, canThrow(*Cap));
+    return CT;
+  }
+
+  case Expr::CXXNewExprClass: {
+    CanThrowResult CT;
+    if (E->isTypeDependent())
+      CT = CT_Dependent;
+    else
+      CT = canCalleeThrow(*this, E, cast<CXXNewExpr>(E)->getOperatorNew());
+    if (CT == CT_Can)
+      return CT;
+    return mergeCanThrow(CT, canSubExprsThrow(*this, E));
+  }
+
+  case Expr::CXXDeleteExprClass: {
+    CanThrowResult CT;
+    QualType DTy = cast<CXXDeleteExpr>(E)->getDestroyedType();
+    if (DTy.isNull() || DTy->isDependentType()) {
+      CT = CT_Dependent;
+    } else {
+      CT = canCalleeThrow(*this, E,
+                          cast<CXXDeleteExpr>(E)->getOperatorDelete());
+      if (const RecordType *RT = DTy->getAs<RecordType>()) {
+        const CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
+        CT = mergeCanThrow(CT, canCalleeThrow(*this, E, RD->getDestructor()));
+      }
+      if (CT == CT_Can)
+        return CT;
+    }
+    return mergeCanThrow(CT, canSubExprsThrow(*this, E));
+  }
+
+  case Expr::CXXBindTemporaryExprClass: {
+    // The bound temporary has to be destroyed again, which might throw.
+    CanThrowResult CT = canCalleeThrow(*this, E,
+      cast<CXXBindTemporaryExpr>(E)->getTemporary()->getDestructor());
+    if (CT == CT_Can)
+      return CT;
+    return mergeCanThrow(CT, canSubExprsThrow(*this, E));
+  }
+
+    // ObjC message sends are like function calls, but never have exception
+    // specs.
+  case Expr::ObjCMessageExprClass:
+  case Expr::ObjCPropertyRefExprClass:
+  case Expr::ObjCSubscriptRefExprClass:
+    return CT_Can;
+
+    // All the ObjC literals that are implemented as calls are
+    // potentially throwing unless we decide to close off that
+    // possibility.
+  case Expr::ObjCArrayLiteralClass:
+  case Expr::ObjCDictionaryLiteralClass:
+  case Expr::ObjCNumericLiteralClass:
+    return CT_Can;
+
+    // Many other things have subexpressions, so we have to test those.
+    // Some are simple:
+  case Expr::ConditionalOperatorClass:
+  case Expr::CompoundLiteralExprClass:
+  case Expr::CXXConstCastExprClass:
+  case Expr::CXXDefaultArgExprClass:
+  case Expr::CXXReinterpretCastExprClass:
+  case Expr::DesignatedInitExprClass:
+  case Expr::ExprWithCleanupsClass:
+  case Expr::ExtVectorElementExprClass:
+  case Expr::InitListExprClass:
+  case Expr::MemberExprClass:
+  case Expr::ObjCIsaExprClass:
+  case Expr::ObjCIvarRefExprClass:
+  case Expr::ParenExprClass:
+  case Expr::ParenListExprClass:
+  case Expr::ShuffleVectorExprClass:
+  case Expr::VAArgExprClass:
+    return canSubExprsThrow(*this, E);
+
+    // Some might be dependent for other reasons.
+  case Expr::ArraySubscriptExprClass:
+  case Expr::BinaryOperatorClass:
+  case Expr::CompoundAssignOperatorClass:
+  case Expr::CStyleCastExprClass:
+  case Expr::CXXStaticCastExprClass:
+  case Expr::CXXFunctionalCastExprClass:
+  case Expr::ImplicitCastExprClass:
+  case Expr::MaterializeTemporaryExprClass:
+  case Expr::UnaryOperatorClass: {
+    CanThrowResult CT = E->isTypeDependent() ? CT_Dependent : CT_Cannot;
+    return mergeCanThrow(CT, canSubExprsThrow(*this, E));
+  }
+
+    // FIXME: We should handle StmtExpr, but that opens a MASSIVE can of worms.
+  case Expr::StmtExprClass:
+    return CT_Can;
+
+  case Expr::ChooseExprClass:
+    if (E->isTypeDependent() || E->isValueDependent())
+      return CT_Dependent;
+    return canThrow(cast<ChooseExpr>(E)->getChosenSubExpr(Context));
+
+  case Expr::GenericSelectionExprClass:
+    if (cast<GenericSelectionExpr>(E)->isResultDependent())
+      return CT_Dependent;
+    return canThrow(cast<GenericSelectionExpr>(E)->getResultExpr());
+
+    // Some expressions are always dependent.
+  case Expr::CXXDependentScopeMemberExprClass:
+  case Expr::CXXUnresolvedConstructExprClass:
+  case Expr::DependentScopeDeclRefExprClass:
+    return CT_Dependent;
+
+  case Expr::AsTypeExprClass:
+  case Expr::BinaryConditionalOperatorClass:
+  case Expr::BlockExprClass:
+  case Expr::CUDAKernelCallExprClass:
+  case Expr::DeclRefExprClass:
+  case Expr::ObjCBridgedCastExprClass:
+  case Expr::ObjCIndirectCopyRestoreExprClass:
+  case Expr::ObjCProtocolExprClass:
+  case Expr::ObjCSelectorExprClass:
+  case Expr::OffsetOfExprClass:
+  case Expr::PackExpansionExprClass:
+  case Expr::PseudoObjectExprClass:
+  case Expr::SubstNonTypeTemplateParmExprClass:
+  case Expr::SubstNonTypeTemplateParmPackExprClass:
+  case Expr::UnaryExprOrTypeTraitExprClass:
+  case Expr::UnresolvedLookupExprClass:
+  case Expr::UnresolvedMemberExprClass:
+    // FIXME: Can any of the above throw?  If so, when?
+    return CT_Cannot;
+
+  case Expr::AddrLabelExprClass:
+  case Expr::ArrayTypeTraitExprClass:
+  case Expr::AtomicExprClass:
+  case Expr::BinaryTypeTraitExprClass:
+  case Expr::TypeTraitExprClass:
+  case Expr::CXXBoolLiteralExprClass:
+  case Expr::CXXNoexceptExprClass:
+  case Expr::CXXNullPtrLiteralExprClass:
+  case Expr::CXXPseudoDestructorExprClass:
+  case Expr::CXXScalarValueInitExprClass:
+  case Expr::CXXThisExprClass:
+  case Expr::CXXUuidofExprClass:
+  case Expr::CharacterLiteralClass:
+  case Expr::ExpressionTraitExprClass:
+  case Expr::FloatingLiteralClass:
+  case Expr::GNUNullExprClass:
+  case Expr::ImaginaryLiteralClass:
+  case Expr::ImplicitValueInitExprClass:
+  case Expr::IntegerLiteralClass:
+  case Expr::ObjCEncodeExprClass:
+  case Expr::ObjCStringLiteralClass:
+  case Expr::ObjCBoolLiteralExprClass:
+  case Expr::OpaqueValueExprClass:
+  case Expr::PredefinedExprClass:
+  case Expr::SizeOfPackExprClass:
+  case Expr::StringLiteralClass:
+  case Expr::UnaryTypeTraitExprClass:
+    // These expressions can never throw.
+    return CT_Cannot;
+
+#define STMT(CLASS, PARENT) case Expr::CLASS##Class:
+#define STMT_RANGE(Base, First, Last)
+#define LAST_STMT_RANGE(BASE, FIRST, LAST)
+#define EXPR(CLASS, PARENT)
+#define ABSTRACT_STMT(STMT)
+#include "clang/AST/StmtNodes.inc"
+  case Expr::NoStmtClass:
+    llvm_unreachable("Invalid class for expression");
+  }
+  llvm_unreachable("Bogus StmtClass");
+}
+
+} // end namespace clang
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
new file mode 100644
index 0000000..d2e0e6b
--- /dev/null
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -0,0 +1,11280 @@
+//===--- SemaExpr.cpp - Semantic Analysis for Expressions -----------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+//  This file implements semantic analysis for expressions.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Sema/SemaInternal.h"
+#include "clang/Sema/DelayedDiagnostic.h"
+#include "clang/Sema/Initialization.h"
+#include "clang/Sema/Lookup.h"
+#include "clang/Sema/ScopeInfo.h"
+#include "clang/Sema/AnalysisBasedWarnings.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/ASTConsumer.h"
+#include "clang/AST/ASTMutationListener.h"
+#include "clang/AST/CXXInheritance.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/AST/DeclTemplate.h"
+#include "clang/AST/EvaluatedExprVisitor.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/ExprCXX.h"
+#include "clang/AST/ExprObjC.h"
+#include "clang/AST/RecursiveASTVisitor.h"
+#include "clang/AST/TypeLoc.h"
+#include "clang/Basic/PartialDiagnostic.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Basic/TargetInfo.h"
+#include "clang/Lex/LiteralSupport.h"
+#include "clang/Lex/Preprocessor.h"
+#include "clang/Sema/DeclSpec.h"
+#include "clang/Sema/Designator.h"
+#include "clang/Sema/Scope.h"
+#include "clang/Sema/ScopeInfo.h"
+#include "clang/Sema/ParsedTemplate.h"
+#include "clang/Sema/SemaFixItUtils.h"
+#include "clang/Sema/Template.h"
+#include "TreeTransform.h"
+using namespace clang;
+using namespace sema;
+
+/// \brief Determine whether the use of this declaration is valid, without
+/// emitting diagnostics.
+bool Sema::CanUseDecl(NamedDecl *D) {
+  // See if this is an auto-typed variable whose initializer we are parsing.
+  if (ParsingInitForAutoVars.count(D))
+    return false;
+
+  // See if this is a deleted function.
+  if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
+    if (FD->isDeleted())
+      return false;
+  }
+
+  // See if this function is unavailable.
+  if (D->getAvailability() == AR_Unavailable &&
+      cast<Decl>(CurContext)->getAvailability() != AR_Unavailable)
+    return false;
+
+  return true;
+}
+
+static AvailabilityResult DiagnoseAvailabilityOfDecl(Sema &S,
+                              NamedDecl *D, SourceLocation Loc,
+                              const ObjCInterfaceDecl *UnknownObjCClass) {
+  // See if this declaration is unavailable or deprecated.
+  std::string Message;
+  AvailabilityResult Result = D->getAvailability(&Message);
+  if (const EnumConstantDecl *ECD = dyn_cast<EnumConstantDecl>(D))
+    if (Result == AR_Available) {
+      const DeclContext *DC = ECD->getDeclContext();
+      if (const EnumDecl *TheEnumDecl = dyn_cast<EnumDecl>(DC))
+        Result = TheEnumDecl->getAvailability(&Message);
+    }
+  
+  switch (Result) {
+    case AR_Available:
+    case AR_NotYetIntroduced:
+      break;
+            
+    case AR_Deprecated:
+      S.EmitDeprecationWarning(D, Message, Loc, UnknownObjCClass);
+      break;
+            
+    case AR_Unavailable:
+      if (S.getCurContextAvailability() != AR_Unavailable) {
+        if (Message.empty()) {
+          if (!UnknownObjCClass)
+            S.Diag(Loc, diag::err_unavailable) << D->getDeclName();
+          else
+            S.Diag(Loc, diag::warn_unavailable_fwdclass_message) 
+              << D->getDeclName();
+        }
+        else 
+          S.Diag(Loc, diag::err_unavailable_message) 
+            << D->getDeclName() << Message;
+          S.Diag(D->getLocation(), diag::note_unavailable_here) 
+          << isa<FunctionDecl>(D) << false;
+      }
+      break;
+    }
+    return Result;
+}
+
+/// \brief Emit a note explaining that this function is deleted or unavailable.
+void Sema::NoteDeletedFunction(FunctionDecl *Decl) {
+  CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(Decl);
+
+  if (Method && Method->isDeleted() && !Method->isDeletedAsWritten()) {
+    // If the method was explicitly defaulted, point at that declaration.
+    if (!Method->isImplicit())
+      Diag(Decl->getLocation(), diag::note_implicitly_deleted);
+
+    // Try to diagnose why this special member function was implicitly
+    // deleted. This might fail, if that reason no longer applies.
+    CXXSpecialMember CSM = getSpecialMember(Method);
+    if (CSM != CXXInvalid)
+      ShouldDeleteSpecialMember(Method, CSM, /*Diagnose=*/true);
+
+    return;
+  }
+
+  Diag(Decl->getLocation(), diag::note_unavailable_here)
+    << 1 << Decl->isDeleted();
+}
+
+/// \brief Determine whether the use of this declaration is valid, and
+/// emit any corresponding diagnostics.
+///
+/// This routine diagnoses various problems with referencing
+/// declarations that can occur when using a declaration. For example,
+/// it might warn if a deprecated or unavailable declaration is being
+/// used, or produce an error (and return true) if a C++0x deleted
+/// function is being used.
+///
+/// \returns true if there was an error (this declaration cannot be
+/// referenced), false otherwise.
+///
+bool Sema::DiagnoseUseOfDecl(NamedDecl *D, SourceLocation Loc,
+                             const ObjCInterfaceDecl *UnknownObjCClass) {
+  if (getLangOpts().CPlusPlus && isa<FunctionDecl>(D)) {
+    // If there were any diagnostics suppressed by template argument deduction,
+    // emit them now.
+    llvm::DenseMap<Decl *, SmallVector<PartialDiagnosticAt, 1> >::iterator
+      Pos = SuppressedDiagnostics.find(D->getCanonicalDecl());
+    if (Pos != SuppressedDiagnostics.end()) {
+      SmallVectorImpl<PartialDiagnosticAt> &Suppressed = Pos->second;
+      for (unsigned I = 0, N = Suppressed.size(); I != N; ++I)
+        Diag(Suppressed[I].first, Suppressed[I].second);
+      
+      // Clear out the list of suppressed diagnostics, so that we don't emit
+      // them again for this specialization. However, we don't obsolete this
+      // entry from the table, because we want to avoid ever emitting these
+      // diagnostics again.
+      Suppressed.clear();
+    }
+  }
+
+  // See if this is an auto-typed variable whose initializer we are parsing.
+  if (ParsingInitForAutoVars.count(D)) {
+    Diag(Loc, diag::err_auto_variable_cannot_appear_in_own_initializer)
+      << D->getDeclName();
+    return true;
+  }
+
+  // See if this is a deleted function.
+  if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
+    if (FD->isDeleted()) {
+      Diag(Loc, diag::err_deleted_function_use);
+      NoteDeletedFunction(FD);
+      return true;
+    }
+  }
+  DiagnoseAvailabilityOfDecl(*this, D, Loc, UnknownObjCClass);
+
+  // Warn if this is used but marked unused.
+  if (D->hasAttr<UnusedAttr>())
+    Diag(Loc, diag::warn_used_but_marked_unused) << D->getDeclName();
+  return false;
+}
+
+/// \brief Retrieve the message suffix that should be added to a
+/// diagnostic complaining about the given function being deleted or
+/// unavailable.
+std::string Sema::getDeletedOrUnavailableSuffix(const FunctionDecl *FD) {
+  // FIXME: C++0x implicitly-deleted special member functions could be
+  // detected here so that we could improve diagnostics to say, e.g.,
+  // "base class 'A' had a deleted copy constructor".
+  if (FD->isDeleted())
+    return std::string();
+
+  std::string Message;
+  if (FD->getAvailability(&Message))
+    return ": " + Message;
+
+  return std::string();
+}
+
+/// DiagnoseSentinelCalls - This routine checks whether a call or
+/// message-send is to a declaration with the sentinel attribute, and
+/// if so, it checks that the requirements of the sentinel are
+/// satisfied.
+void Sema::DiagnoseSentinelCalls(NamedDecl *D, SourceLocation Loc,
+                                 Expr **args, unsigned numArgs) {
+  const SentinelAttr *attr = D->getAttr<SentinelAttr>();
+  if (!attr)
+    return;
+
+  // The number of formal parameters of the declaration.
+  unsigned numFormalParams;
+
+  // The kind of declaration.  This is also an index into a %select in
+  // the diagnostic.
+  enum CalleeType { CT_Function, CT_Method, CT_Block } calleeType;
+
+  if (ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) {
+    numFormalParams = MD->param_size();
+    calleeType = CT_Method;
+  } else if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
+    numFormalParams = FD->param_size();
+    calleeType = CT_Function;
+  } else if (isa<VarDecl>(D)) {
+    QualType type = cast<ValueDecl>(D)->getType();
+    const FunctionType *fn = 0;
+    if (const PointerType *ptr = type->getAs<PointerType>()) {
+      fn = ptr->getPointeeType()->getAs<FunctionType>();
+      if (!fn) return;
+      calleeType = CT_Function;
+    } else if (const BlockPointerType *ptr = type->getAs<BlockPointerType>()) {
+      fn = ptr->getPointeeType()->castAs<FunctionType>();
+      calleeType = CT_Block;
+    } else {
+      return;
+    }
+
+    if (const FunctionProtoType *proto = dyn_cast<FunctionProtoType>(fn)) {
+      numFormalParams = proto->getNumArgs();
+    } else {
+      numFormalParams = 0;
+    }
+  } else {
+    return;
+  }
+
+  // "nullPos" is the number of formal parameters at the end which
+  // effectively count as part of the variadic arguments.  This is
+  // useful if you would prefer to not have *any* formal parameters,
+  // but the language forces you to have at least one.
+  unsigned nullPos = attr->getNullPos();
+  assert((nullPos == 0 || nullPos == 1) && "invalid null position on sentinel");
+  numFormalParams = (nullPos > numFormalParams ? 0 : numFormalParams - nullPos);
+
+  // The number of arguments which should follow the sentinel.
+  unsigned numArgsAfterSentinel = attr->getSentinel();
+
+  // If there aren't enough arguments for all the formal parameters,
+  // the sentinel, and the args after the sentinel, complain.
+  if (numArgs < numFormalParams + numArgsAfterSentinel + 1) {
+    Diag(Loc, diag::warn_not_enough_argument) << D->getDeclName();
+    Diag(D->getLocation(), diag::note_sentinel_here) << calleeType;
+    return;
+  }
+
+  // Otherwise, find the sentinel expression.
+  Expr *sentinelExpr = args[numArgs - numArgsAfterSentinel - 1];
+  if (!sentinelExpr) return;
+  if (sentinelExpr->isValueDependent()) return;
+  if (Context.isSentinelNullExpr(sentinelExpr)) return;
+
+  // Pick a reasonable string to insert.  Optimistically use 'nil' or
+  // 'NULL' if those are actually defined in the context.  Only use
+  // 'nil' for ObjC methods, where it's much more likely that the
+  // variadic arguments form a list of object pointers.
+  SourceLocation MissingNilLoc
+    = PP.getLocForEndOfToken(sentinelExpr->getLocEnd());
+  std::string NullValue;
+  if (calleeType == CT_Method &&
+      PP.getIdentifierInfo("nil")->hasMacroDefinition())
+    NullValue = "nil";
+  else if (PP.getIdentifierInfo("NULL")->hasMacroDefinition())
+    NullValue = "NULL";
+  else
+    NullValue = "(void*) 0";
+
+  if (MissingNilLoc.isInvalid())
+    Diag(Loc, diag::warn_missing_sentinel) << calleeType;
+  else
+    Diag(MissingNilLoc, diag::warn_missing_sentinel) 
+      << calleeType
+      << FixItHint::CreateInsertion(MissingNilLoc, ", " + NullValue);
+  Diag(D->getLocation(), diag::note_sentinel_here) << calleeType;
+}
+
+SourceRange Sema::getExprRange(Expr *E) const {
+  return E ? E->getSourceRange() : SourceRange();
+}
+
+//===----------------------------------------------------------------------===//
+//  Standard Promotions and Conversions
+//===----------------------------------------------------------------------===//
+
+/// DefaultFunctionArrayConversion (C99 6.3.2.1p3, C99 6.3.2.1p4).
+ExprResult Sema::DefaultFunctionArrayConversion(Expr *E) {
+  // Handle any placeholder expressions which made it here.
+  if (E->getType()->isPlaceholderType()) {
+    ExprResult result = CheckPlaceholderExpr(E);
+    if (result.isInvalid()) return ExprError();
+    E = result.take();
+  }
+  
+  QualType Ty = E->getType();
+  assert(!Ty.isNull() && "DefaultFunctionArrayConversion - missing type");
+
+  if (Ty->isFunctionType())
+    E = ImpCastExprToType(E, Context.getPointerType(Ty),
+                          CK_FunctionToPointerDecay).take();
+  else if (Ty->isArrayType()) {
+    // In C90 mode, arrays only promote to pointers if the array expression is
+    // an lvalue.  The relevant legalese is C90 6.2.2.1p3: "an lvalue that has
+    // type 'array of type' is converted to an expression that has type 'pointer
+    // to type'...".  In C99 this was changed to: C99 6.3.2.1p3: "an expression
+    // that has type 'array of type' ...".  The relevant change is "an lvalue"
+    // (C90) to "an expression" (C99).
+    //
+    // C++ 4.2p1:
+    // An lvalue or rvalue of type "array of N T" or "array of unknown bound of
+    // T" can be converted to an rvalue of type "pointer to T".
+    //
+    if (getLangOpts().C99 || getLangOpts().CPlusPlus || E->isLValue())
+      E = ImpCastExprToType(E, Context.getArrayDecayedType(Ty),
+                            CK_ArrayToPointerDecay).take();
+  }
+  return Owned(E);
+}
+
+static void CheckForNullPointerDereference(Sema &S, Expr *E) {
+  // Check to see if we are dereferencing a null pointer.  If so,
+  // and if not volatile-qualified, this is undefined behavior that the
+  // optimizer will delete, so warn about it.  People sometimes try to use this
+  // to get a deterministic trap and are surprised by clang's behavior.  This
+  // only handles the pattern "*null", which is a very syntactic check.
+  if (UnaryOperator *UO = dyn_cast<UnaryOperator>(E->IgnoreParenCasts()))
+    if (UO->getOpcode() == UO_Deref &&
+        UO->getSubExpr()->IgnoreParenCasts()->
+          isNullPointerConstant(S.Context, Expr::NPC_ValueDependentIsNotNull) &&
+        !UO->getType().isVolatileQualified()) {
+    S.DiagRuntimeBehavior(UO->getOperatorLoc(), UO,
+                          S.PDiag(diag::warn_indirection_through_null)
+                            << UO->getSubExpr()->getSourceRange());
+    S.DiagRuntimeBehavior(UO->getOperatorLoc(), UO,
+                        S.PDiag(diag::note_indirection_through_null));
+  }
+}
+
+ExprResult Sema::DefaultLvalueConversion(Expr *E) {
+  // Handle any placeholder expressions which made it here.
+  if (E->getType()->isPlaceholderType()) {
+    ExprResult result = CheckPlaceholderExpr(E);
+    if (result.isInvalid()) return ExprError();
+    E = result.take();
+  }
+  
+  // C++ [conv.lval]p1:
+  //   A glvalue of a non-function, non-array type T can be
+  //   converted to a prvalue.
+  if (!E->isGLValue()) return Owned(E);
+
+  QualType T = E->getType();
+  assert(!T.isNull() && "r-value conversion on typeless expression?");
+
+  // We don't want to throw lvalue-to-rvalue casts on top of
+  // expressions of certain types in C++.
+  if (getLangOpts().CPlusPlus &&
+      (E->getType() == Context.OverloadTy ||
+       T->isDependentType() ||
+       T->isRecordType()))
+    return Owned(E);
+
+  // The C standard is actually really unclear on this point, and
+  // DR106 tells us what the result should be but not why.  It's
+  // generally best to say that void types just doesn't undergo
+  // lvalue-to-rvalue at all.  Note that expressions of unqualified
+  // 'void' type are never l-values, but qualified void can be.
+  if (T->isVoidType())
+    return Owned(E);
+
+  CheckForNullPointerDereference(*this, E);
+
+  // C++ [conv.lval]p1:
+  //   [...] If T is a non-class type, the type of the prvalue is the
+  //   cv-unqualified version of T. Otherwise, the type of the
+  //   rvalue is T.
+  //
+  // C99 6.3.2.1p2:
+  //   If the lvalue has qualified type, the value has the unqualified
+  //   version of the type of the lvalue; otherwise, the value has the
+  //   type of the lvalue.
+  if (T.hasQualifiers())
+    T = T.getUnqualifiedType();
+
+  UpdateMarkingForLValueToRValue(E);
+
+  ExprResult Res = Owned(ImplicitCastExpr::Create(Context, T, CK_LValueToRValue,
+                                                  E, 0, VK_RValue));
+
+  // C11 6.3.2.1p2:
+  //   ... if the lvalue has atomic type, the value has the non-atomic version 
+  //   of the type of the lvalue ...
+  if (const AtomicType *Atomic = T->getAs<AtomicType>()) {
+    T = Atomic->getValueType().getUnqualifiedType();
+    Res = Owned(ImplicitCastExpr::Create(Context, T, CK_AtomicToNonAtomic,
+                                         Res.get(), 0, VK_RValue));
+  }
+  
+  return Res;
+}
+
+ExprResult Sema::DefaultFunctionArrayLvalueConversion(Expr *E) {
+  ExprResult Res = DefaultFunctionArrayConversion(E);
+  if (Res.isInvalid())
+    return ExprError();
+  Res = DefaultLvalueConversion(Res.take());
+  if (Res.isInvalid())
+    return ExprError();
+  return move(Res);
+}
+
+
+/// UsualUnaryConversions - Performs various conversions that are common to most
+/// operators (C99 6.3). The conversions of array and function types are
+/// sometimes suppressed. For example, the array->pointer conversion doesn't
+/// apply if the array is an argument to the sizeof or address (&) operators.
+/// In these instances, this routine should *not* be called.
+ExprResult Sema::UsualUnaryConversions(Expr *E) {
+  // First, convert to an r-value.
+  ExprResult Res = DefaultFunctionArrayLvalueConversion(E);
+  if (Res.isInvalid())
+    return Owned(E);
+  E = Res.take();
+
+  QualType Ty = E->getType();
+  assert(!Ty.isNull() && "UsualUnaryConversions - missing type");
+
+  // Half FP is a bit different: it's a storage-only type, meaning that any
+  // "use" of it should be promoted to float.
+  if (Ty->isHalfType())
+    return ImpCastExprToType(Res.take(), Context.FloatTy, CK_FloatingCast);
+
+  // Try to perform integral promotions if the object has a theoretically
+  // promotable type.
+  if (Ty->isIntegralOrUnscopedEnumerationType()) {
+    // C99 6.3.1.1p2:
+    //
+    //   The following may be used in an expression wherever an int or
+    //   unsigned int may be used:
+    //     - an object or expression with an integer type whose integer
+    //       conversion rank is less than or equal to the rank of int
+    //       and unsigned int.
+    //     - A bit-field of type _Bool, int, signed int, or unsigned int.
+    //
+    //   If an int can represent all values of the original type, the
+    //   value is converted to an int; otherwise, it is converted to an
+    //   unsigned int. These are called the integer promotions. All
+    //   other types are unchanged by the integer promotions.
+
+    QualType PTy = Context.isPromotableBitField(E);
+    if (!PTy.isNull()) {
+      E = ImpCastExprToType(E, PTy, CK_IntegralCast).take();
+      return Owned(E);
+    }
+    if (Ty->isPromotableIntegerType()) {
+      QualType PT = Context.getPromotedIntegerType(Ty);
+      E = ImpCastExprToType(E, PT, CK_IntegralCast).take();
+      return Owned(E);
+    }
+  }
+  return Owned(E);
+}
+
+/// DefaultArgumentPromotion (C99 6.5.2.2p6). Used for function calls that
+/// do not have a prototype. Arguments that have type float are promoted to
+/// double. All other argument types are converted by UsualUnaryConversions().
+ExprResult Sema::DefaultArgumentPromotion(Expr *E) {
+  QualType Ty = E->getType();
+  assert(!Ty.isNull() && "DefaultArgumentPromotion - missing type");
+
+  ExprResult Res = UsualUnaryConversions(E);
+  if (Res.isInvalid())
+    return Owned(E);
+  E = Res.take();
+
+  // If this is a 'float' (CVR qualified or typedef) promote to double.
+  if (Ty->isSpecificBuiltinType(BuiltinType::Float))
+    E = ImpCastExprToType(E, Context.DoubleTy, CK_FloatingCast).take();
+
+  // C++ performs lvalue-to-rvalue conversion as a default argument
+  // promotion, even on class types, but note:
+  //   C++11 [conv.lval]p2:
+  //     When an lvalue-to-rvalue conversion occurs in an unevaluated
+  //     operand or a subexpression thereof the value contained in the
+  //     referenced object is not accessed. Otherwise, if the glvalue
+  //     has a class type, the conversion copy-initializes a temporary
+  //     of type T from the glvalue and the result of the conversion
+  //     is a prvalue for the temporary.
+  // FIXME: add some way to gate this entire thing for correctness in
+  // potentially potentially evaluated contexts.
+  if (getLangOpts().CPlusPlus && E->isGLValue() && 
+      ExprEvalContexts.back().Context != Unevaluated) {
+    ExprResult Temp = PerformCopyInitialization(
+                       InitializedEntity::InitializeTemporary(E->getType()),
+                                                E->getExprLoc(),
+                                                Owned(E));
+    if (Temp.isInvalid())
+      return ExprError();
+    E = Temp.get();
+  }
+
+  return Owned(E);
+}
+
+/// DefaultVariadicArgumentPromotion - Like DefaultArgumentPromotion, but
+/// will warn if the resulting type is not a POD type, and rejects ObjC
+/// interfaces passed by value.
+ExprResult Sema::DefaultVariadicArgumentPromotion(Expr *E, VariadicCallType CT,
+                                                  FunctionDecl *FDecl) {
+  if (const BuiltinType *PlaceholderTy = E->getType()->getAsPlaceholderType()) {
+    // Strip the unbridged-cast placeholder expression off, if applicable.
+    if (PlaceholderTy->getKind() == BuiltinType::ARCUnbridgedCast &&
+        (CT == VariadicMethod ||
+         (FDecl && FDecl->hasAttr<CFAuditedTransferAttr>()))) {
+      E = stripARCUnbridgedCast(E);
+
+    // Otherwise, do normal placeholder checking.
+    } else {
+      ExprResult ExprRes = CheckPlaceholderExpr(E);
+      if (ExprRes.isInvalid())
+        return ExprError();
+      E = ExprRes.take();
+    }
+  }
+  
+  ExprResult ExprRes = DefaultArgumentPromotion(E);
+  if (ExprRes.isInvalid())
+    return ExprError();
+  E = ExprRes.take();
+
+  // Don't allow one to pass an Objective-C interface to a vararg.
+  if (E->getType()->isObjCObjectType() &&
+    DiagRuntimeBehavior(E->getLocStart(), 0,
+                        PDiag(diag::err_cannot_pass_objc_interface_to_vararg)
+                          << E->getType() << CT))
+    return ExprError();
+
+  // Complain about passing non-POD types through varargs. However, don't
+  // perform this check for incomplete types, which we can get here when we're
+  // in an unevaluated context.
+  if (!E->getType()->isIncompleteType() && !E->getType().isPODType(Context)) {
+    // C++0x [expr.call]p7:
+    //   Passing a potentially-evaluated argument of class type (Clause 9) 
+    //   having a non-trivial copy constructor, a non-trivial move constructor,
+    //   or a non-trivial destructor, with no corresponding parameter, 
+    //   is conditionally-supported with implementation-defined semantics.
+    bool TrivialEnough = false;
+    if (getLangOpts().CPlusPlus0x && !E->getType()->isDependentType())  {
+      if (CXXRecordDecl *Record = E->getType()->getAsCXXRecordDecl()) {
+        if (Record->hasTrivialCopyConstructor() &&
+            Record->hasTrivialMoveConstructor() &&
+            Record->hasTrivialDestructor()) {
+          DiagRuntimeBehavior(E->getLocStart(), 0,
+            PDiag(diag::warn_cxx98_compat_pass_non_pod_arg_to_vararg)
+              << E->getType() << CT);
+          TrivialEnough = true;
+        }
+      }
+    }
+
+    if (!TrivialEnough &&
+        getLangOpts().ObjCAutoRefCount &&
+        E->getType()->isObjCLifetimeType())
+      TrivialEnough = true;
+      
+    if (TrivialEnough) {
+      // Nothing to diagnose. This is okay.
+    } else if (DiagRuntimeBehavior(E->getLocStart(), 0,
+                          PDiag(diag::warn_cannot_pass_non_pod_arg_to_vararg)
+                            << getLangOpts().CPlusPlus0x << E->getType() 
+                            << CT)) {
+      // Turn this into a trap.
+      CXXScopeSpec SS;
+      SourceLocation TemplateKWLoc;
+      UnqualifiedId Name;
+      Name.setIdentifier(PP.getIdentifierInfo("__builtin_trap"),
+                         E->getLocStart());
+      ExprResult TrapFn = ActOnIdExpression(TUScope, SS, TemplateKWLoc, Name,
+                                            true, false);
+      if (TrapFn.isInvalid())
+        return ExprError();
+
+      ExprResult Call = ActOnCallExpr(TUScope, TrapFn.get(), E->getLocStart(),
+                                      MultiExprArg(), E->getLocEnd());
+      if (Call.isInvalid())
+        return ExprError();
+      
+      ExprResult Comma = ActOnBinOp(TUScope, E->getLocStart(), tok::comma,
+                                    Call.get(), E);
+      if (Comma.isInvalid())
+        return ExprError();      
+      E = Comma.get();
+    }
+  }
+  // c++ rules are enforced elsewhere.
+  if (!getLangOpts().CPlusPlus &&
+      RequireCompleteType(E->getExprLoc(), E->getType(),
+                          diag::err_call_incomplete_argument))
+    return ExprError();
+  
+  return Owned(E);
+}
+
+/// \brief Converts an integer to complex float type.  Helper function of
+/// UsualArithmeticConversions()
+///
+/// \return false if the integer expression is an integer type and is
+/// successfully converted to the complex type.
+static bool handleIntegerToComplexFloatConversion(Sema &S, ExprResult &IntExpr,
+                                                  ExprResult &ComplexExpr,
+                                                  QualType IntTy,
+                                                  QualType ComplexTy,
+                                                  bool SkipCast) {
+  if (IntTy->isComplexType() || IntTy->isRealFloatingType()) return true;
+  if (SkipCast) return false;
+  if (IntTy->isIntegerType()) {
+    QualType fpTy = cast<ComplexType>(ComplexTy)->getElementType();
+    IntExpr = S.ImpCastExprToType(IntExpr.take(), fpTy, CK_IntegralToFloating);
+    IntExpr = S.ImpCastExprToType(IntExpr.take(), ComplexTy,
+                                  CK_FloatingRealToComplex);
+  } else {
+    assert(IntTy->isComplexIntegerType());
+    IntExpr = S.ImpCastExprToType(IntExpr.take(), ComplexTy,
+                                  CK_IntegralComplexToFloatingComplex);
+  }
+  return false;
+}
+
+/// \brief Takes two complex float types and converts them to the same type.
+/// Helper function of UsualArithmeticConversions()
+static QualType
+handleComplexFloatToComplexFloatConverstion(Sema &S, ExprResult &LHS,
+                                            ExprResult &RHS, QualType LHSType,
+                                            QualType RHSType,
+                                            bool IsCompAssign) {
+  int order = S.Context.getFloatingTypeOrder(LHSType, RHSType);
+
+  if (order < 0) {
+    // _Complex float -> _Complex double
+    if (!IsCompAssign)
+      LHS = S.ImpCastExprToType(LHS.take(), RHSType, CK_FloatingComplexCast);
+    return RHSType;
+  }
+  if (order > 0)
+    // _Complex float -> _Complex double
+    RHS = S.ImpCastExprToType(RHS.take(), LHSType, CK_FloatingComplexCast);
+  return LHSType;
+}
+
+/// \brief Converts otherExpr to complex float and promotes complexExpr if
+/// necessary.  Helper function of UsualArithmeticConversions()
+static QualType handleOtherComplexFloatConversion(Sema &S,
+                                                  ExprResult &ComplexExpr,
+                                                  ExprResult &OtherExpr,
+                                                  QualType ComplexTy,
+                                                  QualType OtherTy,
+                                                  bool ConvertComplexExpr,
+                                                  bool ConvertOtherExpr) {
+  int order = S.Context.getFloatingTypeOrder(ComplexTy, OtherTy);
+
+  // If just the complexExpr is complex, the otherExpr needs to be converted,
+  // and the complexExpr might need to be promoted.
+  if (order > 0) { // complexExpr is wider
+    // float -> _Complex double
+    if (ConvertOtherExpr) {
+      QualType fp = cast<ComplexType>(ComplexTy)->getElementType();
+      OtherExpr = S.ImpCastExprToType(OtherExpr.take(), fp, CK_FloatingCast);
+      OtherExpr = S.ImpCastExprToType(OtherExpr.take(), ComplexTy,
+                                      CK_FloatingRealToComplex);
+    }
+    return ComplexTy;
+  }
+
+  // otherTy is at least as wide.  Find its corresponding complex type.
+  QualType result = (order == 0 ? ComplexTy :
+                                  S.Context.getComplexType(OtherTy));
+
+  // double -> _Complex double
+  if (ConvertOtherExpr)
+    OtherExpr = S.ImpCastExprToType(OtherExpr.take(), result,
+                                    CK_FloatingRealToComplex);
+
+  // _Complex float -> _Complex double
+  if (ConvertComplexExpr && order < 0)
+    ComplexExpr = S.ImpCastExprToType(ComplexExpr.take(), result,
+                                      CK_FloatingComplexCast);
+
+  return result;
+}
+
+/// \brief Handle arithmetic conversion with complex types.  Helper function of
+/// UsualArithmeticConversions()
+static QualType handleComplexFloatConversion(Sema &S, ExprResult &LHS,
+                                             ExprResult &RHS, QualType LHSType,
+                                             QualType RHSType,
+                                             bool IsCompAssign) {
+  // if we have an integer operand, the result is the complex type.
+  if (!handleIntegerToComplexFloatConversion(S, RHS, LHS, RHSType, LHSType,
+                                             /*skipCast*/false))
+    return LHSType;
+  if (!handleIntegerToComplexFloatConversion(S, LHS, RHS, LHSType, RHSType,
+                                             /*skipCast*/IsCompAssign))
+    return RHSType;
+
+  // This handles complex/complex, complex/float, or float/complex.
+  // When both operands are complex, the shorter operand is converted to the
+  // type of the longer, and that is the type of the result. This corresponds
+  // to what is done when combining two real floating-point operands.
+  // The fun begins when size promotion occur across type domains.
+  // From H&S 6.3.4: When one operand is complex and the other is a real
+  // floating-point type, the less precise type is converted, within it's
+  // real or complex domain, to the precision of the other type. For example,
+  // when combining a "long double" with a "double _Complex", the
+  // "double _Complex" is promoted to "long double _Complex".
+
+  bool LHSComplexFloat = LHSType->isComplexType();
+  bool RHSComplexFloat = RHSType->isComplexType();
+
+  // If both are complex, just cast to the more precise type.
+  if (LHSComplexFloat && RHSComplexFloat)
+    return handleComplexFloatToComplexFloatConverstion(S, LHS, RHS,
+                                                       LHSType, RHSType,
+                                                       IsCompAssign);
+
+  // If only one operand is complex, promote it if necessary and convert the
+  // other operand to complex.
+  if (LHSComplexFloat)
+    return handleOtherComplexFloatConversion(
+        S, LHS, RHS, LHSType, RHSType, /*convertComplexExpr*/!IsCompAssign,
+        /*convertOtherExpr*/ true);
+
+  assert(RHSComplexFloat);
+  return handleOtherComplexFloatConversion(
+      S, RHS, LHS, RHSType, LHSType, /*convertComplexExpr*/true,
+      /*convertOtherExpr*/ !IsCompAssign);
+}
+
+/// \brief Hande arithmetic conversion from integer to float.  Helper function
+/// of UsualArithmeticConversions()
+static QualType handleIntToFloatConversion(Sema &S, ExprResult &FloatExpr,
+                                           ExprResult &IntExpr,
+                                           QualType FloatTy, QualType IntTy,
+                                           bool ConvertFloat, bool ConvertInt) {
+  if (IntTy->isIntegerType()) {
+    if (ConvertInt)
+      // Convert intExpr to the lhs floating point type.
+      IntExpr = S.ImpCastExprToType(IntExpr.take(), FloatTy,
+                                    CK_IntegralToFloating);
+    return FloatTy;
+  }
+     
+  // Convert both sides to the appropriate complex float.
+  assert(IntTy->isComplexIntegerType());
+  QualType result = S.Context.getComplexType(FloatTy);
+
+  // _Complex int -> _Complex float
+  if (ConvertInt)
+    IntExpr = S.ImpCastExprToType(IntExpr.take(), result,
+                                  CK_IntegralComplexToFloatingComplex);
+
+  // float -> _Complex float
+  if (ConvertFloat)
+    FloatExpr = S.ImpCastExprToType(FloatExpr.take(), result,
+                                    CK_FloatingRealToComplex);
+
+  return result;
+}
+
+/// \brief Handle arithmethic conversion with floating point types.  Helper
+/// function of UsualArithmeticConversions()
+static QualType handleFloatConversion(Sema &S, ExprResult &LHS,
+                                      ExprResult &RHS, QualType LHSType,
+                                      QualType RHSType, bool IsCompAssign) {
+  bool LHSFloat = LHSType->isRealFloatingType();
+  bool RHSFloat = RHSType->isRealFloatingType();
+
+  // If we have two real floating types, convert the smaller operand
+  // to the bigger result.
+  if (LHSFloat && RHSFloat) {
+    int order = S.Context.getFloatingTypeOrder(LHSType, RHSType);
+    if (order > 0) {
+      RHS = S.ImpCastExprToType(RHS.take(), LHSType, CK_FloatingCast);
+      return LHSType;
+    }
+
+    assert(order < 0 && "illegal float comparison");
+    if (!IsCompAssign)
+      LHS = S.ImpCastExprToType(LHS.take(), RHSType, CK_FloatingCast);
+    return RHSType;
+  }
+
+  if (LHSFloat)
+    return handleIntToFloatConversion(S, LHS, RHS, LHSType, RHSType,
+                                      /*convertFloat=*/!IsCompAssign,
+                                      /*convertInt=*/ true);
+  assert(RHSFloat);
+  return handleIntToFloatConversion(S, RHS, LHS, RHSType, LHSType,
+                                    /*convertInt=*/ true,
+                                    /*convertFloat=*/!IsCompAssign);
+}
+
+/// \brief Handle conversions with GCC complex int extension.  Helper function
+/// of UsualArithmeticConversions()
+// FIXME: if the operands are (int, _Complex long), we currently
+// don't promote the complex.  Also, signedness?
+static QualType handleComplexIntConversion(Sema &S, ExprResult &LHS,
+                                           ExprResult &RHS, QualType LHSType,
+                                           QualType RHSType,
+                                           bool IsCompAssign) {
+  const ComplexType *LHSComplexInt = LHSType->getAsComplexIntegerType();
+  const ComplexType *RHSComplexInt = RHSType->getAsComplexIntegerType();
+
+  if (LHSComplexInt && RHSComplexInt) {
+    int order = S.Context.getIntegerTypeOrder(LHSComplexInt->getElementType(),
+                                              RHSComplexInt->getElementType());
+    assert(order && "inequal types with equal element ordering");
+    if (order > 0) {
+      // _Complex int -> _Complex long
+      RHS = S.ImpCastExprToType(RHS.take(), LHSType, CK_IntegralComplexCast);
+      return LHSType;
+    }
+
+    if (!IsCompAssign)
+      LHS = S.ImpCastExprToType(LHS.take(), RHSType, CK_IntegralComplexCast);
+    return RHSType;
+  }
+
+  if (LHSComplexInt) {
+    // int -> _Complex int
+    // FIXME: This needs to take integer ranks into account
+    RHS = S.ImpCastExprToType(RHS.take(), LHSComplexInt->getElementType(),
+                              CK_IntegralCast);
+    RHS = S.ImpCastExprToType(RHS.take(), LHSType, CK_IntegralRealToComplex);
+    return LHSType;
+  }
+
+  assert(RHSComplexInt);
+  // int -> _Complex int
+  // FIXME: This needs to take integer ranks into account
+  if (!IsCompAssign) {
+    LHS = S.ImpCastExprToType(LHS.take(), RHSComplexInt->getElementType(),
+                              CK_IntegralCast);
+    LHS = S.ImpCastExprToType(LHS.take(), RHSType, CK_IntegralRealToComplex);
+  }
+  return RHSType;
+}
+
+/// \brief Handle integer arithmetic conversions.  Helper function of
+/// UsualArithmeticConversions()
+static QualType handleIntegerConversion(Sema &S, ExprResult &LHS,
+                                        ExprResult &RHS, QualType LHSType,
+                                        QualType RHSType, bool IsCompAssign) {
+  // The rules for this case are in C99 6.3.1.8
+  int order = S.Context.getIntegerTypeOrder(LHSType, RHSType);
+  bool LHSSigned = LHSType->hasSignedIntegerRepresentation();
+  bool RHSSigned = RHSType->hasSignedIntegerRepresentation();
+  if (LHSSigned == RHSSigned) {
+    // Same signedness; use the higher-ranked type
+    if (order >= 0) {
+      RHS = S.ImpCastExprToType(RHS.take(), LHSType, CK_IntegralCast);
+      return LHSType;
+    } else if (!IsCompAssign)
+      LHS = S.ImpCastExprToType(LHS.take(), RHSType, CK_IntegralCast);
+    return RHSType;
+  } else if (order != (LHSSigned ? 1 : -1)) {
+    // The unsigned type has greater than or equal rank to the
+    // signed type, so use the unsigned type
+    if (RHSSigned) {
+      RHS = S.ImpCastExprToType(RHS.take(), LHSType, CK_IntegralCast);
+      return LHSType;
+    } else if (!IsCompAssign)
+      LHS = S.ImpCastExprToType(LHS.take(), RHSType, CK_IntegralCast);
+    return RHSType;
+  } else if (S.Context.getIntWidth(LHSType) != S.Context.getIntWidth(RHSType)) {
+    // The two types are different widths; if we are here, that
+    // means the signed type is larger than the unsigned type, so
+    // use the signed type.
+    if (LHSSigned) {
+      RHS = S.ImpCastExprToType(RHS.take(), LHSType, CK_IntegralCast);
+      return LHSType;
+    } else if (!IsCompAssign)
+      LHS = S.ImpCastExprToType(LHS.take(), RHSType, CK_IntegralCast);
+    return RHSType;
+  } else {
+    // The signed type is higher-ranked than the unsigned type,
+    // but isn't actually any bigger (like unsigned int and long
+    // on most 32-bit systems).  Use the unsigned type corresponding
+    // to the signed type.
+    QualType result =
+      S.Context.getCorrespondingUnsignedType(LHSSigned ? LHSType : RHSType);
+    RHS = S.ImpCastExprToType(RHS.take(), result, CK_IntegralCast);
+    if (!IsCompAssign)
+      LHS = S.ImpCastExprToType(LHS.take(), result, CK_IntegralCast);
+    return result;
+  }
+}
+
+/// UsualArithmeticConversions - Performs various conversions that are common to
+/// binary operators (C99 6.3.1.8). If both operands aren't arithmetic, this
+/// routine returns the first non-arithmetic type found. The client is
+/// responsible for emitting appropriate error diagnostics.
+/// FIXME: verify the conversion rules for "complex int" are consistent with
+/// GCC.
+QualType Sema::UsualArithmeticConversions(ExprResult &LHS, ExprResult &RHS,
+                                          bool IsCompAssign) {
+  if (!IsCompAssign) {
+    LHS = UsualUnaryConversions(LHS.take());
+    if (LHS.isInvalid())
+      return QualType();
+  }
+
+  RHS = UsualUnaryConversions(RHS.take());
+  if (RHS.isInvalid())
+    return QualType();
+
+  // For conversion purposes, we ignore any qualifiers.
+  // For example, "const float" and "float" are equivalent.
+  QualType LHSType =
+    Context.getCanonicalType(LHS.get()->getType()).getUnqualifiedType();
+  QualType RHSType =
+    Context.getCanonicalType(RHS.get()->getType()).getUnqualifiedType();
+
+  // If both types are identical, no conversion is needed.
+  if (LHSType == RHSType)
+    return LHSType;
+
+  // If either side is a non-arithmetic type (e.g. a pointer), we are done.
+  // The caller can deal with this (e.g. pointer + int).
+  if (!LHSType->isArithmeticType() || !RHSType->isArithmeticType())
+    return LHSType;
+
+  // Apply unary and bitfield promotions to the LHS's type.
+  QualType LHSUnpromotedType = LHSType;
+  if (LHSType->isPromotableIntegerType())
+    LHSType = Context.getPromotedIntegerType(LHSType);
+  QualType LHSBitfieldPromoteTy = Context.isPromotableBitField(LHS.get());
+  if (!LHSBitfieldPromoteTy.isNull())
+    LHSType = LHSBitfieldPromoteTy;
+  if (LHSType != LHSUnpromotedType && !IsCompAssign)
+    LHS = ImpCastExprToType(LHS.take(), LHSType, CK_IntegralCast);
+
+  // If both types are identical, no conversion is needed.
+  if (LHSType == RHSType)
+    return LHSType;
+
+  // At this point, we have two different arithmetic types.
+
+  // Handle complex types first (C99 6.3.1.8p1).
+  if (LHSType->isComplexType() || RHSType->isComplexType())
+    return handleComplexFloatConversion(*this, LHS, RHS, LHSType, RHSType,
+                                        IsCompAssign);
+
+  // Now handle "real" floating types (i.e. float, double, long double).
+  if (LHSType->isRealFloatingType() || RHSType->isRealFloatingType())
+    return handleFloatConversion(*this, LHS, RHS, LHSType, RHSType,
+                                 IsCompAssign);
+
+  // Handle GCC complex int extension.
+  if (LHSType->isComplexIntegerType() || RHSType->isComplexIntegerType())
+    return handleComplexIntConversion(*this, LHS, RHS, LHSType, RHSType,
+                                      IsCompAssign);
+
+  // Finally, we have two differing integer types.
+  return handleIntegerConversion(*this, LHS, RHS, LHSType, RHSType,
+                                 IsCompAssign);
+}
+
+//===----------------------------------------------------------------------===//
+//  Semantic Analysis for various Expression Types
+//===----------------------------------------------------------------------===//
+
+
+ExprResult
+Sema::ActOnGenericSelectionExpr(SourceLocation KeyLoc,
+                                SourceLocation DefaultLoc,
+                                SourceLocation RParenLoc,
+                                Expr *ControllingExpr,
+                                MultiTypeArg ArgTypes,
+                                MultiExprArg ArgExprs) {
+  unsigned NumAssocs = ArgTypes.size();
+  assert(NumAssocs == ArgExprs.size());
+
+  ParsedType *ParsedTypes = ArgTypes.release();
+  Expr **Exprs = ArgExprs.release();
+
+  TypeSourceInfo **Types = new TypeSourceInfo*[NumAssocs];
+  for (unsigned i = 0; i < NumAssocs; ++i) {
+    if (ParsedTypes[i])
+      (void) GetTypeFromParser(ParsedTypes[i], &Types[i]);
+    else
+      Types[i] = 0;
+  }
+
+  ExprResult ER = CreateGenericSelectionExpr(KeyLoc, DefaultLoc, RParenLoc,
+                                             ControllingExpr, Types, Exprs,
+                                             NumAssocs);
+  delete [] Types;
+  return ER;
+}
+
+ExprResult
+Sema::CreateGenericSelectionExpr(SourceLocation KeyLoc,
+                                 SourceLocation DefaultLoc,
+                                 SourceLocation RParenLoc,
+                                 Expr *ControllingExpr,
+                                 TypeSourceInfo **Types,
+                                 Expr **Exprs,
+                                 unsigned NumAssocs) {
+  bool TypeErrorFound = false,
+       IsResultDependent = ControllingExpr->isTypeDependent(),
+       ContainsUnexpandedParameterPack
+         = ControllingExpr->containsUnexpandedParameterPack();
+
+  for (unsigned i = 0; i < NumAssocs; ++i) {
+    if (Exprs[i]->containsUnexpandedParameterPack())
+      ContainsUnexpandedParameterPack = true;
+
+    if (Types[i]) {
+      if (Types[i]->getType()->containsUnexpandedParameterPack())
+        ContainsUnexpandedParameterPack = true;
+
+      if (Types[i]->getType()->isDependentType()) {
+        IsResultDependent = true;
+      } else {
+        // C11 6.5.1.1p2 "The type name in a generic association shall specify a
+        // complete object type other than a variably modified type."
+        unsigned D = 0;
+        if (Types[i]->getType()->isIncompleteType())
+          D = diag::err_assoc_type_incomplete;
+        else if (!Types[i]->getType()->isObjectType())
+          D = diag::err_assoc_type_nonobject;
+        else if (Types[i]->getType()->isVariablyModifiedType())
+          D = diag::err_assoc_type_variably_modified;
+
+        if (D != 0) {
+          Diag(Types[i]->getTypeLoc().getBeginLoc(), D)
+            << Types[i]->getTypeLoc().getSourceRange()
+            << Types[i]->getType();
+          TypeErrorFound = true;
+        }
+
+        // C11 6.5.1.1p2 "No two generic associations in the same generic
+        // selection shall specify compatible types."
+        for (unsigned j = i+1; j < NumAssocs; ++j)
+          if (Types[j] && !Types[j]->getType()->isDependentType() &&
+              Context.typesAreCompatible(Types[i]->getType(),
+                                         Types[j]->getType())) {
+            Diag(Types[j]->getTypeLoc().getBeginLoc(),
+                 diag::err_assoc_compatible_types)
+              << Types[j]->getTypeLoc().getSourceRange()
+              << Types[j]->getType()
+              << Types[i]->getType();
+            Diag(Types[i]->getTypeLoc().getBeginLoc(),
+                 diag::note_compat_assoc)
+              << Types[i]->getTypeLoc().getSourceRange()
+              << Types[i]->getType();
+            TypeErrorFound = true;
+          }
+      }
+    }
+  }
+  if (TypeErrorFound)
+    return ExprError();
+
+  // If we determined that the generic selection is result-dependent, don't
+  // try to compute the result expression.
+  if (IsResultDependent)
+    return Owned(new (Context) GenericSelectionExpr(
+                   Context, KeyLoc, ControllingExpr,
+                   Types, Exprs, NumAssocs, DefaultLoc,
+                   RParenLoc, ContainsUnexpandedParameterPack));
+
+  SmallVector<unsigned, 1> CompatIndices;
+  unsigned DefaultIndex = -1U;
+  for (unsigned i = 0; i < NumAssocs; ++i) {
+    if (!Types[i])
+      DefaultIndex = i;
+    else if (Context.typesAreCompatible(ControllingExpr->getType(),
+                                        Types[i]->getType()))
+      CompatIndices.push_back(i);
+  }
+
+  // C11 6.5.1.1p2 "The controlling expression of a generic selection shall have
+  // type compatible with at most one of the types named in its generic
+  // association list."
+  if (CompatIndices.size() > 1) {
+    // We strip parens here because the controlling expression is typically
+    // parenthesized in macro definitions.
+    ControllingExpr = ControllingExpr->IgnoreParens();
+    Diag(ControllingExpr->getLocStart(), diag::err_generic_sel_multi_match)
+      << ControllingExpr->getSourceRange() << ControllingExpr->getType()
+      << (unsigned) CompatIndices.size();
+    for (SmallVector<unsigned, 1>::iterator I = CompatIndices.begin(),
+         E = CompatIndices.end(); I != E; ++I) {
+      Diag(Types[*I]->getTypeLoc().getBeginLoc(),
+           diag::note_compat_assoc)
+        << Types[*I]->getTypeLoc().getSourceRange()
+        << Types[*I]->getType();
+    }
+    return ExprError();
+  }
+
+  // C11 6.5.1.1p2 "If a generic selection has no default generic association,
+  // its controlling expression shall have type compatible with exactly one of
+  // the types named in its generic association list."
+  if (DefaultIndex == -1U && CompatIndices.size() == 0) {
+    // We strip parens here because the controlling expression is typically
+    // parenthesized in macro definitions.
+    ControllingExpr = ControllingExpr->IgnoreParens();
+    Diag(ControllingExpr->getLocStart(), diag::err_generic_sel_no_match)
+      << ControllingExpr->getSourceRange() << ControllingExpr->getType();
+    return ExprError();
+  }
+
+  // C11 6.5.1.1p3 "If a generic selection has a generic association with a
+  // type name that is compatible with the type of the controlling expression,
+  // then the result expression of the generic selection is the expression
+  // in that generic association. Otherwise, the result expression of the
+  // generic selection is the expression in the default generic association."
+  unsigned ResultIndex =
+    CompatIndices.size() ? CompatIndices[0] : DefaultIndex;
+
+  return Owned(new (Context) GenericSelectionExpr(
+                 Context, KeyLoc, ControllingExpr,
+                 Types, Exprs, NumAssocs, DefaultLoc,
+                 RParenLoc, ContainsUnexpandedParameterPack,
+                 ResultIndex));
+}
+
+/// getUDSuffixLoc - Create a SourceLocation for a ud-suffix, given the
+/// location of the token and the offset of the ud-suffix within it.
+static SourceLocation getUDSuffixLoc(Sema &S, SourceLocation TokLoc,
+                                     unsigned Offset) {
+  return Lexer::AdvanceToTokenCharacter(TokLoc, Offset, S.getSourceManager(),
+                                        S.getLangOpts());
+}
+
+/// BuildCookedLiteralOperatorCall - A user-defined literal was found. Look up
+/// the corresponding cooked (non-raw) literal operator, and build a call to it.
+static ExprResult BuildCookedLiteralOperatorCall(Sema &S, Scope *Scope,
+                                                 IdentifierInfo *UDSuffix,
+                                                 SourceLocation UDSuffixLoc,
+                                                 ArrayRef<Expr*> Args,
+                                                 SourceLocation LitEndLoc) {
+  assert(Args.size() <= 2 && "too many arguments for literal operator");
+
+  QualType ArgTy[2];
+  for (unsigned ArgIdx = 0; ArgIdx != Args.size(); ++ArgIdx) {
+    ArgTy[ArgIdx] = Args[ArgIdx]->getType();
+    if (ArgTy[ArgIdx]->isArrayType())
+      ArgTy[ArgIdx] = S.Context.getArrayDecayedType(ArgTy[ArgIdx]);
+  }
+
+  DeclarationName OpName =
+    S.Context.DeclarationNames.getCXXLiteralOperatorName(UDSuffix);
+  DeclarationNameInfo OpNameInfo(OpName, UDSuffixLoc);
+  OpNameInfo.setCXXLiteralOperatorNameLoc(UDSuffixLoc);
+
+  LookupResult R(S, OpName, UDSuffixLoc, Sema::LookupOrdinaryName);
+  if (S.LookupLiteralOperator(Scope, R, llvm::makeArrayRef(ArgTy, Args.size()),
+                              /*AllowRawAndTemplate*/false) == Sema::LOLR_Error)
+    return ExprError();
+
+  return S.BuildLiteralOperatorCall(R, OpNameInfo, Args, LitEndLoc);
+}
+
+/// ActOnStringLiteral - The specified tokens were lexed as pasted string
+/// fragments (e.g. "foo" "bar" L"baz").  The result string has to handle string
+/// concatenation ([C99 5.1.1.2, translation phase #6]), so it may come from
+/// multiple tokens.  However, the common case is that StringToks points to one
+/// string.
+///
+ExprResult
+Sema::ActOnStringLiteral(const Token *StringToks, unsigned NumStringToks,
+                         Scope *UDLScope) {
+  assert(NumStringToks && "Must have at least one string!");
+
+  StringLiteralParser Literal(StringToks, NumStringToks, PP);
+  if (Literal.hadError)
+    return ExprError();
+
+  SmallVector<SourceLocation, 4> StringTokLocs;
+  for (unsigned i = 0; i != NumStringToks; ++i)
+    StringTokLocs.push_back(StringToks[i].getLocation());
+
+  QualType StrTy = Context.CharTy;
+  if (Literal.isWide())
+    StrTy = Context.getWCharType();
+  else if (Literal.isUTF16())
+    StrTy = Context.Char16Ty;
+  else if (Literal.isUTF32())
+    StrTy = Context.Char32Ty;
+  else if (Literal.isPascal())
+    StrTy = Context.UnsignedCharTy;
+
+  StringLiteral::StringKind Kind = StringLiteral::Ascii;
+  if (Literal.isWide())
+    Kind = StringLiteral::Wide;
+  else if (Literal.isUTF8())
+    Kind = StringLiteral::UTF8;
+  else if (Literal.isUTF16())
+    Kind = StringLiteral::UTF16;
+  else if (Literal.isUTF32())
+    Kind = StringLiteral::UTF32;
+
+  // A C++ string literal has a const-qualified element type (C++ 2.13.4p1).
+  if (getLangOpts().CPlusPlus || getLangOpts().ConstStrings)
+    StrTy.addConst();
+
+  // Get an array type for the string, according to C99 6.4.5.  This includes
+  // the nul terminator character as well as the string length for pascal
+  // strings.
+  StrTy = Context.getConstantArrayType(StrTy,
+                                 llvm::APInt(32, Literal.GetNumStringChars()+1),
+                                       ArrayType::Normal, 0);
+
+  // Pass &StringTokLocs[0], StringTokLocs.size() to factory!
+  StringLiteral *Lit = StringLiteral::Create(Context, Literal.GetString(),
+                                             Kind, Literal.Pascal, StrTy,
+                                             &StringTokLocs[0],
+                                             StringTokLocs.size());
+  if (Literal.getUDSuffix().empty())
+    return Owned(Lit);
+
+  // We're building a user-defined literal.
+  IdentifierInfo *UDSuffix = &Context.Idents.get(Literal.getUDSuffix());
+  SourceLocation UDSuffixLoc =
+    getUDSuffixLoc(*this, StringTokLocs[Literal.getUDSuffixToken()],
+                   Literal.getUDSuffixOffset());
+
+  // Make sure we're allowed user-defined literals here.
+  if (!UDLScope)
+    return ExprError(Diag(UDSuffixLoc, diag::err_invalid_string_udl));
+
+  // C++11 [lex.ext]p5: The literal L is treated as a call of the form
+  //   operator "" X (str, len)
+  QualType SizeType = Context.getSizeType();
+  llvm::APInt Len(Context.getIntWidth(SizeType), Literal.GetNumStringChars());
+  IntegerLiteral *LenArg = IntegerLiteral::Create(Context, Len, SizeType,
+                                                  StringTokLocs[0]);
+  Expr *Args[] = { Lit, LenArg };
+  return BuildCookedLiteralOperatorCall(*this, UDLScope, UDSuffix, UDSuffixLoc,
+                                        Args, StringTokLocs.back());
+}
+
+ExprResult
+Sema::BuildDeclRefExpr(ValueDecl *D, QualType Ty, ExprValueKind VK,
+                       SourceLocation Loc,
+                       const CXXScopeSpec *SS) {
+  DeclarationNameInfo NameInfo(D->getDeclName(), Loc);
+  return BuildDeclRefExpr(D, Ty, VK, NameInfo, SS);
+}
+
+/// BuildDeclRefExpr - Build an expression that references a
+/// declaration that does not require a closure capture.
+ExprResult
+Sema::BuildDeclRefExpr(ValueDecl *D, QualType Ty, ExprValueKind VK,
+                       const DeclarationNameInfo &NameInfo,
+                       const CXXScopeSpec *SS) {
+  if (getLangOpts().CUDA)
+    if (const FunctionDecl *Caller = dyn_cast<FunctionDecl>(CurContext))
+      if (const FunctionDecl *Callee = dyn_cast<FunctionDecl>(D)) {
+        CUDAFunctionTarget CallerTarget = IdentifyCUDATarget(Caller),
+                           CalleeTarget = IdentifyCUDATarget(Callee);
+        if (CheckCUDATarget(CallerTarget, CalleeTarget)) {
+          Diag(NameInfo.getLoc(), diag::err_ref_bad_target)
+            << CalleeTarget << D->getIdentifier() << CallerTarget;
+          Diag(D->getLocation(), diag::note_previous_decl)
+            << D->getIdentifier();
+          return ExprError();
+        }
+      }
+
+  bool refersToEnclosingScope =
+    (CurContext != D->getDeclContext() &&
+     D->getDeclContext()->isFunctionOrMethod());
+
+  DeclRefExpr *E = DeclRefExpr::Create(Context,
+                                       SS ? SS->getWithLocInContext(Context)
+                                              : NestedNameSpecifierLoc(),
+                                       SourceLocation(),
+                                       D, refersToEnclosingScope,
+                                       NameInfo, Ty, VK);
+
+  MarkDeclRefReferenced(E);
+
+  // Just in case we're building an illegal pointer-to-member.
+  FieldDecl *FD = dyn_cast<FieldDecl>(D);
+  if (FD && FD->isBitField())
+    E->setObjectKind(OK_BitField);
+
+  return Owned(E);
+}
+
+/// Decomposes the given name into a DeclarationNameInfo, its location, and
+/// possibly a list of template arguments.
+///
+/// If this produces template arguments, it is permitted to call
+/// DecomposeTemplateName.
+///
+/// This actually loses a lot of source location information for
+/// non-standard name kinds; we should consider preserving that in
+/// some way.
+void
+Sema::DecomposeUnqualifiedId(const UnqualifiedId &Id,
+                             TemplateArgumentListInfo &Buffer,
+                             DeclarationNameInfo &NameInfo,
+                             const TemplateArgumentListInfo *&TemplateArgs) {
+  if (Id.getKind() == UnqualifiedId::IK_TemplateId) {
+    Buffer.setLAngleLoc(Id.TemplateId->LAngleLoc);
+    Buffer.setRAngleLoc(Id.TemplateId->RAngleLoc);
+
+    ASTTemplateArgsPtr TemplateArgsPtr(*this,
+                                       Id.TemplateId->getTemplateArgs(),
+                                       Id.TemplateId->NumArgs);
+    translateTemplateArguments(TemplateArgsPtr, Buffer);
+    TemplateArgsPtr.release();
+
+    TemplateName TName = Id.TemplateId->Template.get();
+    SourceLocation TNameLoc = Id.TemplateId->TemplateNameLoc;
+    NameInfo = Context.getNameForTemplate(TName, TNameLoc);
+    TemplateArgs = &Buffer;
+  } else {
+    NameInfo = GetNameFromUnqualifiedId(Id);
+    TemplateArgs = 0;
+  }
+}
+
+/// Diagnose an empty lookup.
+///
+/// \return false if new lookup candidates were found
+bool Sema::DiagnoseEmptyLookup(Scope *S, CXXScopeSpec &SS, LookupResult &R,
+                               CorrectionCandidateCallback &CCC,
+                               TemplateArgumentListInfo *ExplicitTemplateArgs,
+                               llvm::ArrayRef<Expr *> Args) {
+  DeclarationName Name = R.getLookupName();
+
+  unsigned diagnostic = diag::err_undeclared_var_use;
+  unsigned diagnostic_suggest = diag::err_undeclared_var_use_suggest;
+  if (Name.getNameKind() == DeclarationName::CXXOperatorName ||
+      Name.getNameKind() == DeclarationName::CXXLiteralOperatorName ||
+      Name.getNameKind() == DeclarationName::CXXConversionFunctionName) {
+    diagnostic = diag::err_undeclared_use;
+    diagnostic_suggest = diag::err_undeclared_use_suggest;
+  }
+
+  // If the original lookup was an unqualified lookup, fake an
+  // unqualified lookup.  This is useful when (for example) the
+  // original lookup would not have found something because it was a
+  // dependent name.
+  DeclContext *DC = SS.isEmpty() ? CurContext : 0;
+  while (DC) {
+    if (isa<CXXRecordDecl>(DC)) {
+      LookupQualifiedName(R, DC);
+
+      if (!R.empty()) {
+        // Don't give errors about ambiguities in this lookup.
+        R.suppressDiagnostics();
+
+        // During a default argument instantiation the CurContext points
+        // to a CXXMethodDecl; but we can't apply a this-> fixit inside a
+        // function parameter list, hence add an explicit check.
+        bool isDefaultArgument = !ActiveTemplateInstantiations.empty() &&
+                              ActiveTemplateInstantiations.back().Kind ==
+            ActiveTemplateInstantiation::DefaultFunctionArgumentInstantiation;
+        CXXMethodDecl *CurMethod = dyn_cast<CXXMethodDecl>(CurContext);
+        bool isInstance = CurMethod &&
+                          CurMethod->isInstance() &&
+                          DC == CurMethod->getParent() && !isDefaultArgument;
+                          
+
+        // Give a code modification hint to insert 'this->'.
+        // TODO: fixit for inserting 'Base<T>::' in the other cases.
+        // Actually quite difficult!
+        if (isInstance) {
+          UnresolvedLookupExpr *ULE = cast<UnresolvedLookupExpr>(
+              CallsUndergoingInstantiation.back()->getCallee());
+          CXXMethodDecl *DepMethod = cast_or_null<CXXMethodDecl>(
+              CurMethod->getInstantiatedFromMemberFunction());
+          if (DepMethod) {
+            if (getLangOpts().MicrosoftMode)
+              diagnostic = diag::warn_found_via_dependent_bases_lookup;
+            Diag(R.getNameLoc(), diagnostic) << Name
+              << FixItHint::CreateInsertion(R.getNameLoc(), "this->");
+            QualType DepThisType = DepMethod->getThisType(Context);
+            CheckCXXThisCapture(R.getNameLoc());
+            CXXThisExpr *DepThis = new (Context) CXXThisExpr(
+                                       R.getNameLoc(), DepThisType, false);
+            TemplateArgumentListInfo TList;
+            if (ULE->hasExplicitTemplateArgs())
+              ULE->copyTemplateArgumentsInto(TList);
+            
+            CXXScopeSpec SS;
+            SS.Adopt(ULE->getQualifierLoc());
+            CXXDependentScopeMemberExpr *DepExpr =
+                CXXDependentScopeMemberExpr::Create(
+                    Context, DepThis, DepThisType, true, SourceLocation(),
+                    SS.getWithLocInContext(Context),
+                    ULE->getTemplateKeywordLoc(), 0,
+                    R.getLookupNameInfo(),
+                    ULE->hasExplicitTemplateArgs() ? &TList : 0);
+            CallsUndergoingInstantiation.back()->setCallee(DepExpr);
+          } else {
+            // FIXME: we should be able to handle this case too. It is correct
+            // to add this-> here. This is a workaround for PR7947.
+            Diag(R.getNameLoc(), diagnostic) << Name;
+          }
+        } else {
+          if (getLangOpts().MicrosoftMode)
+            diagnostic = diag::warn_found_via_dependent_bases_lookup;
+          Diag(R.getNameLoc(), diagnostic) << Name;
+        }
+
+        // Do we really want to note all of these?
+        for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I)
+          Diag((*I)->getLocation(), diag::note_dependent_var_use);
+
+        // Return true if we are inside a default argument instantiation
+        // and the found name refers to an instance member function, otherwise
+        // the function calling DiagnoseEmptyLookup will try to create an
+        // implicit member call and this is wrong for default argument.
+        if (isDefaultArgument && ((*R.begin())->isCXXInstanceMember())) {
+          Diag(R.getNameLoc(), diag::err_member_call_without_object);
+          return true;
+        }
+
+        // Tell the callee to try to recover.
+        return false;
+      }
+
+      R.clear();
+    }
+
+    // In Microsoft mode, if we are performing lookup from within a friend
+    // function definition declared at class scope then we must set
+    // DC to the lexical parent to be able to search into the parent
+    // class.
+    if (getLangOpts().MicrosoftMode && isa<FunctionDecl>(DC) &&
+        cast<FunctionDecl>(DC)->getFriendObjectKind() &&
+        DC->getLexicalParent()->isRecord())
+      DC = DC->getLexicalParent();
+    else
+      DC = DC->getParent();
+  }
+
+  // We didn't find anything, so try to correct for a typo.
+  TypoCorrection Corrected;
+  if (S && (Corrected = CorrectTypo(R.getLookupNameInfo(), R.getLookupKind(),
+                                    S, &SS, CCC))) {
+    std::string CorrectedStr(Corrected.getAsString(getLangOpts()));
+    std::string CorrectedQuotedStr(Corrected.getQuoted(getLangOpts()));
+    R.setLookupName(Corrected.getCorrection());
+
+    if (NamedDecl *ND = Corrected.getCorrectionDecl()) {
+      if (Corrected.isOverloaded()) {
+        OverloadCandidateSet OCS(R.getNameLoc());
+        OverloadCandidateSet::iterator Best;
+        for (TypoCorrection::decl_iterator CD = Corrected.begin(),
+                                        CDEnd = Corrected.end();
+             CD != CDEnd; ++CD) {
+          if (FunctionTemplateDecl *FTD =
+                   dyn_cast<FunctionTemplateDecl>(*CD))
+            AddTemplateOverloadCandidate(
+                FTD, DeclAccessPair::make(FTD, AS_none), ExplicitTemplateArgs,
+                Args, OCS);
+          else if (FunctionDecl *FD = dyn_cast<FunctionDecl>(*CD))
+            if (!ExplicitTemplateArgs || ExplicitTemplateArgs->size() == 0)
+              AddOverloadCandidate(FD, DeclAccessPair::make(FD, AS_none),
+                                   Args, OCS);
+        }
+        switch (OCS.BestViableFunction(*this, R.getNameLoc(), Best)) {
+          case OR_Success:
+            ND = Best->Function;
+            break;
+          default:
+            break;
+        }
+      }
+      R.addDecl(ND);
+      if (isa<ValueDecl>(ND) || isa<FunctionTemplateDecl>(ND)) {
+        if (SS.isEmpty())
+          Diag(R.getNameLoc(), diagnostic_suggest) << Name << CorrectedQuotedStr
+            << FixItHint::CreateReplacement(R.getNameLoc(), CorrectedStr);
+        else
+          Diag(R.getNameLoc(), diag::err_no_member_suggest)
+            << Name << computeDeclContext(SS, false) << CorrectedQuotedStr
+            << SS.getRange()
+            << FixItHint::CreateReplacement(R.getNameLoc(), CorrectedStr);
+        if (ND)
+          Diag(ND->getLocation(), diag::note_previous_decl)
+            << CorrectedQuotedStr;
+
+        // Tell the callee to try to recover.
+        return false;
+      }
+
+      if (isa<TypeDecl>(ND) || isa<ObjCInterfaceDecl>(ND)) {
+        // FIXME: If we ended up with a typo for a type name or
+        // Objective-C class name, we're in trouble because the parser
+        // is in the wrong place to recover. Suggest the typo
+        // correction, but don't make it a fix-it since we're not going
+        // to recover well anyway.
+        if (SS.isEmpty())
+          Diag(R.getNameLoc(), diagnostic_suggest)
+            << Name << CorrectedQuotedStr;
+        else
+          Diag(R.getNameLoc(), diag::err_no_member_suggest)
+            << Name << computeDeclContext(SS, false) << CorrectedQuotedStr
+            << SS.getRange();
+
+        // Don't try to recover; it won't work.
+        return true;
+      }
+    } else {
+      // FIXME: We found a keyword. Suggest it, but don't provide a fix-it
+      // because we aren't able to recover.
+      if (SS.isEmpty())
+        Diag(R.getNameLoc(), diagnostic_suggest) << Name << CorrectedQuotedStr;
+      else
+        Diag(R.getNameLoc(), diag::err_no_member_suggest)
+        << Name << computeDeclContext(SS, false) << CorrectedQuotedStr
+        << SS.getRange();
+      return true;
+    }
+  }
+  R.clear();
+
+  // Emit a special diagnostic for failed member lookups.
+  // FIXME: computing the declaration context might fail here (?)
+  if (!SS.isEmpty()) {
+    Diag(R.getNameLoc(), diag::err_no_member)
+      << Name << computeDeclContext(SS, false)
+      << SS.getRange();
+    return true;
+  }
+
+  // Give up, we can't recover.
+  Diag(R.getNameLoc(), diagnostic) << Name;
+  return true;
+}
+
+ExprResult Sema::ActOnIdExpression(Scope *S,
+                                   CXXScopeSpec &SS,
+                                   SourceLocation TemplateKWLoc,
+                                   UnqualifiedId &Id,
+                                   bool HasTrailingLParen,
+                                   bool IsAddressOfOperand,
+                                   CorrectionCandidateCallback *CCC) {
+  assert(!(IsAddressOfOperand && HasTrailingLParen) &&
+         "cannot be direct & operand and have a trailing lparen");
+
+  if (SS.isInvalid())
+    return ExprError();
+
+  TemplateArgumentListInfo TemplateArgsBuffer;
+
+  // Decompose the UnqualifiedId into the following data.
+  DeclarationNameInfo NameInfo;
+  const TemplateArgumentListInfo *TemplateArgs;
+  DecomposeUnqualifiedId(Id, TemplateArgsBuffer, NameInfo, TemplateArgs);
+
+  DeclarationName Name = NameInfo.getName();
+  IdentifierInfo *II = Name.getAsIdentifierInfo();
+  SourceLocation NameLoc = NameInfo.getLoc();
+
+  // C++ [temp.dep.expr]p3:
+  //   An id-expression is type-dependent if it contains:
+  //     -- an identifier that was declared with a dependent type,
+  //        (note: handled after lookup)
+  //     -- a template-id that is dependent,
+  //        (note: handled in BuildTemplateIdExpr)
+  //     -- a conversion-function-id that specifies a dependent type,
+  //     -- a nested-name-specifier that contains a class-name that
+  //        names a dependent type.
+  // Determine whether this is a member of an unknown specialization;
+  // we need to handle these differently.
+  bool DependentID = false;
+  if (Name.getNameKind() == DeclarationName::CXXConversionFunctionName &&
+      Name.getCXXNameType()->isDependentType()) {
+    DependentID = true;
+  } else if (SS.isSet()) {
+    if (DeclContext *DC = computeDeclContext(SS, false)) {
+      if (RequireCompleteDeclContext(SS, DC))
+        return ExprError();
+    } else {
+      DependentID = true;
+    }
+  }
+
+  if (DependentID)
+    return ActOnDependentIdExpression(SS, TemplateKWLoc, NameInfo,
+                                      IsAddressOfOperand, TemplateArgs);
+
+  // Perform the required lookup.
+  LookupResult R(*this, NameInfo, 
+                 (Id.getKind() == UnqualifiedId::IK_ImplicitSelfParam) 
+                  ? LookupObjCImplicitSelfParam : LookupOrdinaryName);
+  if (TemplateArgs) {
+    // Lookup the template name again to correctly establish the context in
+    // which it was found. This is really unfortunate as we already did the
+    // lookup to determine that it was a template name in the first place. If
+    // this becomes a performance hit, we can work harder to preserve those
+    // results until we get here but it's likely not worth it.
+    bool MemberOfUnknownSpecialization;
+    LookupTemplateName(R, S, SS, QualType(), /*EnteringContext=*/false,
+                       MemberOfUnknownSpecialization);
+    
+    if (MemberOfUnknownSpecialization ||
+        (R.getResultKind() == LookupResult::NotFoundInCurrentInstantiation))
+      return ActOnDependentIdExpression(SS, TemplateKWLoc, NameInfo,
+                                        IsAddressOfOperand, TemplateArgs);
+  } else {
+    bool IvarLookupFollowUp = II && !SS.isSet() && getCurMethodDecl();
+    LookupParsedName(R, S, &SS, !IvarLookupFollowUp);
+
+    // If the result might be in a dependent base class, this is a dependent 
+    // id-expression.
+    if (R.getResultKind() == LookupResult::NotFoundInCurrentInstantiation)
+      return ActOnDependentIdExpression(SS, TemplateKWLoc, NameInfo,
+                                        IsAddressOfOperand, TemplateArgs);
+
+    // If this reference is in an Objective-C method, then we need to do
+    // some special Objective-C lookup, too.
+    if (IvarLookupFollowUp) {
+      ExprResult E(LookupInObjCMethod(R, S, II, true));
+      if (E.isInvalid())
+        return ExprError();
+
+      if (Expr *Ex = E.takeAs<Expr>())
+        return Owned(Ex);
+    }
+  }
+
+  if (R.isAmbiguous())
+    return ExprError();
+
+  // Determine whether this name might be a candidate for
+  // argument-dependent lookup.
+  bool ADL = UseArgumentDependentLookup(SS, R, HasTrailingLParen);
+
+  if (R.empty() && !ADL) {
+    // Otherwise, this could be an implicitly declared function reference (legal
+    // in C90, extension in C99, forbidden in C++).
+    if (HasTrailingLParen && II && !getLangOpts().CPlusPlus) {
+      NamedDecl *D = ImplicitlyDefineFunction(NameLoc, *II, S);
+      if (D) R.addDecl(D);
+    }
+
+    // If this name wasn't predeclared and if this is not a function
+    // call, diagnose the problem.
+    if (R.empty()) {
+
+      // In Microsoft mode, if we are inside a template class member function
+      // and we can't resolve an identifier then assume the identifier is type
+      // dependent. The goal is to postpone name lookup to instantiation time 
+      // to be able to search into type dependent base classes.
+      if (getLangOpts().MicrosoftMode && CurContext->isDependentContext() &&
+          isa<CXXMethodDecl>(CurContext))
+        return ActOnDependentIdExpression(SS, TemplateKWLoc, NameInfo,
+                                          IsAddressOfOperand, TemplateArgs);
+
+      CorrectionCandidateCallback DefaultValidator;
+      if (DiagnoseEmptyLookup(S, SS, R, CCC ? *CCC : DefaultValidator))
+        return ExprError();
+
+      assert(!R.empty() &&
+             "DiagnoseEmptyLookup returned false but added no results");
+
+      // If we found an Objective-C instance variable, let
+      // LookupInObjCMethod build the appropriate expression to
+      // reference the ivar.
+      if (ObjCIvarDecl *Ivar = R.getAsSingle<ObjCIvarDecl>()) {
+        R.clear();
+        ExprResult E(LookupInObjCMethod(R, S, Ivar->getIdentifier()));
+        // In a hopelessly buggy code, Objective-C instance variable
+        // lookup fails and no expression will be built to reference it.
+        if (!E.isInvalid() && !E.get())
+          return ExprError();
+        return move(E);
+      }
+    }
+  }
+
+  // This is guaranteed from this point on.
+  assert(!R.empty() || ADL);
+
+  // Check whether this might be a C++ implicit instance member access.
+  // C++ [class.mfct.non-static]p3:
+  //   When an id-expression that is not part of a class member access
+  //   syntax and not used to form a pointer to member is used in the
+  //   body of a non-static member function of class X, if name lookup
+  //   resolves the name in the id-expression to a non-static non-type
+  //   member of some class C, the id-expression is transformed into a
+  //   class member access expression using (*this) as the
+  //   postfix-expression to the left of the . operator.
+  //
+  // But we don't actually need to do this for '&' operands if R
+  // resolved to a function or overloaded function set, because the
+  // expression is ill-formed if it actually works out to be a
+  // non-static member function:
+  //
+  // C++ [expr.ref]p4:
+  //   Otherwise, if E1.E2 refers to a non-static member function. . .
+  //   [t]he expression can be used only as the left-hand operand of a
+  //   member function call.
+  //
+  // There are other safeguards against such uses, but it's important
+  // to get this right here so that we don't end up making a
+  // spuriously dependent expression if we're inside a dependent
+  // instance method.
+  if (!R.empty() && (*R.begin())->isCXXClassMember()) {
+    bool MightBeImplicitMember;
+    if (!IsAddressOfOperand)
+      MightBeImplicitMember = true;
+    else if (!SS.isEmpty())
+      MightBeImplicitMember = false;
+    else if (R.isOverloadedResult())
+      MightBeImplicitMember = false;
+    else if (R.isUnresolvableResult())
+      MightBeImplicitMember = true;
+    else
+      MightBeImplicitMember = isa<FieldDecl>(R.getFoundDecl()) ||
+                              isa<IndirectFieldDecl>(R.getFoundDecl());
+
+    if (MightBeImplicitMember)
+      return BuildPossibleImplicitMemberExpr(SS, TemplateKWLoc,
+                                             R, TemplateArgs);
+  }
+
+  if (TemplateArgs || TemplateKWLoc.isValid())
+    return BuildTemplateIdExpr(SS, TemplateKWLoc, R, ADL, TemplateArgs);
+
+  return BuildDeclarationNameExpr(SS, R, ADL);
+}
+
+/// BuildQualifiedDeclarationNameExpr - Build a C++ qualified
+/// declaration name, generally during template instantiation.
+/// There's a large number of things which don't need to be done along
+/// this path.
+ExprResult
+Sema::BuildQualifiedDeclarationNameExpr(CXXScopeSpec &SS,
+                                        const DeclarationNameInfo &NameInfo) {
+  DeclContext *DC;
+  if (!(DC = computeDeclContext(SS, false)) || DC->isDependentContext())
+    return BuildDependentDeclRefExpr(SS, /*TemplateKWLoc=*/SourceLocation(),
+                                     NameInfo, /*TemplateArgs=*/0);
+
+  if (RequireCompleteDeclContext(SS, DC))
+    return ExprError();
+
+  LookupResult R(*this, NameInfo, LookupOrdinaryName);
+  LookupQualifiedName(R, DC);
+
+  if (R.isAmbiguous())
+    return ExprError();
+
+  if (R.empty()) {
+    Diag(NameInfo.getLoc(), diag::err_no_member)
+      << NameInfo.getName() << DC << SS.getRange();
+    return ExprError();
+  }
+
+  return BuildDeclarationNameExpr(SS, R, /*ADL*/ false);
+}
+
+/// LookupInObjCMethod - The parser has read a name in, and Sema has
+/// detected that we're currently inside an ObjC method.  Perform some
+/// additional lookup.
+///
+/// Ideally, most of this would be done by lookup, but there's
+/// actually quite a lot of extra work involved.
+///
+/// Returns a null sentinel to indicate trivial success.
+ExprResult
+Sema::LookupInObjCMethod(LookupResult &Lookup, Scope *S,
+                         IdentifierInfo *II, bool AllowBuiltinCreation) {
+  SourceLocation Loc = Lookup.getNameLoc();
+  ObjCMethodDecl *CurMethod = getCurMethodDecl();
+
+  // There are two cases to handle here.  1) scoped lookup could have failed,
+  // in which case we should look for an ivar.  2) scoped lookup could have
+  // found a decl, but that decl is outside the current instance method (i.e.
+  // a global variable).  In these two cases, we do a lookup for an ivar with
+  // this name, if the lookup sucedes, we replace it our current decl.
+
+  // If we're in a class method, we don't normally want to look for
+  // ivars.  But if we don't find anything else, and there's an
+  // ivar, that's an error.
+  bool IsClassMethod = CurMethod->isClassMethod();
+
+  bool LookForIvars;
+  if (Lookup.empty())
+    LookForIvars = true;
+  else if (IsClassMethod)
+    LookForIvars = false;
+  else
+    LookForIvars = (Lookup.isSingleResult() &&
+                    Lookup.getFoundDecl()->isDefinedOutsideFunctionOrMethod());
+  ObjCInterfaceDecl *IFace = 0;
+  if (LookForIvars) {
+    IFace = CurMethod->getClassInterface();
+    ObjCInterfaceDecl *ClassDeclared;
+    ObjCIvarDecl *IV = 0;
+    if (IFace && (IV = IFace->lookupInstanceVariable(II, ClassDeclared))) {
+      // Diagnose using an ivar in a class method.
+      if (IsClassMethod)
+        return ExprError(Diag(Loc, diag::error_ivar_use_in_class_method)
+                         << IV->getDeclName());
+
+      // If we're referencing an invalid decl, just return this as a silent
+      // error node.  The error diagnostic was already emitted on the decl.
+      if (IV->isInvalidDecl())
+        return ExprError();
+
+      // Check if referencing a field with __attribute__((deprecated)).
+      if (DiagnoseUseOfDecl(IV, Loc))
+        return ExprError();
+
+      // Diagnose the use of an ivar outside of the declaring class.
+      if (IV->getAccessControl() == ObjCIvarDecl::Private &&
+          !declaresSameEntity(ClassDeclared, IFace) &&
+          !getLangOpts().DebuggerSupport)
+        Diag(Loc, diag::error_private_ivar_access) << IV->getDeclName();
+
+      // FIXME: This should use a new expr for a direct reference, don't
+      // turn this into Self->ivar, just return a BareIVarExpr or something.
+      IdentifierInfo &II = Context.Idents.get("self");
+      UnqualifiedId SelfName;
+      SelfName.setIdentifier(&II, SourceLocation());
+      SelfName.setKind(UnqualifiedId::IK_ImplicitSelfParam);
+      CXXScopeSpec SelfScopeSpec;
+      SourceLocation TemplateKWLoc;
+      ExprResult SelfExpr = ActOnIdExpression(S, SelfScopeSpec, TemplateKWLoc,
+                                              SelfName, false, false);
+      if (SelfExpr.isInvalid())
+        return ExprError();
+
+      SelfExpr = DefaultLvalueConversion(SelfExpr.take());
+      if (SelfExpr.isInvalid())
+        return ExprError();
+
+      MarkAnyDeclReferenced(Loc, IV);
+      return Owned(new (Context)
+                   ObjCIvarRefExpr(IV, IV->getType(), Loc,
+                                   SelfExpr.take(), true, true));
+    }
+  } else if (CurMethod->isInstanceMethod()) {
+    // We should warn if a local variable hides an ivar.
+    if (ObjCInterfaceDecl *IFace = CurMethod->getClassInterface()) {
+      ObjCInterfaceDecl *ClassDeclared;
+      if (ObjCIvarDecl *IV = IFace->lookupInstanceVariable(II, ClassDeclared)) {
+        if (IV->getAccessControl() != ObjCIvarDecl::Private ||
+            declaresSameEntity(IFace, ClassDeclared))
+          Diag(Loc, diag::warn_ivar_use_hidden) << IV->getDeclName();
+      }
+    }
+  } else if (Lookup.isSingleResult() &&
+             Lookup.getFoundDecl()->isDefinedOutsideFunctionOrMethod()) {
+    // If accessing a stand-alone ivar in a class method, this is an error.
+    if (const ObjCIvarDecl *IV = dyn_cast<ObjCIvarDecl>(Lookup.getFoundDecl()))
+      return ExprError(Diag(Loc, diag::error_ivar_use_in_class_method)
+                       << IV->getDeclName());
+  }
+
+  if (Lookup.empty() && II && AllowBuiltinCreation) {
+    // FIXME. Consolidate this with similar code in LookupName.
+    if (unsigned BuiltinID = II->getBuiltinID()) {
+      if (!(getLangOpts().CPlusPlus &&
+            Context.BuiltinInfo.isPredefinedLibFunction(BuiltinID))) {
+        NamedDecl *D = LazilyCreateBuiltin((IdentifierInfo *)II, BuiltinID,
+                                           S, Lookup.isForRedeclaration(),
+                                           Lookup.getNameLoc());
+        if (D) Lookup.addDecl(D);
+      }
+    }
+  }
+  // Sentinel value saying that we didn't do anything special.
+  return Owned((Expr*) 0);
+}
+
+/// \brief Cast a base object to a member's actual type.
+///
+/// Logically this happens in three phases:
+///
+/// * First we cast from the base type to the naming class.
+///   The naming class is the class into which we were looking
+///   when we found the member;  it's the qualifier type if a
+///   qualifier was provided, and otherwise it's the base type.
+///
+/// * Next we cast from the naming class to the declaring class.
+///   If the member we found was brought into a class's scope by
+///   a using declaration, this is that class;  otherwise it's
+///   the class declaring the member.
+///
+/// * Finally we cast from the declaring class to the "true"
+///   declaring class of the member.  This conversion does not
+///   obey access control.
+ExprResult
+Sema::PerformObjectMemberConversion(Expr *From,
+                                    NestedNameSpecifier *Qualifier,
+                                    NamedDecl *FoundDecl,
+                                    NamedDecl *Member) {
+  CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(Member->getDeclContext());
+  if (!RD)
+    return Owned(From);
+
+  QualType DestRecordType;
+  QualType DestType;
+  QualType FromRecordType;
+  QualType FromType = From->getType();
+  bool PointerConversions = false;
+  if (isa<FieldDecl>(Member)) {
+    DestRecordType = Context.getCanonicalType(Context.getTypeDeclType(RD));
+
+    if (FromType->getAs<PointerType>()) {
+      DestType = Context.getPointerType(DestRecordType);
+      FromRecordType = FromType->getPointeeType();
+      PointerConversions = true;
+    } else {
+      DestType = DestRecordType;
+      FromRecordType = FromType;
+    }
+  } else if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(Member)) {
+    if (Method->isStatic())
+      return Owned(From);
+
+    DestType = Method->getThisType(Context);
+    DestRecordType = DestType->getPointeeType();
+
+    if (FromType->getAs<PointerType>()) {
+      FromRecordType = FromType->getPointeeType();
+      PointerConversions = true;
+    } else {
+      FromRecordType = FromType;
+      DestType = DestRecordType;
+    }
+  } else {
+    // No conversion necessary.
+    return Owned(From);
+  }
+
+  if (DestType->isDependentType() || FromType->isDependentType())
+    return Owned(From);
+
+  // If the unqualified types are the same, no conversion is necessary.
+  if (Context.hasSameUnqualifiedType(FromRecordType, DestRecordType))
+    return Owned(From);
+
+  SourceRange FromRange = From->getSourceRange();
+  SourceLocation FromLoc = FromRange.getBegin();
+
+  ExprValueKind VK = From->getValueKind();
+
+  // C++ [class.member.lookup]p8:
+  //   [...] Ambiguities can often be resolved by qualifying a name with its
+  //   class name.
+  //
+  // If the member was a qualified name and the qualified referred to a
+  // specific base subobject type, we'll cast to that intermediate type
+  // first and then to the object in which the member is declared. That allows
+  // one to resolve ambiguities in, e.g., a diamond-shaped hierarchy such as:
+  //
+  //   class Base { public: int x; };
+  //   class Derived1 : public Base { };
+  //   class Derived2 : public Base { };
+  //   class VeryDerived : public Derived1, public Derived2 { void f(); };
+  //
+  //   void VeryDerived::f() {
+  //     x = 17; // error: ambiguous base subobjects
+  //     Derived1::x = 17; // okay, pick the Base subobject of Derived1
+  //   }
+  if (Qualifier) {
+    QualType QType = QualType(Qualifier->getAsType(), 0);
+    assert(!QType.isNull() && "lookup done with dependent qualifier?");
+    assert(QType->isRecordType() && "lookup done with non-record type");
+
+    QualType QRecordType = QualType(QType->getAs<RecordType>(), 0);
+
+    // In C++98, the qualifier type doesn't actually have to be a base
+    // type of the object type, in which case we just ignore it.
+    // Otherwise build the appropriate casts.
+    if (IsDerivedFrom(FromRecordType, QRecordType)) {
+      CXXCastPath BasePath;
+      if (CheckDerivedToBaseConversion(FromRecordType, QRecordType,
+                                       FromLoc, FromRange, &BasePath))
+        return ExprError();
+
+      if (PointerConversions)
+        QType = Context.getPointerType(QType);
+      From = ImpCastExprToType(From, QType, CK_UncheckedDerivedToBase,
+                               VK, &BasePath).take();
+
+      FromType = QType;
+      FromRecordType = QRecordType;
+
+      // If the qualifier type was the same as the destination type,
+      // we're done.
+      if (Context.hasSameUnqualifiedType(FromRecordType, DestRecordType))
+        return Owned(From);
+    }
+  }
+
+  bool IgnoreAccess = false;
+
+  // If we actually found the member through a using declaration, cast
+  // down to the using declaration's type.
+  //
+  // Pointer equality is fine here because only one declaration of a
+  // class ever has member declarations.
+  if (FoundDecl->getDeclContext() != Member->getDeclContext()) {
+    assert(isa<UsingShadowDecl>(FoundDecl));
+    QualType URecordType = Context.getTypeDeclType(
+                           cast<CXXRecordDecl>(FoundDecl->getDeclContext()));
+
+    // We only need to do this if the naming-class to declaring-class
+    // conversion is non-trivial.
+    if (!Context.hasSameUnqualifiedType(FromRecordType, URecordType)) {
+      assert(IsDerivedFrom(FromRecordType, URecordType));
+      CXXCastPath BasePath;
+      if (CheckDerivedToBaseConversion(FromRecordType, URecordType,
+                                       FromLoc, FromRange, &BasePath))
+        return ExprError();
+
+      QualType UType = URecordType;
+      if (PointerConversions)
+        UType = Context.getPointerType(UType);
+      From = ImpCastExprToType(From, UType, CK_UncheckedDerivedToBase,
+                               VK, &BasePath).take();
+      FromType = UType;
+      FromRecordType = URecordType;
+    }
+
+    // We don't do access control for the conversion from the
+    // declaring class to the true declaring class.
+    IgnoreAccess = true;
+  }
+
+  CXXCastPath BasePath;
+  if (CheckDerivedToBaseConversion(FromRecordType, DestRecordType,
+                                   FromLoc, FromRange, &BasePath,
+                                   IgnoreAccess))
+    return ExprError();
+
+  return ImpCastExprToType(From, DestType, CK_UncheckedDerivedToBase,
+                           VK, &BasePath);
+}
+
+bool Sema::UseArgumentDependentLookup(const CXXScopeSpec &SS,
+                                      const LookupResult &R,
+                                      bool HasTrailingLParen) {
+  // Only when used directly as the postfix-expression of a call.
+  if (!HasTrailingLParen)
+    return false;
+
+  // Never if a scope specifier was provided.
+  if (SS.isSet())
+    return false;
+
+  // Only in C++ or ObjC++.
+  if (!getLangOpts().CPlusPlus)
+    return false;
+
+  // Turn off ADL when we find certain kinds of declarations during
+  // normal lookup:
+  for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I) {
+    NamedDecl *D = *I;
+
+    // C++0x [basic.lookup.argdep]p3:
+    //     -- a declaration of a class member
+    // Since using decls preserve this property, we check this on the
+    // original decl.
+    if (D->isCXXClassMember())
+      return false;
+
+    // C++0x [basic.lookup.argdep]p3:
+    //     -- a block-scope function declaration that is not a
+    //        using-declaration
+    // NOTE: we also trigger this for function templates (in fact, we
+    // don't check the decl type at all, since all other decl types
+    // turn off ADL anyway).
+    if (isa<UsingShadowDecl>(D))
+      D = cast<UsingShadowDecl>(D)->getTargetDecl();
+    else if (D->getDeclContext()->isFunctionOrMethod())
+      return false;
+
+    // C++0x [basic.lookup.argdep]p3:
+    //     -- a declaration that is neither a function or a function
+    //        template
+    // And also for builtin functions.
+    if (isa<FunctionDecl>(D)) {
+      FunctionDecl *FDecl = cast<FunctionDecl>(D);
+
+      // But also builtin functions.
+      if (FDecl->getBuiltinID() && FDecl->isImplicit())
+        return false;
+    } else if (!isa<FunctionTemplateDecl>(D))
+      return false;
+  }
+
+  return true;
+}
+
+
+/// Diagnoses obvious problems with the use of the given declaration
+/// as an expression.  This is only actually called for lookups that
+/// were not overloaded, and it doesn't promise that the declaration
+/// will in fact be used.
+static bool CheckDeclInExpr(Sema &S, SourceLocation Loc, NamedDecl *D) {
+  if (isa<TypedefNameDecl>(D)) {
+    S.Diag(Loc, diag::err_unexpected_typedef) << D->getDeclName();
+    return true;
+  }
+
+  if (isa<ObjCInterfaceDecl>(D)) {
+    S.Diag(Loc, diag::err_unexpected_interface) << D->getDeclName();
+    return true;
+  }
+
+  if (isa<NamespaceDecl>(D)) {
+    S.Diag(Loc, diag::err_unexpected_namespace) << D->getDeclName();
+    return true;
+  }
+
+  return false;
+}
+
+ExprResult
+Sema::BuildDeclarationNameExpr(const CXXScopeSpec &SS,
+                               LookupResult &R,
+                               bool NeedsADL) {
+  // If this is a single, fully-resolved result and we don't need ADL,
+  // just build an ordinary singleton decl ref.
+  if (!NeedsADL && R.isSingleResult() && !R.getAsSingle<FunctionTemplateDecl>())
+    return BuildDeclarationNameExpr(SS, R.getLookupNameInfo(),
+                                    R.getFoundDecl());
+
+  // We only need to check the declaration if there's exactly one
+  // result, because in the overloaded case the results can only be
+  // functions and function templates.
+  if (R.isSingleResult() &&
+      CheckDeclInExpr(*this, R.getNameLoc(), R.getFoundDecl()))
+    return ExprError();
+
+  // Otherwise, just build an unresolved lookup expression.  Suppress
+  // any lookup-related diagnostics; we'll hash these out later, when
+  // we've picked a target.
+  R.suppressDiagnostics();
+
+  UnresolvedLookupExpr *ULE
+    = UnresolvedLookupExpr::Create(Context, R.getNamingClass(),
+                                   SS.getWithLocInContext(Context),
+                                   R.getLookupNameInfo(),
+                                   NeedsADL, R.isOverloadedResult(),
+                                   R.begin(), R.end());
+
+  return Owned(ULE);
+}
+
+/// \brief Complete semantic analysis for a reference to the given declaration.
+ExprResult
+Sema::BuildDeclarationNameExpr(const CXXScopeSpec &SS,
+                               const DeclarationNameInfo &NameInfo,
+                               NamedDecl *D) {
+  assert(D && "Cannot refer to a NULL declaration");
+  assert(!isa<FunctionTemplateDecl>(D) &&
+         "Cannot refer unambiguously to a function template");
+
+  SourceLocation Loc = NameInfo.getLoc();
+  if (CheckDeclInExpr(*this, Loc, D))
+    return ExprError();
+
+  if (TemplateDecl *Template = dyn_cast<TemplateDecl>(D)) {
+    // Specifically diagnose references to class templates that are missing
+    // a template argument list.
+    Diag(Loc, diag::err_template_decl_ref)
+      << Template << SS.getRange();
+    Diag(Template->getLocation(), diag::note_template_decl_here);
+    return ExprError();
+  }
+
+  // Make sure that we're referring to a value.
+  ValueDecl *VD = dyn_cast<ValueDecl>(D);
+  if (!VD) {
+    Diag(Loc, diag::err_ref_non_value)
+      << D << SS.getRange();
+    Diag(D->getLocation(), diag::note_declared_at);
+    return ExprError();
+  }
+
+  // Check whether this declaration can be used. Note that we suppress
+  // this check when we're going to perform argument-dependent lookup
+  // on this function name, because this might not be the function
+  // that overload resolution actually selects.
+  if (DiagnoseUseOfDecl(VD, Loc))
+    return ExprError();
+
+  // Only create DeclRefExpr's for valid Decl's.
+  if (VD->isInvalidDecl())
+    return ExprError();
+
+  // Handle members of anonymous structs and unions.  If we got here,
+  // and the reference is to a class member indirect field, then this
+  // must be the subject of a pointer-to-member expression.
+  if (IndirectFieldDecl *indirectField = dyn_cast<IndirectFieldDecl>(VD))
+    if (!indirectField->isCXXClassMember())
+      return BuildAnonymousStructUnionMemberReference(SS, NameInfo.getLoc(),
+                                                      indirectField);
+
+  {
+    QualType type = VD->getType();
+    ExprValueKind valueKind = VK_RValue;
+
+    switch (D->getKind()) {
+    // Ignore all the non-ValueDecl kinds.
+#define ABSTRACT_DECL(kind)
+#define VALUE(type, base)
+#define DECL(type, base) \
+    case Decl::type:
+#include "clang/AST/DeclNodes.inc"
+      llvm_unreachable("invalid value decl kind");
+
+    // These shouldn't make it here.
+    case Decl::ObjCAtDefsField:
+    case Decl::ObjCIvar:
+      llvm_unreachable("forming non-member reference to ivar?");
+
+    // Enum constants are always r-values and never references.
+    // Unresolved using declarations are dependent.
+    case Decl::EnumConstant:
+    case Decl::UnresolvedUsingValue:
+      valueKind = VK_RValue;
+      break;
+
+    // Fields and indirect fields that got here must be for
+    // pointer-to-member expressions; we just call them l-values for
+    // internal consistency, because this subexpression doesn't really
+    // exist in the high-level semantics.
+    case Decl::Field:
+    case Decl::IndirectField:
+      assert(getLangOpts().CPlusPlus &&
+             "building reference to field in C?");
+
+      // These can't have reference type in well-formed programs, but
+      // for internal consistency we do this anyway.
+      type = type.getNonReferenceType();
+      valueKind = VK_LValue;
+      break;
+
+    // Non-type template parameters are either l-values or r-values
+    // depending on the type.
+    case Decl::NonTypeTemplateParm: {
+      if (const ReferenceType *reftype = type->getAs<ReferenceType>()) {
+        type = reftype->getPointeeType();
+        valueKind = VK_LValue; // even if the parameter is an r-value reference
+        break;
+      }
+
+      // For non-references, we need to strip qualifiers just in case
+      // the template parameter was declared as 'const int' or whatever.
+      valueKind = VK_RValue;
+      type = type.getUnqualifiedType();
+      break;
+    }
+
+    case Decl::Var:
+      // In C, "extern void blah;" is valid and is an r-value.
+      if (!getLangOpts().CPlusPlus &&
+          !type.hasQualifiers() &&
+          type->isVoidType()) {
+        valueKind = VK_RValue;
+        break;
+      }
+      // fallthrough
+
+    case Decl::ImplicitParam:
+    case Decl::ParmVar: {
+      // These are always l-values.
+      valueKind = VK_LValue;
+      type = type.getNonReferenceType();
+
+      // FIXME: Does the addition of const really only apply in
+      // potentially-evaluated contexts? Since the variable isn't actually
+      // captured in an unevaluated context, it seems that the answer is no.
+      if (ExprEvalContexts.back().Context != Sema::Unevaluated) {
+        QualType CapturedType = getCapturedDeclRefType(cast<VarDecl>(VD), Loc);
+        if (!CapturedType.isNull())
+          type = CapturedType;
+      }
+      
+      break;
+    }
+        
+    case Decl::Function: {
+      const FunctionType *fty = type->castAs<FunctionType>();
+
+      // If we're referring to a function with an __unknown_anytype
+      // result type, make the entire expression __unknown_anytype.
+      if (fty->getResultType() == Context.UnknownAnyTy) {
+        type = Context.UnknownAnyTy;
+        valueKind = VK_RValue;
+        break;
+      }
+
+      // Functions are l-values in C++.
+      if (getLangOpts().CPlusPlus) {
+        valueKind = VK_LValue;
+        break;
+      }
+      
+      // C99 DR 316 says that, if a function type comes from a
+      // function definition (without a prototype), that type is only
+      // used for checking compatibility. Therefore, when referencing
+      // the function, we pretend that we don't have the full function
+      // type.
+      if (!cast<FunctionDecl>(VD)->hasPrototype() &&
+          isa<FunctionProtoType>(fty))
+        type = Context.getFunctionNoProtoType(fty->getResultType(),
+                                              fty->getExtInfo());
+
+      // Functions are r-values in C.
+      valueKind = VK_RValue;
+      break;
+    }
+
+    case Decl::CXXMethod:
+      // If we're referring to a method with an __unknown_anytype
+      // result type, make the entire expression __unknown_anytype.
+      // This should only be possible with a type written directly.
+      if (const FunctionProtoType *proto
+            = dyn_cast<FunctionProtoType>(VD->getType()))
+        if (proto->getResultType() == Context.UnknownAnyTy) {
+          type = Context.UnknownAnyTy;
+          valueKind = VK_RValue;
+          break;
+        }
+
+      // C++ methods are l-values if static, r-values if non-static.
+      if (cast<CXXMethodDecl>(VD)->isStatic()) {
+        valueKind = VK_LValue;
+        break;
+      }
+      // fallthrough
+
+    case Decl::CXXConversion:
+    case Decl::CXXDestructor:
+    case Decl::CXXConstructor:
+      valueKind = VK_RValue;
+      break;
+    }
+
+    return BuildDeclRefExpr(VD, type, valueKind, NameInfo, &SS);
+  }
+}
+
+ExprResult Sema::ActOnPredefinedExpr(SourceLocation Loc, tok::TokenKind Kind) {
+  PredefinedExpr::IdentType IT;
+
+  switch (Kind) {
+  default: llvm_unreachable("Unknown simple primary expr!");
+  case tok::kw___func__: IT = PredefinedExpr::Func; break; // [C99 6.4.2.2]
+  case tok::kw___FUNCTION__: IT = PredefinedExpr::Function; break;
+  case tok::kw___PRETTY_FUNCTION__: IT = PredefinedExpr::PrettyFunction; break;
+  }
+
+  // Pre-defined identifiers are of type char[x], where x is the length of the
+  // string.
+
+  Decl *currentDecl = getCurFunctionOrMethodDecl();
+  if (!currentDecl && getCurBlock())
+    currentDecl = getCurBlock()->TheDecl;
+  if (!currentDecl) {
+    Diag(Loc, diag::ext_predef_outside_function);
+    currentDecl = Context.getTranslationUnitDecl();
+  }
+
+  QualType ResTy;
+  if (cast<DeclContext>(currentDecl)->isDependentContext()) {
+    ResTy = Context.DependentTy;
+  } else {
+    unsigned Length = PredefinedExpr::ComputeName(IT, currentDecl).length();
+
+    llvm::APInt LengthI(32, Length + 1);
+    ResTy = Context.CharTy.withConst();
+    ResTy = Context.getConstantArrayType(ResTy, LengthI, ArrayType::Normal, 0);
+  }
+  return Owned(new (Context) PredefinedExpr(Loc, ResTy, IT));
+}
+
+ExprResult Sema::ActOnCharacterConstant(const Token &Tok, Scope *UDLScope) {
+  SmallString<16> CharBuffer;
+  bool Invalid = false;
+  StringRef ThisTok = PP.getSpelling(Tok, CharBuffer, &Invalid);
+  if (Invalid)
+    return ExprError();
+
+  CharLiteralParser Literal(ThisTok.begin(), ThisTok.end(), Tok.getLocation(),
+                            PP, Tok.getKind());
+  if (Literal.hadError())
+    return ExprError();
+
+  QualType Ty;
+  if (Literal.isWide())
+    Ty = Context.WCharTy; // L'x' -> wchar_t in C and C++.
+  else if (Literal.isUTF16())
+    Ty = Context.Char16Ty; // u'x' -> char16_t in C11 and C++11.
+  else if (Literal.isUTF32())
+    Ty = Context.Char32Ty; // U'x' -> char32_t in C11 and C++11.
+  else if (!getLangOpts().CPlusPlus || Literal.isMultiChar())
+    Ty = Context.IntTy;   // 'x' -> int in C, 'wxyz' -> int in C++.
+  else
+    Ty = Context.CharTy;  // 'x' -> char in C++
+
+  CharacterLiteral::CharacterKind Kind = CharacterLiteral::Ascii;
+  if (Literal.isWide())
+    Kind = CharacterLiteral::Wide;
+  else if (Literal.isUTF16())
+    Kind = CharacterLiteral::UTF16;
+  else if (Literal.isUTF32())
+    Kind = CharacterLiteral::UTF32;
+
+  Expr *Lit = new (Context) CharacterLiteral(Literal.getValue(), Kind, Ty,
+                                             Tok.getLocation());
+
+  if (Literal.getUDSuffix().empty())
+    return Owned(Lit);
+
+  // We're building a user-defined literal.
+  IdentifierInfo *UDSuffix = &Context.Idents.get(Literal.getUDSuffix());
+  SourceLocation UDSuffixLoc =
+    getUDSuffixLoc(*this, Tok.getLocation(), Literal.getUDSuffixOffset());
+
+  // Make sure we're allowed user-defined literals here.
+  if (!UDLScope)
+    return ExprError(Diag(UDSuffixLoc, diag::err_invalid_character_udl));
+
+  // C++11 [lex.ext]p6: The literal L is treated as a call of the form
+  //   operator "" X (ch)
+  return BuildCookedLiteralOperatorCall(*this, UDLScope, UDSuffix, UDSuffixLoc,
+                                        llvm::makeArrayRef(&Lit, 1),
+                                        Tok.getLocation());
+}
+
+ExprResult Sema::ActOnIntegerConstant(SourceLocation Loc, uint64_t Val) {
+  unsigned IntSize = Context.getTargetInfo().getIntWidth();
+  return Owned(IntegerLiteral::Create(Context, llvm::APInt(IntSize, Val),
+                                      Context.IntTy, Loc));
+}
+
+static Expr *BuildFloatingLiteral(Sema &S, NumericLiteralParser &Literal,
+                                  QualType Ty, SourceLocation Loc) {
+  const llvm::fltSemantics &Format = S.Context.getFloatTypeSemantics(Ty);
+
+  using llvm::APFloat;
+  APFloat Val(Format);
+
+  APFloat::opStatus result = Literal.GetFloatValue(Val);
+
+  // Overflow is always an error, but underflow is only an error if
+  // we underflowed to zero (APFloat reports denormals as underflow).
+  if ((result & APFloat::opOverflow) ||
+      ((result & APFloat::opUnderflow) && Val.isZero())) {
+    unsigned diagnostic;
+    SmallString<20> buffer;
+    if (result & APFloat::opOverflow) {
+      diagnostic = diag::warn_float_overflow;
+      APFloat::getLargest(Format).toString(buffer);
+    } else {
+      diagnostic = diag::warn_float_underflow;
+      APFloat::getSmallest(Format).toString(buffer);
+    }
+
+    S.Diag(Loc, diagnostic)
+      << Ty
+      << StringRef(buffer.data(), buffer.size());
+  }
+
+  bool isExact = (result == APFloat::opOK);
+  return FloatingLiteral::Create(S.Context, Val, isExact, Ty, Loc);
+}
+
+ExprResult Sema::ActOnNumericConstant(const Token &Tok, Scope *UDLScope) {
+  // Fast path for a single digit (which is quite common).  A single digit
+  // cannot have a trigraph, escaped newline, radix prefix, or suffix.
+  if (Tok.getLength() == 1) {
+    const char Val = PP.getSpellingOfSingleCharacterNumericConstant(Tok);
+    return ActOnIntegerConstant(Tok.getLocation(), Val-'0');
+  }
+
+  SmallString<512> IntegerBuffer;
+  // Add padding so that NumericLiteralParser can overread by one character.
+  IntegerBuffer.resize(Tok.getLength()+1);
+  const char *ThisTokBegin = &IntegerBuffer[0];
+
+  // Get the spelling of the token, which eliminates trigraphs, etc.
+  bool Invalid = false;
+  unsigned ActualLength = PP.getSpelling(Tok, ThisTokBegin, &Invalid);
+  if (Invalid)
+    return ExprError();
+
+  NumericLiteralParser Literal(ThisTokBegin, ThisTokBegin+ActualLength,
+                               Tok.getLocation(), PP);
+  if (Literal.hadError)
+    return ExprError();
+
+  if (Literal.hasUDSuffix()) {
+    // We're building a user-defined literal.
+    IdentifierInfo *UDSuffix = &Context.Idents.get(Literal.getUDSuffix());
+    SourceLocation UDSuffixLoc =
+      getUDSuffixLoc(*this, Tok.getLocation(), Literal.getUDSuffixOffset());
+
+    // Make sure we're allowed user-defined literals here.
+    if (!UDLScope)
+      return ExprError(Diag(UDSuffixLoc, diag::err_invalid_numeric_udl));
+
+    QualType CookedTy;
+    if (Literal.isFloatingLiteral()) {
+      // C++11 [lex.ext]p4: If S contains a literal operator with parameter type
+      // long double, the literal is treated as a call of the form
+      //   operator "" X (f L)
+      CookedTy = Context.LongDoubleTy;
+    } else {
+      // C++11 [lex.ext]p3: If S contains a literal operator with parameter type
+      // unsigned long long, the literal is treated as a call of the form
+      //   operator "" X (n ULL)
+      CookedTy = Context.UnsignedLongLongTy;
+    }
+
+    DeclarationName OpName =
+      Context.DeclarationNames.getCXXLiteralOperatorName(UDSuffix);
+    DeclarationNameInfo OpNameInfo(OpName, UDSuffixLoc);
+    OpNameInfo.setCXXLiteralOperatorNameLoc(UDSuffixLoc);
+
+    // Perform literal operator lookup to determine if we're building a raw
+    // literal or a cooked one.
+    LookupResult R(*this, OpName, UDSuffixLoc, LookupOrdinaryName);
+    switch (LookupLiteralOperator(UDLScope, R, llvm::makeArrayRef(&CookedTy, 1),
+                                  /*AllowRawAndTemplate*/true)) {
+    case LOLR_Error:
+      return ExprError();
+
+    case LOLR_Cooked: {
+      Expr *Lit;
+      if (Literal.isFloatingLiteral()) {
+        Lit = BuildFloatingLiteral(*this, Literal, CookedTy, Tok.getLocation());
+      } else {
+        llvm::APInt ResultVal(Context.getTargetInfo().getLongLongWidth(), 0);
+        if (Literal.GetIntegerValue(ResultVal))
+          Diag(Tok.getLocation(), diag::warn_integer_too_large);
+        Lit = IntegerLiteral::Create(Context, ResultVal, CookedTy,
+                                     Tok.getLocation());
+      }
+      return BuildLiteralOperatorCall(R, OpNameInfo,
+                                      llvm::makeArrayRef(&Lit, 1),
+                                      Tok.getLocation());
+    }
+
+    case LOLR_Raw: {
+      // C++11 [lit.ext]p3, p4: If S contains a raw literal operator, the
+      // literal is treated as a call of the form
+      //   operator "" X ("n")
+      SourceLocation TokLoc = Tok.getLocation();
+      unsigned Length = Literal.getUDSuffixOffset();
+      QualType StrTy = Context.getConstantArrayType(
+          Context.CharTy, llvm::APInt(32, Length + 1),
+          ArrayType::Normal, 0);
+      Expr *Lit = StringLiteral::Create(
+          Context, StringRef(ThisTokBegin, Length), StringLiteral::Ascii,
+          /*Pascal*/false, StrTy, &TokLoc, 1);
+      return BuildLiteralOperatorCall(R, OpNameInfo,
+                                      llvm::makeArrayRef(&Lit, 1), TokLoc);
+    }
+
+    case LOLR_Template:
+      // C++11 [lit.ext]p3, p4: Otherwise (S contains a literal operator
+      // template), L is treated as a call fo the form
+      //   operator "" X <'c1', 'c2', ... 'ck'>()
+      // where n is the source character sequence c1 c2 ... ck.
+      TemplateArgumentListInfo ExplicitArgs;
+      unsigned CharBits = Context.getIntWidth(Context.CharTy);
+      bool CharIsUnsigned = Context.CharTy->isUnsignedIntegerType();
+      llvm::APSInt Value(CharBits, CharIsUnsigned);
+      for (unsigned I = 0, N = Literal.getUDSuffixOffset(); I != N; ++I) {
+        Value = ThisTokBegin[I];
+        TemplateArgument Arg(Value, Context.CharTy);
+        TemplateArgumentLocInfo ArgInfo;
+        ExplicitArgs.addArgument(TemplateArgumentLoc(Arg, ArgInfo));
+      }
+      return BuildLiteralOperatorCall(R, OpNameInfo, ArrayRef<Expr*>(),
+                                      Tok.getLocation(), &ExplicitArgs);
+    }
+
+    llvm_unreachable("unexpected literal operator lookup result");
+  }
+
+  Expr *Res;
+
+  if (Literal.isFloatingLiteral()) {
+    QualType Ty;
+    if (Literal.isFloat)
+      Ty = Context.FloatTy;
+    else if (!Literal.isLong)
+      Ty = Context.DoubleTy;
+    else
+      Ty = Context.LongDoubleTy;
+
+    Res = BuildFloatingLiteral(*this, Literal, Ty, Tok.getLocation());
+
+    if (Ty == Context.DoubleTy) {
+      if (getLangOpts().SinglePrecisionConstants) {
+        Res = ImpCastExprToType(Res, Context.FloatTy, CK_FloatingCast).take();
+      } else if (getLangOpts().OpenCL && !getOpenCLOptions().cl_khr_fp64) {
+        Diag(Tok.getLocation(), diag::warn_double_const_requires_fp64);
+        Res = ImpCastExprToType(Res, Context.FloatTy, CK_FloatingCast).take();
+      }
+    }
+  } else if (!Literal.isIntegerLiteral()) {
+    return ExprError();
+  } else {
+    QualType Ty;
+
+    // long long is a C99 feature.
+    if (!getLangOpts().C99 && Literal.isLongLong)
+      Diag(Tok.getLocation(),
+           getLangOpts().CPlusPlus0x ?
+             diag::warn_cxx98_compat_longlong : diag::ext_longlong);
+
+    // Get the value in the widest-possible width.
+    llvm::APInt ResultVal(Context.getTargetInfo().getIntMaxTWidth(), 0);
+
+    if (Literal.GetIntegerValue(ResultVal)) {
+      // If this value didn't fit into uintmax_t, warn and force to ull.
+      Diag(Tok.getLocation(), diag::warn_integer_too_large);
+      Ty = Context.UnsignedLongLongTy;
+      assert(Context.getTypeSize(Ty) == ResultVal.getBitWidth() &&
+             "long long is not intmax_t?");
+    } else {
+      // If this value fits into a ULL, try to figure out what else it fits into
+      // according to the rules of C99 6.4.4.1p5.
+
+      // Octal, Hexadecimal, and integers with a U suffix are allowed to
+      // be an unsigned int.
+      bool AllowUnsigned = Literal.isUnsigned || Literal.getRadix() != 10;
+
+      // Check from smallest to largest, picking the smallest type we can.
+      unsigned Width = 0;
+      if (!Literal.isLong && !Literal.isLongLong) {
+        // Are int/unsigned possibilities?
+        unsigned IntSize = Context.getTargetInfo().getIntWidth();
+
+        // Does it fit in a unsigned int?
+        if (ResultVal.isIntN(IntSize)) {
+          // Does it fit in a signed int?
+          if (!Literal.isUnsigned && ResultVal[IntSize-1] == 0)
+            Ty = Context.IntTy;
+          else if (AllowUnsigned)
+            Ty = Context.UnsignedIntTy;
+          Width = IntSize;
+        }
+      }
+
+      // Are long/unsigned long possibilities?
+      if (Ty.isNull() && !Literal.isLongLong) {
+        unsigned LongSize = Context.getTargetInfo().getLongWidth();
+
+        // Does it fit in a unsigned long?
+        if (ResultVal.isIntN(LongSize)) {
+          // Does it fit in a signed long?
+          if (!Literal.isUnsigned && ResultVal[LongSize-1] == 0)
+            Ty = Context.LongTy;
+          else if (AllowUnsigned)
+            Ty = Context.UnsignedLongTy;
+          Width = LongSize;
+        }
+      }
+
+      // Finally, check long long if needed.
+      if (Ty.isNull()) {
+        unsigned LongLongSize = Context.getTargetInfo().getLongLongWidth();
+
+        // Does it fit in a unsigned long long?
+        if (ResultVal.isIntN(LongLongSize)) {
+          // Does it fit in a signed long long?
+          // To be compatible with MSVC, hex integer literals ending with the
+          // LL or i64 suffix are always signed in Microsoft mode.
+          if (!Literal.isUnsigned && (ResultVal[LongLongSize-1] == 0 ||
+              (getLangOpts().MicrosoftExt && Literal.isLongLong)))
+            Ty = Context.LongLongTy;
+          else if (AllowUnsigned)
+            Ty = Context.UnsignedLongLongTy;
+          Width = LongLongSize;
+        }
+      }
+
+      // If we still couldn't decide a type, we probably have something that
+      // does not fit in a signed long long, but has no U suffix.
+      if (Ty.isNull()) {
+        Diag(Tok.getLocation(), diag::warn_integer_too_large_for_signed);
+        Ty = Context.UnsignedLongLongTy;
+        Width = Context.getTargetInfo().getLongLongWidth();
+      }
+
+      if (ResultVal.getBitWidth() != Width)
+        ResultVal = ResultVal.trunc(Width);
+    }
+    Res = IntegerLiteral::Create(Context, ResultVal, Ty, Tok.getLocation());
+  }
+
+  // If this is an imaginary literal, create the ImaginaryLiteral wrapper.
+  if (Literal.isImaginary)
+    Res = new (Context) ImaginaryLiteral(Res,
+                                        Context.getComplexType(Res->getType()));
+
+  return Owned(Res);
+}
+
+ExprResult Sema::ActOnParenExpr(SourceLocation L, SourceLocation R, Expr *E) {
+  assert((E != 0) && "ActOnParenExpr() missing expr");
+  return Owned(new (Context) ParenExpr(L, R, E));
+}
+
+static bool CheckVecStepTraitOperandType(Sema &S, QualType T,
+                                         SourceLocation Loc,
+                                         SourceRange ArgRange) {
+  // [OpenCL 1.1 6.11.12] "The vec_step built-in function takes a built-in
+  // scalar or vector data type argument..."
+  // Every built-in scalar type (OpenCL 1.1 6.1.1) is either an arithmetic
+  // type (C99 6.2.5p18) or void.
+  if (!(T->isArithmeticType() || T->isVoidType() || T->isVectorType())) {
+    S.Diag(Loc, diag::err_vecstep_non_scalar_vector_type)
+      << T << ArgRange;
+    return true;
+  }
+
+  assert((T->isVoidType() || !T->isIncompleteType()) &&
+         "Scalar types should always be complete");
+  return false;
+}
+
+static bool CheckExtensionTraitOperandType(Sema &S, QualType T,
+                                           SourceLocation Loc,
+                                           SourceRange ArgRange,
+                                           UnaryExprOrTypeTrait TraitKind) {
+  // C99 6.5.3.4p1:
+  if (T->isFunctionType()) {
+    // alignof(function) is allowed as an extension.
+    if (TraitKind == UETT_SizeOf)
+      S.Diag(Loc, diag::ext_sizeof_function_type) << ArgRange;
+    return false;
+  }
+
+  // Allow sizeof(void)/alignof(void) as an extension.
+  if (T->isVoidType()) {
+    S.Diag(Loc, diag::ext_sizeof_void_type) << TraitKind << ArgRange;
+    return false;
+  }
+
+  return true;
+}
+
+static bool CheckObjCTraitOperandConstraints(Sema &S, QualType T,
+                                             SourceLocation Loc,
+                                             SourceRange ArgRange,
+                                             UnaryExprOrTypeTrait TraitKind) {
+  // Reject sizeof(interface) and sizeof(interface<proto>) in 64-bit mode.
+  if (S.LangOpts.ObjCNonFragileABI && T->isObjCObjectType()) {
+    S.Diag(Loc, diag::err_sizeof_nonfragile_interface)
+      << T << (TraitKind == UETT_SizeOf)
+      << ArgRange;
+    return true;
+  }
+
+  return false;
+}
+
+/// \brief Check the constrains on expression operands to unary type expression
+/// and type traits.
+///
+/// Completes any types necessary and validates the constraints on the operand
+/// expression. The logic mostly mirrors the type-based overload, but may modify
+/// the expression as it completes the type for that expression through template
+/// instantiation, etc.
+bool Sema::CheckUnaryExprOrTypeTraitOperand(Expr *E,
+                                            UnaryExprOrTypeTrait ExprKind) {
+  QualType ExprTy = E->getType();
+
+  // C++ [expr.sizeof]p2: "When applied to a reference or a reference type,
+  //   the result is the size of the referenced type."
+  // C++ [expr.alignof]p3: "When alignof is applied to a reference type, the
+  //   result shall be the alignment of the referenced type."
+  if (const ReferenceType *Ref = ExprTy->getAs<ReferenceType>())
+    ExprTy = Ref->getPointeeType();
+
+  if (ExprKind == UETT_VecStep)
+    return CheckVecStepTraitOperandType(*this, ExprTy, E->getExprLoc(),
+                                        E->getSourceRange());
+
+  // Whitelist some types as extensions
+  if (!CheckExtensionTraitOperandType(*this, ExprTy, E->getExprLoc(),
+                                      E->getSourceRange(), ExprKind))
+    return false;
+
+  if (RequireCompleteExprType(E,
+                              PDiag(diag::err_sizeof_alignof_incomplete_type)
+                              << ExprKind << E->getSourceRange(),
+                              std::make_pair(SourceLocation(), PDiag(0))))
+    return true;
+
+  // Completeing the expression's type may have changed it.
+  ExprTy = E->getType();
+  if (const ReferenceType *Ref = ExprTy->getAs<ReferenceType>())
+    ExprTy = Ref->getPointeeType();
+
+  if (CheckObjCTraitOperandConstraints(*this, ExprTy, E->getExprLoc(),
+                                       E->getSourceRange(), ExprKind))
+    return true;
+
+  if (ExprKind == UETT_SizeOf) {
+    if (DeclRefExpr *DeclRef = dyn_cast<DeclRefExpr>(E->IgnoreParens())) {
+      if (ParmVarDecl *PVD = dyn_cast<ParmVarDecl>(DeclRef->getFoundDecl())) {
+        QualType OType = PVD->getOriginalType();
+        QualType Type = PVD->getType();
+        if (Type->isPointerType() && OType->isArrayType()) {
+          Diag(E->getExprLoc(), diag::warn_sizeof_array_param)
+            << Type << OType;
+          Diag(PVD->getLocation(), diag::note_declared_at);
+        }
+      }
+    }
+  }
+
+  return false;
+}
+
+/// \brief Check the constraints on operands to unary expression and type
+/// traits.
+///
+/// This will complete any types necessary, and validate the various constraints
+/// on those operands.
+///
+/// The UsualUnaryConversions() function is *not* called by this routine.
+/// C99 6.3.2.1p[2-4] all state:
+///   Except when it is the operand of the sizeof operator ...
+///
+/// C++ [expr.sizeof]p4
+///   The lvalue-to-rvalue, array-to-pointer, and function-to-pointer
+///   standard conversions are not applied to the operand of sizeof.
+///
+/// This policy is followed for all of the unary trait expressions.
+bool Sema::CheckUnaryExprOrTypeTraitOperand(QualType ExprType,
+                                            SourceLocation OpLoc,
+                                            SourceRange ExprRange,
+                                            UnaryExprOrTypeTrait ExprKind) {
+  if (ExprType->isDependentType())
+    return false;
+
+  // C++ [expr.sizeof]p2: "When applied to a reference or a reference type,
+  //   the result is the size of the referenced type."
+  // C++ [expr.alignof]p3: "When alignof is applied to a reference type, the
+  //   result shall be the alignment of the referenced type."
+  if (const ReferenceType *Ref = ExprType->getAs<ReferenceType>())
+    ExprType = Ref->getPointeeType();
+
+  if (ExprKind == UETT_VecStep)
+    return CheckVecStepTraitOperandType(*this, ExprType, OpLoc, ExprRange);
+
+  // Whitelist some types as extensions
+  if (!CheckExtensionTraitOperandType(*this, ExprType, OpLoc, ExprRange,
+                                      ExprKind))
+    return false;
+
+  if (RequireCompleteType(OpLoc, ExprType,
+                          PDiag(diag::err_sizeof_alignof_incomplete_type)
+                          << ExprKind << ExprRange))
+    return true;
+
+  if (CheckObjCTraitOperandConstraints(*this, ExprType, OpLoc, ExprRange,
+                                       ExprKind))
+    return true;
+
+  return false;
+}
+
+static bool CheckAlignOfExpr(Sema &S, Expr *E) {
+  E = E->IgnoreParens();
+
+  // alignof decl is always ok.
+  if (isa<DeclRefExpr>(E))
+    return false;
+
+  // Cannot know anything else if the expression is dependent.
+  if (E->isTypeDependent())
+    return false;
+
+  if (E->getBitField()) {
+    S.Diag(E->getExprLoc(), diag::err_sizeof_alignof_bitfield)
+       << 1 << E->getSourceRange();
+    return true;
+  }
+
+  // Alignment of a field access is always okay, so long as it isn't a
+  // bit-field.
+  if (MemberExpr *ME = dyn_cast<MemberExpr>(E))
+    if (isa<FieldDecl>(ME->getMemberDecl()))
+      return false;
+
+  return S.CheckUnaryExprOrTypeTraitOperand(E, UETT_AlignOf);
+}
+
+bool Sema::CheckVecStepExpr(Expr *E) {
+  E = E->IgnoreParens();
+
+  // Cannot know anything else if the expression is dependent.
+  if (E->isTypeDependent())
+    return false;
+
+  return CheckUnaryExprOrTypeTraitOperand(E, UETT_VecStep);
+}
+
+/// \brief Build a sizeof or alignof expression given a type operand.
+ExprResult
+Sema::CreateUnaryExprOrTypeTraitExpr(TypeSourceInfo *TInfo,
+                                     SourceLocation OpLoc,
+                                     UnaryExprOrTypeTrait ExprKind,
+                                     SourceRange R) {
+  if (!TInfo)
+    return ExprError();
+
+  QualType T = TInfo->getType();
+
+  if (!T->isDependentType() &&
+      CheckUnaryExprOrTypeTraitOperand(T, OpLoc, R, ExprKind))
+    return ExprError();
+
+  // C99 6.5.3.4p4: the type (an unsigned integer type) is size_t.
+  return Owned(new (Context) UnaryExprOrTypeTraitExpr(ExprKind, TInfo,
+                                                      Context.getSizeType(),
+                                                      OpLoc, R.getEnd()));
+}
+
+/// \brief Build a sizeof or alignof expression given an expression
+/// operand.
+ExprResult
+Sema::CreateUnaryExprOrTypeTraitExpr(Expr *E, SourceLocation OpLoc,
+                                     UnaryExprOrTypeTrait ExprKind) {
+  ExprResult PE = CheckPlaceholderExpr(E);
+  if (PE.isInvalid()) 
+    return ExprError();
+
+  E = PE.get();
+  
+  // Verify that the operand is valid.
+  bool isInvalid = false;
+  if (E->isTypeDependent()) {
+    // Delay type-checking for type-dependent expressions.
+  } else if (ExprKind == UETT_AlignOf) {
+    isInvalid = CheckAlignOfExpr(*this, E);
+  } else if (ExprKind == UETT_VecStep) {
+    isInvalid = CheckVecStepExpr(E);
+  } else if (E->getBitField()) {  // C99 6.5.3.4p1.
+    Diag(E->getExprLoc(), diag::err_sizeof_alignof_bitfield) << 0;
+    isInvalid = true;
+  } else {
+    isInvalid = CheckUnaryExprOrTypeTraitOperand(E, UETT_SizeOf);
+  }
+
+  if (isInvalid)
+    return ExprError();
+
+  if (ExprKind == UETT_SizeOf && E->getType()->isVariableArrayType()) {
+    PE = TranformToPotentiallyEvaluated(E);
+    if (PE.isInvalid()) return ExprError();
+    E = PE.take();
+  }
+
+  // C99 6.5.3.4p4: the type (an unsigned integer type) is size_t.
+  return Owned(new (Context) UnaryExprOrTypeTraitExpr(
+      ExprKind, E, Context.getSizeType(), OpLoc,
+      E->getSourceRange().getEnd()));
+}
+
+/// ActOnUnaryExprOrTypeTraitExpr - Handle @c sizeof(type) and @c sizeof @c
+/// expr and the same for @c alignof and @c __alignof
+/// Note that the ArgRange is invalid if isType is false.
+ExprResult
+Sema::ActOnUnaryExprOrTypeTraitExpr(SourceLocation OpLoc,
+                                    UnaryExprOrTypeTrait ExprKind, bool IsType,
+                                    void *TyOrEx, const SourceRange &ArgRange) {
+  // If error parsing type, ignore.
+  if (TyOrEx == 0) return ExprError();
+
+  if (IsType) {
+    TypeSourceInfo *TInfo;
+    (void) GetTypeFromParser(ParsedType::getFromOpaquePtr(TyOrEx), &TInfo);
+    return CreateUnaryExprOrTypeTraitExpr(TInfo, OpLoc, ExprKind, ArgRange);
+  }
+
+  Expr *ArgEx = (Expr *)TyOrEx;
+  ExprResult Result = CreateUnaryExprOrTypeTraitExpr(ArgEx, OpLoc, ExprKind);
+  return move(Result);
+}
+
+static QualType CheckRealImagOperand(Sema &S, ExprResult &V, SourceLocation Loc,
+                                     bool IsReal) {
+  if (V.get()->isTypeDependent())
+    return S.Context.DependentTy;
+
+  // _Real and _Imag are only l-values for normal l-values.
+  if (V.get()->getObjectKind() != OK_Ordinary) {
+    V = S.DefaultLvalueConversion(V.take());
+    if (V.isInvalid())
+      return QualType();
+  }
+
+  // These operators return the element type of a complex type.
+  if (const ComplexType *CT = V.get()->getType()->getAs<ComplexType>())
+    return CT->getElementType();
+
+  // Otherwise they pass through real integer and floating point types here.
+  if (V.get()->getType()->isArithmeticType())
+    return V.get()->getType();
+
+  // Test for placeholders.
+  ExprResult PR = S.CheckPlaceholderExpr(V.get());
+  if (PR.isInvalid()) return QualType();
+  if (PR.get() != V.get()) {
+    V = move(PR);
+    return CheckRealImagOperand(S, V, Loc, IsReal);
+  }
+
+  // Reject anything else.
+  S.Diag(Loc, diag::err_realimag_invalid_type) << V.get()->getType()
+    << (IsReal ? "__real" : "__imag");
+  return QualType();
+}
+
+
+
+ExprResult
+Sema::ActOnPostfixUnaryOp(Scope *S, SourceLocation OpLoc,
+                          tok::TokenKind Kind, Expr *Input) {
+  UnaryOperatorKind Opc;
+  switch (Kind) {
+  default: llvm_unreachable("Unknown unary op!");
+  case tok::plusplus:   Opc = UO_PostInc; break;
+  case tok::minusminus: Opc = UO_PostDec; break;
+  }
+
+  // Since this might is a postfix expression, get rid of ParenListExprs.
+  ExprResult Result = MaybeConvertParenListExprToParenExpr(S, Input);
+  if (Result.isInvalid()) return ExprError();
+  Input = Result.take();
+
+  return BuildUnaryOp(S, OpLoc, Opc, Input);
+}
+
+ExprResult
+Sema::ActOnArraySubscriptExpr(Scope *S, Expr *Base, SourceLocation LLoc,
+                              Expr *Idx, SourceLocation RLoc) {
+  // Since this might be a postfix expression, get rid of ParenListExprs.
+  ExprResult Result = MaybeConvertParenListExprToParenExpr(S, Base);
+  if (Result.isInvalid()) return ExprError();
+  Base = Result.take();
+
+  Expr *LHSExp = Base, *RHSExp = Idx;
+
+  if (getLangOpts().CPlusPlus &&
+      (LHSExp->isTypeDependent() || RHSExp->isTypeDependent())) {
+    return Owned(new (Context) ArraySubscriptExpr(LHSExp, RHSExp,
+                                                  Context.DependentTy,
+                                                  VK_LValue, OK_Ordinary,
+                                                  RLoc));
+  }
+
+  if (getLangOpts().CPlusPlus &&
+      (LHSExp->getType()->isRecordType() ||
+       LHSExp->getType()->isEnumeralType() ||
+       RHSExp->getType()->isRecordType() ||
+       RHSExp->getType()->isEnumeralType()) &&
+      !LHSExp->getType()->isObjCObjectPointerType()) {
+    return CreateOverloadedArraySubscriptExpr(LLoc, RLoc, Base, Idx);
+  }
+
+  return CreateBuiltinArraySubscriptExpr(Base, LLoc, Idx, RLoc);
+}
+
+
+ExprResult
+Sema::CreateBuiltinArraySubscriptExpr(Expr *Base, SourceLocation LLoc,
+                                      Expr *Idx, SourceLocation RLoc) {
+  Expr *LHSExp = Base;
+  Expr *RHSExp = Idx;
+
+  // Perform default conversions.
+  if (!LHSExp->getType()->getAs<VectorType>()) {
+    ExprResult Result = DefaultFunctionArrayLvalueConversion(LHSExp);
+    if (Result.isInvalid())
+      return ExprError();
+    LHSExp = Result.take();
+  }
+  ExprResult Result = DefaultFunctionArrayLvalueConversion(RHSExp);
+  if (Result.isInvalid())
+    return ExprError();
+  RHSExp = Result.take();
+
+  QualType LHSTy = LHSExp->getType(), RHSTy = RHSExp->getType();
+  ExprValueKind VK = VK_LValue;
+  ExprObjectKind OK = OK_Ordinary;
+
+  // C99 6.5.2.1p2: the expression e1[e2] is by definition precisely equivalent
+  // to the expression *((e1)+(e2)). This means the array "Base" may actually be
+  // in the subscript position. As a result, we need to derive the array base
+  // and index from the expression types.
+  Expr *BaseExpr, *IndexExpr;
+  QualType ResultType;
+  if (LHSTy->isDependentType() || RHSTy->isDependentType()) {
+    BaseExpr = LHSExp;
+    IndexExpr = RHSExp;
+    ResultType = Context.DependentTy;
+  } else if (const PointerType *PTy = LHSTy->getAs<PointerType>()) {
+    BaseExpr = LHSExp;
+    IndexExpr = RHSExp;
+    ResultType = PTy->getPointeeType();
+  } else if (const ObjCObjectPointerType *PTy =
+             LHSTy->getAs<ObjCObjectPointerType>()) {
+    BaseExpr = LHSExp;
+    IndexExpr = RHSExp;
+    Result = BuildObjCSubscriptExpression(RLoc, BaseExpr, IndexExpr, 0, 0);
+    if (!Result.isInvalid())
+      return Owned(Result.take());
+    ResultType = PTy->getPointeeType();
+  } else if (const PointerType *PTy = RHSTy->getAs<PointerType>()) {
+     // Handle the uncommon case of "123[Ptr]".
+    BaseExpr = RHSExp;
+    IndexExpr = LHSExp;
+    ResultType = PTy->getPointeeType();
+  } else if (const ObjCObjectPointerType *PTy =
+               RHSTy->getAs<ObjCObjectPointerType>()) {
+     // Handle the uncommon case of "123[Ptr]".
+    BaseExpr = RHSExp;
+    IndexExpr = LHSExp;
+    ResultType = PTy->getPointeeType();
+  } else if (const VectorType *VTy = LHSTy->getAs<VectorType>()) {
+    BaseExpr = LHSExp;    // vectors: V[123]
+    IndexExpr = RHSExp;
+    VK = LHSExp->getValueKind();
+    if (VK != VK_RValue)
+      OK = OK_VectorComponent;
+
+    // FIXME: need to deal with const...
+    ResultType = VTy->getElementType();
+  } else if (LHSTy->isArrayType()) {
+    // If we see an array that wasn't promoted by
+    // DefaultFunctionArrayLvalueConversion, it must be an array that
+    // wasn't promoted because of the C90 rule that doesn't
+    // allow promoting non-lvalue arrays.  Warn, then
+    // force the promotion here.
+    Diag(LHSExp->getLocStart(), diag::ext_subscript_non_lvalue) <<
+        LHSExp->getSourceRange();
+    LHSExp = ImpCastExprToType(LHSExp, Context.getArrayDecayedType(LHSTy),
+                               CK_ArrayToPointerDecay).take();
+    LHSTy = LHSExp->getType();
+
+    BaseExpr = LHSExp;
+    IndexExpr = RHSExp;
+    ResultType = LHSTy->getAs<PointerType>()->getPointeeType();
+  } else if (RHSTy->isArrayType()) {
+    // Same as previous, except for 123[f().a] case
+    Diag(RHSExp->getLocStart(), diag::ext_subscript_non_lvalue) <<
+        RHSExp->getSourceRange();
+    RHSExp = ImpCastExprToType(RHSExp, Context.getArrayDecayedType(RHSTy),
+                               CK_ArrayToPointerDecay).take();
+    RHSTy = RHSExp->getType();
+
+    BaseExpr = RHSExp;
+    IndexExpr = LHSExp;
+    ResultType = RHSTy->getAs<PointerType>()->getPointeeType();
+  } else {
+    return ExprError(Diag(LLoc, diag::err_typecheck_subscript_value)
+       << LHSExp->getSourceRange() << RHSExp->getSourceRange());
+  }
+  // C99 6.5.2.1p1
+  if (!IndexExpr->getType()->isIntegerType() && !IndexExpr->isTypeDependent())
+    return ExprError(Diag(LLoc, diag::err_typecheck_subscript_not_integer)
+                     << IndexExpr->getSourceRange());
+
+  if ((IndexExpr->getType()->isSpecificBuiltinType(BuiltinType::Char_S) ||
+       IndexExpr->getType()->isSpecificBuiltinType(BuiltinType::Char_U))
+         && !IndexExpr->isTypeDependent())
+    Diag(LLoc, diag::warn_subscript_is_char) << IndexExpr->getSourceRange();
+
+  // C99 6.5.2.1p1: "shall have type "pointer to *object* type". Similarly,
+  // C++ [expr.sub]p1: The type "T" shall be a completely-defined object
+  // type. Note that Functions are not objects, and that (in C99 parlance)
+  // incomplete types are not object types.
+  if (ResultType->isFunctionType()) {
+    Diag(BaseExpr->getLocStart(), diag::err_subscript_function_type)
+      << ResultType << BaseExpr->getSourceRange();
+    return ExprError();
+  }
+
+  if (ResultType->isVoidType() && !getLangOpts().CPlusPlus) {
+    // GNU extension: subscripting on pointer to void
+    Diag(LLoc, diag::ext_gnu_subscript_void_type)
+      << BaseExpr->getSourceRange();
+
+    // C forbids expressions of unqualified void type from being l-values.
+    // See IsCForbiddenLValueType.
+    if (!ResultType.hasQualifiers()) VK = VK_RValue;
+  } else if (!ResultType->isDependentType() &&
+      RequireCompleteType(LLoc, ResultType,
+                          PDiag(diag::err_subscript_incomplete_type)
+                            << BaseExpr->getSourceRange()))
+    return ExprError();
+
+  // Diagnose bad cases where we step over interface counts.
+  if (ResultType->isObjCObjectType() && LangOpts.ObjCNonFragileABI) {
+    Diag(LLoc, diag::err_subscript_nonfragile_interface)
+      << ResultType << BaseExpr->getSourceRange();
+    return ExprError();
+  }
+
+  assert(VK == VK_RValue || LangOpts.CPlusPlus ||
+         !ResultType.isCForbiddenLValueType());
+
+  return Owned(new (Context) ArraySubscriptExpr(LHSExp, RHSExp,
+                                                ResultType, VK, OK, RLoc));
+}
+
+ExprResult Sema::BuildCXXDefaultArgExpr(SourceLocation CallLoc,
+                                        FunctionDecl *FD,
+                                        ParmVarDecl *Param) {
+  if (Param->hasUnparsedDefaultArg()) {
+    Diag(CallLoc,
+         diag::err_use_of_default_argument_to_function_declared_later) <<
+      FD << cast<CXXRecordDecl>(FD->getDeclContext())->getDeclName();
+    Diag(UnparsedDefaultArgLocs[Param],
+         diag::note_default_argument_declared_here);
+    return ExprError();
+  }
+  
+  if (Param->hasUninstantiatedDefaultArg()) {
+    Expr *UninstExpr = Param->getUninstantiatedDefaultArg();
+
+    // Instantiate the expression.
+    MultiLevelTemplateArgumentList ArgList
+      = getTemplateInstantiationArgs(FD, 0, /*RelativeToPrimary=*/true);
+
+    std::pair<const TemplateArgument *, unsigned> Innermost
+      = ArgList.getInnermost();
+    InstantiatingTemplate Inst(*this, CallLoc, Param, Innermost.first,
+                               Innermost.second);
+
+    ExprResult Result;
+    {
+      // C++ [dcl.fct.default]p5:
+      //   The names in the [default argument] expression are bound, and
+      //   the semantic constraints are checked, at the point where the
+      //   default argument expression appears.
+      ContextRAII SavedContext(*this, FD);
+      LocalInstantiationScope Local(*this);
+      Result = SubstExpr(UninstExpr, ArgList);
+    }
+    if (Result.isInvalid())
+      return ExprError();
+
+    // Check the expression as an initializer for the parameter.
+    InitializedEntity Entity
+      = InitializedEntity::InitializeParameter(Context, Param);
+    InitializationKind Kind
+      = InitializationKind::CreateCopy(Param->getLocation(),
+             /*FIXME:EqualLoc*/UninstExpr->getLocStart());
+    Expr *ResultE = Result.takeAs<Expr>();
+
+    InitializationSequence InitSeq(*this, Entity, Kind, &ResultE, 1);
+    Result = InitSeq.Perform(*this, Entity, Kind,
+                             MultiExprArg(*this, &ResultE, 1));
+    if (Result.isInvalid())
+      return ExprError();
+
+    // Build the default argument expression.
+    return Owned(CXXDefaultArgExpr::Create(Context, CallLoc, Param,
+                                           Result.takeAs<Expr>()));
+  }
+
+  // If the default expression creates temporaries, we need to
+  // push them to the current stack of expression temporaries so they'll
+  // be properly destroyed.
+  // FIXME: We should really be rebuilding the default argument with new
+  // bound temporaries; see the comment in PR5810.
+  // We don't need to do that with block decls, though, because
+  // blocks in default argument expression can never capture anything.
+  if (isa<ExprWithCleanups>(Param->getInit())) {
+    // Set the "needs cleanups" bit regardless of whether there are
+    // any explicit objects.
+    ExprNeedsCleanups = true;
+
+    // Append all the objects to the cleanup list.  Right now, this
+    // should always be a no-op, because blocks in default argument
+    // expressions should never be able to capture anything.
+    assert(!cast<ExprWithCleanups>(Param->getInit())->getNumObjects() &&
+           "default argument expression has capturing blocks?");
+  }
+
+  // We already type-checked the argument, so we know it works. 
+  // Just mark all of the declarations in this potentially-evaluated expression
+  // as being "referenced".
+  MarkDeclarationsReferencedInExpr(Param->getDefaultArg(),
+                                   /*SkipLocalVariables=*/true);
+  return Owned(CXXDefaultArgExpr::Create(Context, CallLoc, Param));
+}
+
+/// ConvertArgumentsForCall - Converts the arguments specified in
+/// Args/NumArgs to the parameter types of the function FDecl with
+/// function prototype Proto. Call is the call expression itself, and
+/// Fn is the function expression. For a C++ member function, this
+/// routine does not attempt to convert the object argument. Returns
+/// true if the call is ill-formed.
+bool
+Sema::ConvertArgumentsForCall(CallExpr *Call, Expr *Fn,
+                              FunctionDecl *FDecl,
+                              const FunctionProtoType *Proto,
+                              Expr **Args, unsigned NumArgs,
+                              SourceLocation RParenLoc,
+                              bool IsExecConfig) {
+  // Bail out early if calling a builtin with custom typechecking.
+  // We don't need to do this in the 
+  if (FDecl)
+    if (unsigned ID = FDecl->getBuiltinID())
+      if (Context.BuiltinInfo.hasCustomTypechecking(ID))
+        return false;
+
+  // C99 6.5.2.2p7 - the arguments are implicitly converted, as if by
+  // assignment, to the types of the corresponding parameter, ...
+  unsigned NumArgsInProto = Proto->getNumArgs();
+  bool Invalid = false;
+  unsigned MinArgs = FDecl ? FDecl->getMinRequiredArguments() : NumArgsInProto;
+  unsigned FnKind = Fn->getType()->isBlockPointerType()
+                       ? 1 /* block */
+                       : (IsExecConfig ? 3 /* kernel function (exec config) */
+                                       : 0 /* function */);
+
+  // If too few arguments are available (and we don't have default
+  // arguments for the remaining parameters), don't make the call.
+  if (NumArgs < NumArgsInProto) {
+    if (NumArgs < MinArgs) {
+      Diag(RParenLoc, MinArgs == NumArgsInProto
+                        ? diag::err_typecheck_call_too_few_args
+                        : diag::err_typecheck_call_too_few_args_at_least)
+        << FnKind
+        << MinArgs << NumArgs << Fn->getSourceRange();
+
+      // Emit the location of the prototype.
+      if (FDecl && !FDecl->getBuiltinID() && !IsExecConfig)
+        Diag(FDecl->getLocStart(), diag::note_callee_decl)
+          << FDecl;
+
+      return true;
+    }
+    Call->setNumArgs(Context, NumArgsInProto);
+  }
+
+  // If too many are passed and not variadic, error on the extras and drop
+  // them.
+  if (NumArgs > NumArgsInProto) {
+    if (!Proto->isVariadic()) {
+      Diag(Args[NumArgsInProto]->getLocStart(),
+           MinArgs == NumArgsInProto
+             ? diag::err_typecheck_call_too_many_args
+             : diag::err_typecheck_call_too_many_args_at_most)
+        << FnKind
+        << NumArgsInProto << NumArgs << Fn->getSourceRange()
+        << SourceRange(Args[NumArgsInProto]->getLocStart(),
+                       Args[NumArgs-1]->getLocEnd());
+
+      // Emit the location of the prototype.
+      if (FDecl && !FDecl->getBuiltinID() && !IsExecConfig)
+        Diag(FDecl->getLocStart(), diag::note_callee_decl)
+          << FDecl;
+      
+      // This deletes the extra arguments.
+      Call->setNumArgs(Context, NumArgsInProto);
+      return true;
+    }
+  }
+  SmallVector<Expr *, 8> AllArgs;
+  VariadicCallType CallType =
+    Proto->isVariadic() ? VariadicFunction : VariadicDoesNotApply;
+  if (Fn->getType()->isBlockPointerType())
+    CallType = VariadicBlock; // Block
+  else if (isa<MemberExpr>(Fn))
+    CallType = VariadicMethod;
+  Invalid = GatherArgumentsForCall(Call->getLocStart(), FDecl,
+                                   Proto, 0, Args, NumArgs, AllArgs, CallType);
+  if (Invalid)
+    return true;
+  unsigned TotalNumArgs = AllArgs.size();
+  for (unsigned i = 0; i < TotalNumArgs; ++i)
+    Call->setArg(i, AllArgs[i]);
+
+  return false;
+}
+
+bool Sema::GatherArgumentsForCall(SourceLocation CallLoc,
+                                  FunctionDecl *FDecl,
+                                  const FunctionProtoType *Proto,
+                                  unsigned FirstProtoArg,
+                                  Expr **Args, unsigned NumArgs,
+                                  SmallVector<Expr *, 8> &AllArgs,
+                                  VariadicCallType CallType,
+                                  bool AllowExplicit) {
+  unsigned NumArgsInProto = Proto->getNumArgs();
+  unsigned NumArgsToCheck = NumArgs;
+  bool Invalid = false;
+  if (NumArgs != NumArgsInProto)
+    // Use default arguments for missing arguments
+    NumArgsToCheck = NumArgsInProto;
+  unsigned ArgIx = 0;
+  // Continue to check argument types (even if we have too few/many args).
+  for (unsigned i = FirstProtoArg; i != NumArgsToCheck; i++) {
+    QualType ProtoArgType = Proto->getArgType(i);
+
+    Expr *Arg;
+    ParmVarDecl *Param;
+    if (ArgIx < NumArgs) {
+      Arg = Args[ArgIx++];
+
+      if (RequireCompleteType(Arg->getLocStart(),
+                              ProtoArgType,
+                              PDiag(diag::err_call_incomplete_argument)
+                              << Arg->getSourceRange()))
+        return true;
+
+      // Pass the argument
+      Param = 0;
+      if (FDecl && i < FDecl->getNumParams())
+        Param = FDecl->getParamDecl(i);
+
+      // Strip the unbridged-cast placeholder expression off, if applicable.
+      if (Arg->getType() == Context.ARCUnbridgedCastTy &&
+          FDecl && FDecl->hasAttr<CFAuditedTransferAttr>() &&
+          (!Param || !Param->hasAttr<CFConsumedAttr>()))
+        Arg = stripARCUnbridgedCast(Arg);
+
+      InitializedEntity Entity =
+        Param? InitializedEntity::InitializeParameter(Context, Param)
+             : InitializedEntity::InitializeParameter(Context, ProtoArgType,
+                                                      Proto->isArgConsumed(i));
+      ExprResult ArgE = PerformCopyInitialization(Entity,
+                                                  SourceLocation(),
+                                                  Owned(Arg),
+                                                  /*TopLevelOfInitList=*/false,
+                                                  AllowExplicit);
+      if (ArgE.isInvalid())
+        return true;
+
+      Arg = ArgE.takeAs<Expr>();
+    } else {
+      Param = FDecl->getParamDecl(i);
+
+      ExprResult ArgExpr =
+        BuildCXXDefaultArgExpr(CallLoc, FDecl, Param);
+      if (ArgExpr.isInvalid())
+        return true;
+
+      Arg = ArgExpr.takeAs<Expr>();
+    }
+
+    // Check for array bounds violations for each argument to the call. This
+    // check only triggers warnings when the argument isn't a more complex Expr
+    // with its own checking, such as a BinaryOperator.
+    CheckArrayAccess(Arg);
+
+    // Check for violations of C99 static array rules (C99 6.7.5.3p7).
+    CheckStaticArrayArgument(CallLoc, Param, Arg);
+
+    AllArgs.push_back(Arg);
+  }
+
+  // If this is a variadic call, handle args passed through "...".
+  if (CallType != VariadicDoesNotApply) {
+
+    // Assume that extern "C" functions with variadic arguments that
+    // return __unknown_anytype aren't *really* variadic.
+    if (Proto->getResultType() == Context.UnknownAnyTy &&
+        FDecl && FDecl->isExternC()) {
+      for (unsigned i = ArgIx; i != NumArgs; ++i) {
+        ExprResult arg;
+        if (isa<ExplicitCastExpr>(Args[i]->IgnoreParens()))
+          arg = DefaultFunctionArrayLvalueConversion(Args[i]);
+        else
+          arg = DefaultVariadicArgumentPromotion(Args[i], CallType, FDecl);
+        Invalid |= arg.isInvalid();
+        AllArgs.push_back(arg.take());
+      }
+
+    // Otherwise do argument promotion, (C99 6.5.2.2p7).
+    } else {
+      for (unsigned i = ArgIx; i != NumArgs; ++i) {
+        ExprResult Arg = DefaultVariadicArgumentPromotion(Args[i], CallType,
+                                                          FDecl);
+        Invalid |= Arg.isInvalid();
+        AllArgs.push_back(Arg.take());
+      }
+    }
+
+    // Check for array bounds violations.
+    for (unsigned i = ArgIx; i != NumArgs; ++i)
+      CheckArrayAccess(Args[i]);
+  }
+  return Invalid;
+}
+
+static void DiagnoseCalleeStaticArrayParam(Sema &S, ParmVarDecl *PVD) {
+  TypeLoc TL = PVD->getTypeSourceInfo()->getTypeLoc();
+  if (ArrayTypeLoc *ATL = dyn_cast<ArrayTypeLoc>(&TL))
+    S.Diag(PVD->getLocation(), diag::note_callee_static_array)
+      << ATL->getLocalSourceRange();
+}
+
+/// CheckStaticArrayArgument - If the given argument corresponds to a static
+/// array parameter, check that it is non-null, and that if it is formed by
+/// array-to-pointer decay, the underlying array is sufficiently large.
+///
+/// C99 6.7.5.3p7: If the keyword static also appears within the [ and ] of the
+/// array type derivation, then for each call to the function, the value of the
+/// corresponding actual argument shall provide access to the first element of
+/// an array with at least as many elements as specified by the size expression.
+void
+Sema::CheckStaticArrayArgument(SourceLocation CallLoc,
+                               ParmVarDecl *Param,
+                               const Expr *ArgExpr) {
+  // Static array parameters are not supported in C++.
+  if (!Param || getLangOpts().CPlusPlus)
+    return;
+
+  QualType OrigTy = Param->getOriginalType();
+
+  const ArrayType *AT = Context.getAsArrayType(OrigTy);
+  if (!AT || AT->getSizeModifier() != ArrayType::Static)
+    return;
+
+  if (ArgExpr->isNullPointerConstant(Context,
+                                     Expr::NPC_NeverValueDependent)) {
+    Diag(CallLoc, diag::warn_null_arg) << ArgExpr->getSourceRange();
+    DiagnoseCalleeStaticArrayParam(*this, Param);
+    return;
+  }
+
+  const ConstantArrayType *CAT = dyn_cast<ConstantArrayType>(AT);
+  if (!CAT)
+    return;
+
+  const ConstantArrayType *ArgCAT =
+    Context.getAsConstantArrayType(ArgExpr->IgnoreParenImpCasts()->getType());
+  if (!ArgCAT)
+    return;
+
+  if (ArgCAT->getSize().ult(CAT->getSize())) {
+    Diag(CallLoc, diag::warn_static_array_too_small)
+      << ArgExpr->getSourceRange()
+      << (unsigned) ArgCAT->getSize().getZExtValue()
+      << (unsigned) CAT->getSize().getZExtValue();
+    DiagnoseCalleeStaticArrayParam(*this, Param);
+  }
+}
+
+/// Given a function expression of unknown-any type, try to rebuild it
+/// to have a function type.
+static ExprResult rebuildUnknownAnyFunction(Sema &S, Expr *fn);
+
+/// ActOnCallExpr - Handle a call to Fn with the specified array of arguments.
+/// This provides the location of the left/right parens and a list of comma
+/// locations.
+ExprResult
+Sema::ActOnCallExpr(Scope *S, Expr *Fn, SourceLocation LParenLoc,
+                    MultiExprArg ArgExprs, SourceLocation RParenLoc,
+                    Expr *ExecConfig, bool IsExecConfig) {
+  unsigned NumArgs = ArgExprs.size();
+
+  // Since this might be a postfix expression, get rid of ParenListExprs.
+  ExprResult Result = MaybeConvertParenListExprToParenExpr(S, Fn);
+  if (Result.isInvalid()) return ExprError();
+  Fn = Result.take();
+
+  Expr **Args = ArgExprs.release();
+
+  if (getLangOpts().CPlusPlus) {
+    // If this is a pseudo-destructor expression, build the call immediately.
+    if (isa<CXXPseudoDestructorExpr>(Fn)) {
+      if (NumArgs > 0) {
+        // Pseudo-destructor calls should not have any arguments.
+        Diag(Fn->getLocStart(), diag::err_pseudo_dtor_call_with_args)
+          << FixItHint::CreateRemoval(
+                                    SourceRange(Args[0]->getLocStart(),
+                                                Args[NumArgs-1]->getLocEnd()));
+      }
+
+      return Owned(new (Context) CallExpr(Context, Fn, 0, 0, Context.VoidTy,
+                                          VK_RValue, RParenLoc));
+    }
+
+    // Determine whether this is a dependent call inside a C++ template,
+    // in which case we won't do any semantic analysis now.
+    // FIXME: Will need to cache the results of name lookup (including ADL) in
+    // Fn.
+    bool Dependent = false;
+    if (Fn->isTypeDependent())
+      Dependent = true;
+    else if (Expr::hasAnyTypeDependentArguments(
+        llvm::makeArrayRef(Args, NumArgs)))
+      Dependent = true;
+
+    if (Dependent) {
+      if (ExecConfig) {
+        return Owned(new (Context) CUDAKernelCallExpr(
+            Context, Fn, cast<CallExpr>(ExecConfig), Args, NumArgs,
+            Context.DependentTy, VK_RValue, RParenLoc));
+      } else {
+        return Owned(new (Context) CallExpr(Context, Fn, Args, NumArgs,
+                                            Context.DependentTy, VK_RValue,
+                                            RParenLoc));
+      }
+    }
+
+    // Determine whether this is a call to an object (C++ [over.call.object]).
+    if (Fn->getType()->isRecordType())
+      return Owned(BuildCallToObjectOfClassType(S, Fn, LParenLoc, Args, NumArgs,
+                                                RParenLoc));
+
+    if (Fn->getType() == Context.UnknownAnyTy) {
+      ExprResult result = rebuildUnknownAnyFunction(*this, Fn);
+      if (result.isInvalid()) return ExprError();
+      Fn = result.take();
+    }
+
+    if (Fn->getType() == Context.BoundMemberTy) {
+      return BuildCallToMemberFunction(S, Fn, LParenLoc, Args, NumArgs,
+                                       RParenLoc);
+    }
+  }
+
+  // Check for overloaded calls.  This can happen even in C due to extensions.
+  if (Fn->getType() == Context.OverloadTy) {
+    OverloadExpr::FindResult find = OverloadExpr::find(Fn);
+
+    // We aren't supposed to apply this logic for if there's an '&' involved.
+    if (!find.HasFormOfMemberPointer) {
+      OverloadExpr *ovl = find.Expression;
+      if (isa<UnresolvedLookupExpr>(ovl)) {
+        UnresolvedLookupExpr *ULE = cast<UnresolvedLookupExpr>(ovl);
+        return BuildOverloadedCallExpr(S, Fn, ULE, LParenLoc, Args, NumArgs,
+                                       RParenLoc, ExecConfig);
+      } else {
+        return BuildCallToMemberFunction(S, Fn, LParenLoc, Args, NumArgs,
+                                         RParenLoc);
+      }
+    }
+  }
+
+  // If we're directly calling a function, get the appropriate declaration.
+  if (Fn->getType() == Context.UnknownAnyTy) {
+    ExprResult result = rebuildUnknownAnyFunction(*this, Fn);
+    if (result.isInvalid()) return ExprError();
+    Fn = result.take();
+  }
+
+  Expr *NakedFn = Fn->IgnoreParens();
+
+  NamedDecl *NDecl = 0;
+  if (UnaryOperator *UnOp = dyn_cast<UnaryOperator>(NakedFn))
+    if (UnOp->getOpcode() == UO_AddrOf)
+      NakedFn = UnOp->getSubExpr()->IgnoreParens();
+  
+  if (isa<DeclRefExpr>(NakedFn))
+    NDecl = cast<DeclRefExpr>(NakedFn)->getDecl();
+  else if (isa<MemberExpr>(NakedFn))
+    NDecl = cast<MemberExpr>(NakedFn)->getMemberDecl();
+
+  return BuildResolvedCallExpr(Fn, NDecl, LParenLoc, Args, NumArgs, RParenLoc,
+                               ExecConfig, IsExecConfig);
+}
+
+ExprResult
+Sema::ActOnCUDAExecConfigExpr(Scope *S, SourceLocation LLLLoc,
+                              MultiExprArg ExecConfig, SourceLocation GGGLoc) {
+  FunctionDecl *ConfigDecl = Context.getcudaConfigureCallDecl();
+  if (!ConfigDecl)
+    return ExprError(Diag(LLLLoc, diag::err_undeclared_var_use)
+                          << "cudaConfigureCall");
+  QualType ConfigQTy = ConfigDecl->getType();
+
+  DeclRefExpr *ConfigDR = new (Context) DeclRefExpr(
+      ConfigDecl, false, ConfigQTy, VK_LValue, LLLLoc);
+  MarkFunctionReferenced(LLLLoc, ConfigDecl);
+
+  return ActOnCallExpr(S, ConfigDR, LLLLoc, ExecConfig, GGGLoc, 0,
+                       /*IsExecConfig=*/true);
+}
+
+/// ActOnAsTypeExpr - create a new asType (bitcast) from the arguments.
+///
+/// __builtin_astype( value, dst type )
+///
+ExprResult Sema::ActOnAsTypeExpr(Expr *E, ParsedType ParsedDestTy,
+                                 SourceLocation BuiltinLoc,
+                                 SourceLocation RParenLoc) {
+  ExprValueKind VK = VK_RValue;
+  ExprObjectKind OK = OK_Ordinary;
+  QualType DstTy = GetTypeFromParser(ParsedDestTy);
+  QualType SrcTy = E->getType();
+  if (Context.getTypeSize(DstTy) != Context.getTypeSize(SrcTy))
+    return ExprError(Diag(BuiltinLoc,
+                          diag::err_invalid_astype_of_different_size)
+                     << DstTy
+                     << SrcTy
+                     << E->getSourceRange());
+  return Owned(new (Context) AsTypeExpr(E, DstTy, VK, OK, BuiltinLoc,
+               RParenLoc));
+}
+
+/// BuildResolvedCallExpr - Build a call to a resolved expression,
+/// i.e. an expression not of \p OverloadTy.  The expression should
+/// unary-convert to an expression of function-pointer or
+/// block-pointer type.
+///
+/// \param NDecl the declaration being called, if available
+ExprResult
+Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl,
+                            SourceLocation LParenLoc,
+                            Expr **Args, unsigned NumArgs,
+                            SourceLocation RParenLoc,
+                            Expr *Config, bool IsExecConfig) {
+  FunctionDecl *FDecl = dyn_cast_or_null<FunctionDecl>(NDecl);
+
+  // Promote the function operand.
+  ExprResult Result = UsualUnaryConversions(Fn);
+  if (Result.isInvalid())
+    return ExprError();
+  Fn = Result.take();
+
+  // Make the call expr early, before semantic checks.  This guarantees cleanup
+  // of arguments and function on error.
+  CallExpr *TheCall;
+  if (Config) {
+    TheCall = new (Context) CUDAKernelCallExpr(Context, Fn,
+                                               cast<CallExpr>(Config),
+                                               Args, NumArgs,
+                                               Context.BoolTy,
+                                               VK_RValue,
+                                               RParenLoc);
+  } else {
+    TheCall = new (Context) CallExpr(Context, Fn,
+                                     Args, NumArgs,
+                                     Context.BoolTy,
+                                     VK_RValue,
+                                     RParenLoc);
+  }
+
+  unsigned BuiltinID = (FDecl ? FDecl->getBuiltinID() : 0);
+
+  // Bail out early if calling a builtin with custom typechecking.
+  if (BuiltinID && Context.BuiltinInfo.hasCustomTypechecking(BuiltinID))
+    return CheckBuiltinFunctionCall(BuiltinID, TheCall);
+
+ retry:
+  const FunctionType *FuncT;
+  if (const PointerType *PT = Fn->getType()->getAs<PointerType>()) {
+    // C99 6.5.2.2p1 - "The expression that denotes the called function shall
+    // have type pointer to function".
+    FuncT = PT->getPointeeType()->getAs<FunctionType>();
+    if (FuncT == 0)
+      return ExprError(Diag(LParenLoc, diag::err_typecheck_call_not_function)
+                         << Fn->getType() << Fn->getSourceRange());
+  } else if (const BlockPointerType *BPT =
+               Fn->getType()->getAs<BlockPointerType>()) {
+    FuncT = BPT->getPointeeType()->castAs<FunctionType>();
+  } else {
+    // Handle calls to expressions of unknown-any type.
+    if (Fn->getType() == Context.UnknownAnyTy) {
+      ExprResult rewrite = rebuildUnknownAnyFunction(*this, Fn);
+      if (rewrite.isInvalid()) return ExprError();
+      Fn = rewrite.take();
+      TheCall->setCallee(Fn);
+      goto retry;
+    }
+
+    return ExprError(Diag(LParenLoc, diag::err_typecheck_call_not_function)
+      << Fn->getType() << Fn->getSourceRange());
+  }
+
+  if (getLangOpts().CUDA) {
+    if (Config) {
+      // CUDA: Kernel calls must be to global functions
+      if (FDecl && !FDecl->hasAttr<CUDAGlobalAttr>())
+        return ExprError(Diag(LParenLoc,diag::err_kern_call_not_global_function)
+            << FDecl->getName() << Fn->getSourceRange());
+
+      // CUDA: Kernel function must have 'void' return type
+      if (!FuncT->getResultType()->isVoidType())
+        return ExprError(Diag(LParenLoc, diag::err_kern_type_not_void_return)
+            << Fn->getType() << Fn->getSourceRange());
+    } else {
+      // CUDA: Calls to global functions must be configured
+      if (FDecl && FDecl->hasAttr<CUDAGlobalAttr>())
+        return ExprError(Diag(LParenLoc, diag::err_global_call_not_config)
+            << FDecl->getName() << Fn->getSourceRange());
+    }
+  }
+
+  // Check for a valid return type
+  if (CheckCallReturnType(FuncT->getResultType(),
+                          Fn->getLocStart(), TheCall,
+                          FDecl))
+    return ExprError();
+
+  // We know the result type of the call, set it.
+  TheCall->setType(FuncT->getCallResultType(Context));
+  TheCall->setValueKind(Expr::getValueKindForType(FuncT->getResultType()));
+
+  if (const FunctionProtoType *Proto = dyn_cast<FunctionProtoType>(FuncT)) {
+    if (ConvertArgumentsForCall(TheCall, Fn, FDecl, Proto, Args, NumArgs,
+                                RParenLoc, IsExecConfig))
+      return ExprError();
+  } else {
+    assert(isa<FunctionNoProtoType>(FuncT) && "Unknown FunctionType!");
+
+    if (FDecl) {
+      // Check if we have too few/too many template arguments, based
+      // on our knowledge of the function definition.
+      const FunctionDecl *Def = 0;
+      if (FDecl->hasBody(Def) && NumArgs != Def->param_size()) {
+        const FunctionProtoType *Proto 
+          = Def->getType()->getAs<FunctionProtoType>();
+        if (!Proto || !(Proto->isVariadic() && NumArgs >= Def->param_size()))
+          Diag(RParenLoc, diag::warn_call_wrong_number_of_arguments)
+            << (NumArgs > Def->param_size()) << FDecl << Fn->getSourceRange();
+      }
+      
+      // If the function we're calling isn't a function prototype, but we have
+      // a function prototype from a prior declaratiom, use that prototype.
+      if (!FDecl->hasPrototype())
+        Proto = FDecl->getType()->getAs<FunctionProtoType>();
+    }
+
+    // Promote the arguments (C99 6.5.2.2p6).
+    for (unsigned i = 0; i != NumArgs; i++) {
+      Expr *Arg = Args[i];
+
+      if (Proto && i < Proto->getNumArgs()) {
+        InitializedEntity Entity
+          = InitializedEntity::InitializeParameter(Context, 
+                                                   Proto->getArgType(i),
+                                                   Proto->isArgConsumed(i));
+        ExprResult ArgE = PerformCopyInitialization(Entity,
+                                                    SourceLocation(),
+                                                    Owned(Arg));
+        if (ArgE.isInvalid())
+          return true;
+        
+        Arg = ArgE.takeAs<Expr>();
+
+      } else {
+        ExprResult ArgE = DefaultArgumentPromotion(Arg);
+
+        if (ArgE.isInvalid())
+          return true;
+
+        Arg = ArgE.takeAs<Expr>();
+      }
+      
+      if (RequireCompleteType(Arg->getLocStart(),
+                              Arg->getType(),
+                              PDiag(diag::err_call_incomplete_argument)
+                                << Arg->getSourceRange()))
+        return ExprError();
+
+      TheCall->setArg(i, Arg);
+    }
+  }
+
+  if (CXXMethodDecl *Method = dyn_cast_or_null<CXXMethodDecl>(FDecl))
+    if (!Method->isStatic())
+      return ExprError(Diag(LParenLoc, diag::err_member_call_without_object)
+        << Fn->getSourceRange());
+
+  // Check for sentinels
+  if (NDecl)
+    DiagnoseSentinelCalls(NDecl, LParenLoc, Args, NumArgs);
+
+  // Do special checking on direct calls to functions.
+  if (FDecl) {
+    if (CheckFunctionCall(FDecl, TheCall))
+      return ExprError();
+
+    if (BuiltinID)
+      return CheckBuiltinFunctionCall(BuiltinID, TheCall);
+  } else if (NDecl) {
+    if (CheckBlockCall(NDecl, TheCall))
+      return ExprError();
+  }
+
+  return MaybeBindToTemporary(TheCall);
+}
+
+ExprResult
+Sema::ActOnCompoundLiteral(SourceLocation LParenLoc, ParsedType Ty,
+                           SourceLocation RParenLoc, Expr *InitExpr) {
+  assert((Ty != 0) && "ActOnCompoundLiteral(): missing type");
+  // FIXME: put back this assert when initializers are worked out.
+  //assert((InitExpr != 0) && "ActOnCompoundLiteral(): missing expression");
+
+  TypeSourceInfo *TInfo;
+  QualType literalType = GetTypeFromParser(Ty, &TInfo);
+  if (!TInfo)
+    TInfo = Context.getTrivialTypeSourceInfo(literalType);
+
+  return BuildCompoundLiteralExpr(LParenLoc, TInfo, RParenLoc, InitExpr);
+}
+
+ExprResult
+Sema::BuildCompoundLiteralExpr(SourceLocation LParenLoc, TypeSourceInfo *TInfo,
+                               SourceLocation RParenLoc, Expr *LiteralExpr) {
+  QualType literalType = TInfo->getType();
+
+  if (literalType->isArrayType()) {
+    if (RequireCompleteType(LParenLoc, Context.getBaseElementType(literalType),
+             PDiag(diag::err_illegal_decl_array_incomplete_type)
+               << SourceRange(LParenLoc,
+                              LiteralExpr->getSourceRange().getEnd())))
+      return ExprError();
+    if (literalType->isVariableArrayType())
+      return ExprError(Diag(LParenLoc, diag::err_variable_object_no_init)
+        << SourceRange(LParenLoc, LiteralExpr->getSourceRange().getEnd()));
+  } else if (!literalType->isDependentType() &&
+             RequireCompleteType(LParenLoc, literalType,
+                      PDiag(diag::err_typecheck_decl_incomplete_type)
+                        << SourceRange(LParenLoc,
+                                       LiteralExpr->getSourceRange().getEnd())))
+    return ExprError();
+
+  InitializedEntity Entity
+    = InitializedEntity::InitializeTemporary(literalType);
+  InitializationKind Kind
+    = InitializationKind::CreateCStyleCast(LParenLoc, 
+                                           SourceRange(LParenLoc, RParenLoc),
+                                           /*InitList=*/true);
+  InitializationSequence InitSeq(*this, Entity, Kind, &LiteralExpr, 1);
+  ExprResult Result = InitSeq.Perform(*this, Entity, Kind,
+                                       MultiExprArg(*this, &LiteralExpr, 1),
+                                            &literalType);
+  if (Result.isInvalid())
+    return ExprError();
+  LiteralExpr = Result.get();
+
+  bool isFileScope = getCurFunctionOrMethodDecl() == 0;
+  if (isFileScope) { // 6.5.2.5p3
+    if (CheckForConstantInitializer(LiteralExpr, literalType))
+      return ExprError();
+  }
+
+  // In C, compound literals are l-values for some reason.
+  ExprValueKind VK = getLangOpts().CPlusPlus ? VK_RValue : VK_LValue;
+
+  return MaybeBindToTemporary(
+           new (Context) CompoundLiteralExpr(LParenLoc, TInfo, literalType,
+                                             VK, LiteralExpr, isFileScope));
+}
+
+ExprResult
+Sema::ActOnInitList(SourceLocation LBraceLoc, MultiExprArg InitArgList,
+                    SourceLocation RBraceLoc) {
+  unsigned NumInit = InitArgList.size();
+  Expr **InitList = InitArgList.release();
+
+  // Immediately handle non-overload placeholders.  Overloads can be
+  // resolved contextually, but everything else here can't.
+  for (unsigned I = 0; I != NumInit; ++I) {
+    if (InitList[I]->getType()->isNonOverloadPlaceholderType()) {
+      ExprResult result = CheckPlaceholderExpr(InitList[I]);
+
+      // Ignore failures; dropping the entire initializer list because
+      // of one failure would be terrible for indexing/etc.
+      if (result.isInvalid()) continue;
+
+      InitList[I] = result.take();
+    }
+  }
+
+  // Semantic analysis for initializers is done by ActOnDeclarator() and
+  // CheckInitializer() - it requires knowledge of the object being intialized.
+
+  InitListExpr *E = new (Context) InitListExpr(Context, LBraceLoc, InitList,
+                                               NumInit, RBraceLoc);
+  E->setType(Context.VoidTy); // FIXME: just a place holder for now.
+  return Owned(E);
+}
+
+/// Do an explicit extend of the given block pointer if we're in ARC.
+static void maybeExtendBlockObject(Sema &S, ExprResult &E) {
+  assert(E.get()->getType()->isBlockPointerType());
+  assert(E.get()->isRValue());
+
+  // Only do this in an r-value context.
+  if (!S.getLangOpts().ObjCAutoRefCount) return;
+
+  E = ImplicitCastExpr::Create(S.Context, E.get()->getType(),
+                               CK_ARCExtendBlockObject, E.get(),
+                               /*base path*/ 0, VK_RValue);
+  S.ExprNeedsCleanups = true;
+}
+
+/// Prepare a conversion of the given expression to an ObjC object
+/// pointer type.
+CastKind Sema::PrepareCastToObjCObjectPointer(ExprResult &E) {
+  QualType type = E.get()->getType();
+  if (type->isObjCObjectPointerType()) {
+    return CK_BitCast;
+  } else if (type->isBlockPointerType()) {
+    maybeExtendBlockObject(*this, E);
+    return CK_BlockPointerToObjCPointerCast;
+  } else {
+    assert(type->isPointerType());
+    return CK_CPointerToObjCPointerCast;
+  }
+}
+
+/// Prepares for a scalar cast, performing all the necessary stages
+/// except the final cast and returning the kind required.
+CastKind Sema::PrepareScalarCast(ExprResult &Src, QualType DestTy) {
+  // Both Src and Dest are scalar types, i.e. arithmetic or pointer.
+  // Also, callers should have filtered out the invalid cases with
+  // pointers.  Everything else should be possible.
+
+  QualType SrcTy = Src.get()->getType();
+  if (const AtomicType *SrcAtomicTy = SrcTy->getAs<AtomicType>())
+    SrcTy = SrcAtomicTy->getValueType();
+  if (const AtomicType *DestAtomicTy = DestTy->getAs<AtomicType>())
+    DestTy = DestAtomicTy->getValueType();
+
+  if (Context.hasSameUnqualifiedType(SrcTy, DestTy))
+    return CK_NoOp;
+
+  switch (Type::ScalarTypeKind SrcKind = SrcTy->getScalarTypeKind()) {
+  case Type::STK_MemberPointer:
+    llvm_unreachable("member pointer type in C");
+
+  case Type::STK_CPointer:
+  case Type::STK_BlockPointer:
+  case Type::STK_ObjCObjectPointer:
+    switch (DestTy->getScalarTypeKind()) {
+    case Type::STK_CPointer:
+      return CK_BitCast;
+    case Type::STK_BlockPointer:
+      return (SrcKind == Type::STK_BlockPointer
+                ? CK_BitCast : CK_AnyPointerToBlockPointerCast);
+    case Type::STK_ObjCObjectPointer:
+      if (SrcKind == Type::STK_ObjCObjectPointer)
+        return CK_BitCast;
+      if (SrcKind == Type::STK_CPointer)
+        return CK_CPointerToObjCPointerCast;
+      maybeExtendBlockObject(*this, Src);
+      return CK_BlockPointerToObjCPointerCast;
+    case Type::STK_Bool:
+      return CK_PointerToBoolean;
+    case Type::STK_Integral:
+      return CK_PointerToIntegral;
+    case Type::STK_Floating:
+    case Type::STK_FloatingComplex:
+    case Type::STK_IntegralComplex:
+    case Type::STK_MemberPointer:
+      llvm_unreachable("illegal cast from pointer");
+    }
+    llvm_unreachable("Should have returned before this");
+
+  case Type::STK_Bool: // casting from bool is like casting from an integer
+  case Type::STK_Integral:
+    switch (DestTy->getScalarTypeKind()) {
+    case Type::STK_CPointer:
+    case Type::STK_ObjCObjectPointer:
+    case Type::STK_BlockPointer:
+      if (Src.get()->isNullPointerConstant(Context,
+                                           Expr::NPC_ValueDependentIsNull))
+        return CK_NullToPointer;
+      return CK_IntegralToPointer;
+    case Type::STK_Bool:
+      return CK_IntegralToBoolean;
+    case Type::STK_Integral:
+      return CK_IntegralCast;
+    case Type::STK_Floating:
+      return CK_IntegralToFloating;
+    case Type::STK_IntegralComplex:
+      Src = ImpCastExprToType(Src.take(),
+                              DestTy->castAs<ComplexType>()->getElementType(),
+                              CK_IntegralCast);
+      return CK_IntegralRealToComplex;
+    case Type::STK_FloatingComplex:
+      Src = ImpCastExprToType(Src.take(),
+                              DestTy->castAs<ComplexType>()->getElementType(),
+                              CK_IntegralToFloating);
+      return CK_FloatingRealToComplex;
+    case Type::STK_MemberPointer:
+      llvm_unreachable("member pointer type in C");
+    }
+    llvm_unreachable("Should have returned before this");
+
+  case Type::STK_Floating:
+    switch (DestTy->getScalarTypeKind()) {
+    case Type::STK_Floating:
+      return CK_FloatingCast;
+    case Type::STK_Bool:
+      return CK_FloatingToBoolean;
+    case Type::STK_Integral:
+      return CK_FloatingToIntegral;
+    case Type::STK_FloatingComplex:
+      Src = ImpCastExprToType(Src.take(),
+                              DestTy->castAs<ComplexType>()->getElementType(),
+                              CK_FloatingCast);
+      return CK_FloatingRealToComplex;
+    case Type::STK_IntegralComplex:
+      Src = ImpCastExprToType(Src.take(),
+                              DestTy->castAs<ComplexType>()->getElementType(),
+                              CK_FloatingToIntegral);
+      return CK_IntegralRealToComplex;
+    case Type::STK_CPointer:
+    case Type::STK_ObjCObjectPointer:
+    case Type::STK_BlockPointer:
+      llvm_unreachable("valid float->pointer cast?");
+    case Type::STK_MemberPointer:
+      llvm_unreachable("member pointer type in C");
+    }
+    llvm_unreachable("Should have returned before this");
+
+  case Type::STK_FloatingComplex:
+    switch (DestTy->getScalarTypeKind()) {
+    case Type::STK_FloatingComplex:
+      return CK_FloatingComplexCast;
+    case Type::STK_IntegralComplex:
+      return CK_FloatingComplexToIntegralComplex;
+    case Type::STK_Floating: {
+      QualType ET = SrcTy->castAs<ComplexType>()->getElementType();
+      if (Context.hasSameType(ET, DestTy))
+        return CK_FloatingComplexToReal;
+      Src = ImpCastExprToType(Src.take(), ET, CK_FloatingComplexToReal);
+      return CK_FloatingCast;
+    }
+    case Type::STK_Bool:
+      return CK_FloatingComplexToBoolean;
+    case Type::STK_Integral:
+      Src = ImpCastExprToType(Src.take(),
+                              SrcTy->castAs<ComplexType>()->getElementType(),
+                              CK_FloatingComplexToReal);
+      return CK_FloatingToIntegral;
+    case Type::STK_CPointer:
+    case Type::STK_ObjCObjectPointer:
+    case Type::STK_BlockPointer:
+      llvm_unreachable("valid complex float->pointer cast?");
+    case Type::STK_MemberPointer:
+      llvm_unreachable("member pointer type in C");
+    }
+    llvm_unreachable("Should have returned before this");
+
+  case Type::STK_IntegralComplex:
+    switch (DestTy->getScalarTypeKind()) {
+    case Type::STK_FloatingComplex:
+      return CK_IntegralComplexToFloatingComplex;
+    case Type::STK_IntegralComplex:
+      return CK_IntegralComplexCast;
+    case Type::STK_Integral: {
+      QualType ET = SrcTy->castAs<ComplexType>()->getElementType();
+      if (Context.hasSameType(ET, DestTy))
+        return CK_IntegralComplexToReal;
+      Src = ImpCastExprToType(Src.take(), ET, CK_IntegralComplexToReal);
+      return CK_IntegralCast;
+    }
+    case Type::STK_Bool:
+      return CK_IntegralComplexToBoolean;
+    case Type::STK_Floating:
+      Src = ImpCastExprToType(Src.take(),
+                              SrcTy->castAs<ComplexType>()->getElementType(),
+                              CK_IntegralComplexToReal);
+      return CK_IntegralToFloating;
+    case Type::STK_CPointer:
+    case Type::STK_ObjCObjectPointer:
+    case Type::STK_BlockPointer:
+      llvm_unreachable("valid complex int->pointer cast?");
+    case Type::STK_MemberPointer:
+      llvm_unreachable("member pointer type in C");
+    }
+    llvm_unreachable("Should have returned before this");
+  }
+
+  llvm_unreachable("Unhandled scalar cast");
+}
+
+bool Sema::CheckVectorCast(SourceRange R, QualType VectorTy, QualType Ty,
+                           CastKind &Kind) {
+  assert(VectorTy->isVectorType() && "Not a vector type!");
+
+  if (Ty->isVectorType() || Ty->isIntegerType()) {
+    if (Context.getTypeSize(VectorTy) != Context.getTypeSize(Ty))
+      return Diag(R.getBegin(),
+                  Ty->isVectorType() ?
+                  diag::err_invalid_conversion_between_vectors :
+                  diag::err_invalid_conversion_between_vector_and_integer)
+        << VectorTy << Ty << R;
+  } else
+    return Diag(R.getBegin(),
+                diag::err_invalid_conversion_between_vector_and_scalar)
+      << VectorTy << Ty << R;
+
+  Kind = CK_BitCast;
+  return false;
+}
+
+ExprResult Sema::CheckExtVectorCast(SourceRange R, QualType DestTy,
+                                    Expr *CastExpr, CastKind &Kind) {
+  assert(DestTy->isExtVectorType() && "Not an extended vector type!");
+
+  QualType SrcTy = CastExpr->getType();
+
+  // If SrcTy is a VectorType, the total size must match to explicitly cast to
+  // an ExtVectorType.
+  // In OpenCL, casts between vectors of different types are not allowed.
+  // (See OpenCL 6.2).
+  if (SrcTy->isVectorType()) {
+    if (Context.getTypeSize(DestTy) != Context.getTypeSize(SrcTy)
+        || (getLangOpts().OpenCL &&
+            (DestTy.getCanonicalType() != SrcTy.getCanonicalType()))) {
+      Diag(R.getBegin(),diag::err_invalid_conversion_between_ext_vectors)
+        << DestTy << SrcTy << R;
+      return ExprError();
+    }
+    Kind = CK_BitCast;
+    return Owned(CastExpr);
+  }
+
+  // All non-pointer scalars can be cast to ExtVector type.  The appropriate
+  // conversion will take place first from scalar to elt type, and then
+  // splat from elt type to vector.
+  if (SrcTy->isPointerType())
+    return Diag(R.getBegin(),
+                diag::err_invalid_conversion_between_vector_and_scalar)
+      << DestTy << SrcTy << R;
+
+  QualType DestElemTy = DestTy->getAs<ExtVectorType>()->getElementType();
+  ExprResult CastExprRes = Owned(CastExpr);
+  CastKind CK = PrepareScalarCast(CastExprRes, DestElemTy);
+  if (CastExprRes.isInvalid())
+    return ExprError();
+  CastExpr = ImpCastExprToType(CastExprRes.take(), DestElemTy, CK).take();
+
+  Kind = CK_VectorSplat;
+  return Owned(CastExpr);
+}
+
+ExprResult
+Sema::ActOnCastExpr(Scope *S, SourceLocation LParenLoc,
+                    Declarator &D, ParsedType &Ty,
+                    SourceLocation RParenLoc, Expr *CastExpr) {
+  assert(!D.isInvalidType() && (CastExpr != 0) &&
+         "ActOnCastExpr(): missing type or expr");
+
+  TypeSourceInfo *castTInfo = GetTypeForDeclaratorCast(D, CastExpr->getType());
+  if (D.isInvalidType())
+    return ExprError();
+
+  if (getLangOpts().CPlusPlus) {
+    // Check that there are no default arguments (C++ only).
+    CheckExtraCXXDefaultArguments(D);
+  }
+
+  checkUnusedDeclAttributes(D);
+
+  QualType castType = castTInfo->getType();
+  Ty = CreateParsedType(castType, castTInfo);
+
+  bool isVectorLiteral = false;
+
+  // Check for an altivec or OpenCL literal,
+  // i.e. all the elements are integer constants.
+  ParenExpr *PE = dyn_cast<ParenExpr>(CastExpr);
+  ParenListExpr *PLE = dyn_cast<ParenListExpr>(CastExpr);
+  if ((getLangOpts().AltiVec || getLangOpts().OpenCL)
+       && castType->isVectorType() && (PE || PLE)) {
+    if (PLE && PLE->getNumExprs() == 0) {
+      Diag(PLE->getExprLoc(), diag::err_altivec_empty_initializer);
+      return ExprError();
+    }
+    if (PE || PLE->getNumExprs() == 1) {
+      Expr *E = (PE ? PE->getSubExpr() : PLE->getExpr(0));
+      if (!E->getType()->isVectorType())
+        isVectorLiteral = true;
+    }
+    else
+      isVectorLiteral = true;
+  }
+
+  // If this is a vector initializer, '(' type ')' '(' init, ..., init ')'
+  // then handle it as such.
+  if (isVectorLiteral)
+    return BuildVectorLiteral(LParenLoc, RParenLoc, CastExpr, castTInfo);
+
+  // If the Expr being casted is a ParenListExpr, handle it specially.
+  // This is not an AltiVec-style cast, so turn the ParenListExpr into a
+  // sequence of BinOp comma operators.
+  if (isa<ParenListExpr>(CastExpr)) {
+    ExprResult Result = MaybeConvertParenListExprToParenExpr(S, CastExpr);
+    if (Result.isInvalid()) return ExprError();
+    CastExpr = Result.take();
+  }
+
+  return BuildCStyleCastExpr(LParenLoc, castTInfo, RParenLoc, CastExpr);
+}
+
+ExprResult Sema::BuildVectorLiteral(SourceLocation LParenLoc,
+                                    SourceLocation RParenLoc, Expr *E,
+                                    TypeSourceInfo *TInfo) {
+  assert((isa<ParenListExpr>(E) || isa<ParenExpr>(E)) &&
+         "Expected paren or paren list expression");
+
+  Expr **exprs;
+  unsigned numExprs;
+  Expr *subExpr;
+  if (ParenListExpr *PE = dyn_cast<ParenListExpr>(E)) {
+    exprs = PE->getExprs();
+    numExprs = PE->getNumExprs();
+  } else {
+    subExpr = cast<ParenExpr>(E)->getSubExpr();
+    exprs = &subExpr;
+    numExprs = 1;
+  }
+
+  QualType Ty = TInfo->getType();
+  assert(Ty->isVectorType() && "Expected vector type");
+
+  SmallVector<Expr *, 8> initExprs;
+  const VectorType *VTy = Ty->getAs<VectorType>();
+  unsigned numElems = Ty->getAs<VectorType>()->getNumElements();
+  
+  // '(...)' form of vector initialization in AltiVec: the number of
+  // initializers must be one or must match the size of the vector.
+  // If a single value is specified in the initializer then it will be
+  // replicated to all the components of the vector
+  if (VTy->getVectorKind() == VectorType::AltiVecVector) {
+    // The number of initializers must be one or must match the size of the
+    // vector. If a single value is specified in the initializer then it will
+    // be replicated to all the components of the vector
+    if (numExprs == 1) {
+      QualType ElemTy = Ty->getAs<VectorType>()->getElementType();
+      ExprResult Literal = DefaultLvalueConversion(exprs[0]);
+      if (Literal.isInvalid())
+        return ExprError();
+      Literal = ImpCastExprToType(Literal.take(), ElemTy,
+                                  PrepareScalarCast(Literal, ElemTy));
+      return BuildCStyleCastExpr(LParenLoc, TInfo, RParenLoc, Literal.take());
+    }
+    else if (numExprs < numElems) {
+      Diag(E->getExprLoc(),
+           diag::err_incorrect_number_of_vector_initializers);
+      return ExprError();
+    }
+    else
+      initExprs.append(exprs, exprs + numExprs);
+  }
+  else {
+    // For OpenCL, when the number of initializers is a single value,
+    // it will be replicated to all components of the vector.
+    if (getLangOpts().OpenCL &&
+        VTy->getVectorKind() == VectorType::GenericVector &&
+        numExprs == 1) {
+        QualType ElemTy = Ty->getAs<VectorType>()->getElementType();
+        ExprResult Literal = DefaultLvalueConversion(exprs[0]);
+        if (Literal.isInvalid())
+          return ExprError();
+        Literal = ImpCastExprToType(Literal.take(), ElemTy,
+                                    PrepareScalarCast(Literal, ElemTy));
+        return BuildCStyleCastExpr(LParenLoc, TInfo, RParenLoc, Literal.take());
+    }
+    
+    initExprs.append(exprs, exprs + numExprs);
+  }
+  // FIXME: This means that pretty-printing the final AST will produce curly
+  // braces instead of the original commas.
+  InitListExpr *initE = new (Context) InitListExpr(Context, LParenLoc,
+                                                   &initExprs[0],
+                                                   initExprs.size(), RParenLoc);
+  initE->setType(Ty);
+  return BuildCompoundLiteralExpr(LParenLoc, TInfo, RParenLoc, initE);
+}
+
+/// This is not an AltiVec-style cast or or C++ direct-initialization, so turn
+/// the ParenListExpr into a sequence of comma binary operators.
+ExprResult
+Sema::MaybeConvertParenListExprToParenExpr(Scope *S, Expr *OrigExpr) {
+  ParenListExpr *E = dyn_cast<ParenListExpr>(OrigExpr);
+  if (!E)
+    return Owned(OrigExpr);
+
+  ExprResult Result(E->getExpr(0));
+
+  for (unsigned i = 1, e = E->getNumExprs(); i != e && !Result.isInvalid(); ++i)
+    Result = ActOnBinOp(S, E->getExprLoc(), tok::comma, Result.get(),
+                        E->getExpr(i));
+
+  if (Result.isInvalid()) return ExprError();
+
+  return ActOnParenExpr(E->getLParenLoc(), E->getRParenLoc(), Result.get());
+}
+
+ExprResult Sema::ActOnParenListExpr(SourceLocation L,
+                                    SourceLocation R,
+                                    MultiExprArg Val) {
+  unsigned nexprs = Val.size();
+  Expr **exprs = reinterpret_cast<Expr**>(Val.release());
+  assert((exprs != 0) && "ActOnParenOrParenListExpr() missing expr list");
+  Expr *expr = new (Context) ParenListExpr(Context, L, exprs, nexprs, R);
+  return Owned(expr);
+}
+
+/// \brief Emit a specialized diagnostic when one expression is a null pointer
+/// constant and the other is not a pointer.  Returns true if a diagnostic is
+/// emitted.
+bool Sema::DiagnoseConditionalForNull(Expr *LHSExpr, Expr *RHSExpr,
+                                      SourceLocation QuestionLoc) {
+  Expr *NullExpr = LHSExpr;
+  Expr *NonPointerExpr = RHSExpr;
+  Expr::NullPointerConstantKind NullKind =
+      NullExpr->isNullPointerConstant(Context,
+                                      Expr::NPC_ValueDependentIsNotNull);
+
+  if (NullKind == Expr::NPCK_NotNull) {
+    NullExpr = RHSExpr;
+    NonPointerExpr = LHSExpr;
+    NullKind =
+        NullExpr->isNullPointerConstant(Context,
+                                        Expr::NPC_ValueDependentIsNotNull);
+  }
+
+  if (NullKind == Expr::NPCK_NotNull)
+    return false;
+
+  if (NullKind == Expr::NPCK_ZeroInteger) {
+    // In this case, check to make sure that we got here from a "NULL"
+    // string in the source code.
+    NullExpr = NullExpr->IgnoreParenImpCasts();
+    SourceLocation loc = NullExpr->getExprLoc();
+    if (!findMacroSpelling(loc, "NULL"))
+      return false;
+  }
+
+  int DiagType = (NullKind == Expr::NPCK_CXX0X_nullptr);
+  Diag(QuestionLoc, diag::err_typecheck_cond_incompatible_operands_null)
+      << NonPointerExpr->getType() << DiagType
+      << NonPointerExpr->getSourceRange();
+  return true;
+}
+
+/// \brief Return false if the condition expression is valid, true otherwise.
+static bool checkCondition(Sema &S, Expr *Cond) {
+  QualType CondTy = Cond->getType();
+
+  // C99 6.5.15p2
+  if (CondTy->isScalarType()) return false;
+
+  // OpenCL: Sec 6.3.i says the condition is allowed to be a vector or scalar.
+  if (S.getLangOpts().OpenCL && CondTy->isVectorType())
+    return false;
+
+  // Emit the proper error message.
+  S.Diag(Cond->getLocStart(), S.getLangOpts().OpenCL ?
+                              diag::err_typecheck_cond_expect_scalar :
+                              diag::err_typecheck_cond_expect_scalar_or_vector)
+    << CondTy;
+  return true;
+}
+
+/// \brief Return false if the two expressions can be converted to a vector,
+/// true otherwise
+static bool checkConditionalConvertScalarsToVectors(Sema &S, ExprResult &LHS,
+                                                    ExprResult &RHS,
+                                                    QualType CondTy) {
+  // Both operands should be of scalar type.
+  if (!LHS.get()->getType()->isScalarType()) {
+    S.Diag(LHS.get()->getLocStart(), diag::err_typecheck_cond_expect_scalar)
+      << CondTy;
+    return true;
+  }
+  if (!RHS.get()->getType()->isScalarType()) {
+    S.Diag(RHS.get()->getLocStart(), diag::err_typecheck_cond_expect_scalar)
+      << CondTy;
+    return true;
+  }
+
+  // Implicity convert these scalars to the type of the condition.
+  LHS = S.ImpCastExprToType(LHS.take(), CondTy, CK_IntegralCast);
+  RHS = S.ImpCastExprToType(RHS.take(), CondTy, CK_IntegralCast);
+  return false;
+}
+
+/// \brief Handle when one or both operands are void type.
+static QualType checkConditionalVoidType(Sema &S, ExprResult &LHS,
+                                         ExprResult &RHS) {
+    Expr *LHSExpr = LHS.get();
+    Expr *RHSExpr = RHS.get();
+
+    if (!LHSExpr->getType()->isVoidType())
+      S.Diag(RHSExpr->getLocStart(), diag::ext_typecheck_cond_one_void)
+        << RHSExpr->getSourceRange();
+    if (!RHSExpr->getType()->isVoidType())
+      S.Diag(LHSExpr->getLocStart(), diag::ext_typecheck_cond_one_void)
+        << LHSExpr->getSourceRange();
+    LHS = S.ImpCastExprToType(LHS.take(), S.Context.VoidTy, CK_ToVoid);
+    RHS = S.ImpCastExprToType(RHS.take(), S.Context.VoidTy, CK_ToVoid);
+    return S.Context.VoidTy;
+}
+
+/// \brief Return false if the NullExpr can be promoted to PointerTy,
+/// true otherwise.
+static bool checkConditionalNullPointer(Sema &S, ExprResult &NullExpr,
+                                        QualType PointerTy) {
+  if ((!PointerTy->isAnyPointerType() && !PointerTy->isBlockPointerType()) ||
+      !NullExpr.get()->isNullPointerConstant(S.Context,
+                                            Expr::NPC_ValueDependentIsNull))
+    return true;
+
+  NullExpr = S.ImpCastExprToType(NullExpr.take(), PointerTy, CK_NullToPointer);
+  return false;
+}
+
+/// \brief Checks compatibility between two pointers and return the resulting
+/// type.
+static QualType checkConditionalPointerCompatibility(Sema &S, ExprResult &LHS,
+                                                     ExprResult &RHS,
+                                                     SourceLocation Loc) {
+  QualType LHSTy = LHS.get()->getType();
+  QualType RHSTy = RHS.get()->getType();
+
+  if (S.Context.hasSameType(LHSTy, RHSTy)) {
+    // Two identical pointers types are always compatible.
+    return LHSTy;
+  }
+
+  QualType lhptee, rhptee;
+
+  // Get the pointee types.
+  if (const BlockPointerType *LHSBTy = LHSTy->getAs<BlockPointerType>()) {
+    lhptee = LHSBTy->getPointeeType();
+    rhptee = RHSTy->castAs<BlockPointerType>()->getPointeeType();
+  } else {
+    lhptee = LHSTy->castAs<PointerType>()->getPointeeType();
+    rhptee = RHSTy->castAs<PointerType>()->getPointeeType();
+  }
+
+  // C99 6.5.15p6: If both operands are pointers to compatible types or to
+  // differently qualified versions of compatible types, the result type is
+  // a pointer to an appropriately qualified version of the composite
+  // type.
+
+  // Only CVR-qualifiers exist in the standard, and the differently-qualified
+  // clause doesn't make sense for our extensions. E.g. address space 2 should
+  // be incompatible with address space 3: they may live on different devices or
+  // anything.
+  Qualifiers lhQual = lhptee.getQualifiers();
+  Qualifiers rhQual = rhptee.getQualifiers();
+
+  unsigned MergedCVRQual = lhQual.getCVRQualifiers() | rhQual.getCVRQualifiers();
+  lhQual.removeCVRQualifiers();
+  rhQual.removeCVRQualifiers();
+
+  lhptee = S.Context.getQualifiedType(lhptee.getUnqualifiedType(), lhQual);
+  rhptee = S.Context.getQualifiedType(rhptee.getUnqualifiedType(), rhQual);
+
+  QualType CompositeTy = S.Context.mergeTypes(lhptee, rhptee);
+
+  if (CompositeTy.isNull()) {
+    S.Diag(Loc, diag::warn_typecheck_cond_incompatible_pointers)
+      << LHSTy << RHSTy << LHS.get()->getSourceRange()
+      << RHS.get()->getSourceRange();
+    // In this situation, we assume void* type. No especially good
+    // reason, but this is what gcc does, and we do have to pick
+    // to get a consistent AST.
+    QualType incompatTy = S.Context.getPointerType(S.Context.VoidTy);
+    LHS = S.ImpCastExprToType(LHS.take(), incompatTy, CK_BitCast);
+    RHS = S.ImpCastExprToType(RHS.take(), incompatTy, CK_BitCast);
+    return incompatTy;
+  }
+
+  // The pointer types are compatible.
+  QualType ResultTy = CompositeTy.withCVRQualifiers(MergedCVRQual);
+  ResultTy = S.Context.getPointerType(ResultTy);
+
+  LHS = S.ImpCastExprToType(LHS.take(), ResultTy, CK_BitCast);
+  RHS = S.ImpCastExprToType(RHS.take(), ResultTy, CK_BitCast);
+  return ResultTy;
+}
+
+/// \brief Return the resulting type when the operands are both block pointers.
+static QualType checkConditionalBlockPointerCompatibility(Sema &S,
+                                                          ExprResult &LHS,
+                                                          ExprResult &RHS,
+                                                          SourceLocation Loc) {
+  QualType LHSTy = LHS.get()->getType();
+  QualType RHSTy = RHS.get()->getType();
+
+  if (!LHSTy->isBlockPointerType() || !RHSTy->isBlockPointerType()) {
+    if (LHSTy->isVoidPointerType() || RHSTy->isVoidPointerType()) {
+      QualType destType = S.Context.getPointerType(S.Context.VoidTy);
+      LHS = S.ImpCastExprToType(LHS.take(), destType, CK_BitCast);
+      RHS = S.ImpCastExprToType(RHS.take(), destType, CK_BitCast);
+      return destType;
+    }
+    S.Diag(Loc, diag::err_typecheck_cond_incompatible_operands)
+      << LHSTy << RHSTy << LHS.get()->getSourceRange()
+      << RHS.get()->getSourceRange();
+    return QualType();
+  }
+
+  // We have 2 block pointer types.
+  return checkConditionalPointerCompatibility(S, LHS, RHS, Loc);
+}
+
+/// \brief Return the resulting type when the operands are both pointers.
+static QualType
+checkConditionalObjectPointersCompatibility(Sema &S, ExprResult &LHS,
+                                            ExprResult &RHS,
+                                            SourceLocation Loc) {
+  // get the pointer types
+  QualType LHSTy = LHS.get()->getType();
+  QualType RHSTy = RHS.get()->getType();
+
+  // get the "pointed to" types
+  QualType lhptee = LHSTy->getAs<PointerType>()->getPointeeType();
+  QualType rhptee = RHSTy->getAs<PointerType>()->getPointeeType();
+
+  // ignore qualifiers on void (C99 6.5.15p3, clause 6)
+  if (lhptee->isVoidType() && rhptee->isIncompleteOrObjectType()) {
+    // Figure out necessary qualifiers (C99 6.5.15p6)
+    QualType destPointee
+      = S.Context.getQualifiedType(lhptee, rhptee.getQualifiers());
+    QualType destType = S.Context.getPointerType(destPointee);
+    // Add qualifiers if necessary.
+    LHS = S.ImpCastExprToType(LHS.take(), destType, CK_NoOp);
+    // Promote to void*.
+    RHS = S.ImpCastExprToType(RHS.take(), destType, CK_BitCast);
+    return destType;
+  }
+  if (rhptee->isVoidType() && lhptee->isIncompleteOrObjectType()) {
+    QualType destPointee
+      = S.Context.getQualifiedType(rhptee, lhptee.getQualifiers());
+    QualType destType = S.Context.getPointerType(destPointee);
+    // Add qualifiers if necessary.
+    RHS = S.ImpCastExprToType(RHS.take(), destType, CK_NoOp);
+    // Promote to void*.
+    LHS = S.ImpCastExprToType(LHS.take(), destType, CK_BitCast);
+    return destType;
+  }
+
+  return checkConditionalPointerCompatibility(S, LHS, RHS, Loc);
+}
+
+/// \brief Return false if the first expression is not an integer and the second
+/// expression is not a pointer, true otherwise.
+static bool checkPointerIntegerMismatch(Sema &S, ExprResult &Int,
+                                        Expr* PointerExpr, SourceLocation Loc,
+                                        bool IsIntFirstExpr) {
+  if (!PointerExpr->getType()->isPointerType() ||
+      !Int.get()->getType()->isIntegerType())
+    return false;
+
+  Expr *Expr1 = IsIntFirstExpr ? Int.get() : PointerExpr;
+  Expr *Expr2 = IsIntFirstExpr ? PointerExpr : Int.get();
+
+  S.Diag(Loc, diag::warn_typecheck_cond_pointer_integer_mismatch)
+    << Expr1->getType() << Expr2->getType()
+    << Expr1->getSourceRange() << Expr2->getSourceRange();
+  Int = S.ImpCastExprToType(Int.take(), PointerExpr->getType(),
+                            CK_IntegralToPointer);
+  return true;
+}
+
+/// Note that LHS is not null here, even if this is the gnu "x ?: y" extension.
+/// In that case, LHS = cond.
+/// C99 6.5.15
+QualType Sema::CheckConditionalOperands(ExprResult &Cond, ExprResult &LHS,
+                                        ExprResult &RHS, ExprValueKind &VK,
+                                        ExprObjectKind &OK,
+                                        SourceLocation QuestionLoc) {
+
+  ExprResult LHSResult = CheckPlaceholderExpr(LHS.get());
+  if (!LHSResult.isUsable()) return QualType();
+  LHS = move(LHSResult);
+
+  ExprResult RHSResult = CheckPlaceholderExpr(RHS.get());
+  if (!RHSResult.isUsable()) return QualType();
+  RHS = move(RHSResult);
+
+  // C++ is sufficiently different to merit its own checker.
+  if (getLangOpts().CPlusPlus)
+    return CXXCheckConditionalOperands(Cond, LHS, RHS, VK, OK, QuestionLoc);
+
+  VK = VK_RValue;
+  OK = OK_Ordinary;
+
+  Cond = UsualUnaryConversions(Cond.take());
+  if (Cond.isInvalid())
+    return QualType();
+  LHS = UsualUnaryConversions(LHS.take());
+  if (LHS.isInvalid())
+    return QualType();
+  RHS = UsualUnaryConversions(RHS.take());
+  if (RHS.isInvalid())
+    return QualType();
+
+  QualType CondTy = Cond.get()->getType();
+  QualType LHSTy = LHS.get()->getType();
+  QualType RHSTy = RHS.get()->getType();
+
+  // first, check the condition.
+  if (checkCondition(*this, Cond.get()))
+    return QualType();
+
+  // Now check the two expressions.
+  if (LHSTy->isVectorType() || RHSTy->isVectorType())
+    return CheckVectorOperands(LHS, RHS, QuestionLoc, /*isCompAssign*/false);
+
+  // OpenCL: If the condition is a vector, and both operands are scalar,
+  // attempt to implicity convert them to the vector type to act like the
+  // built in select.
+  if (getLangOpts().OpenCL && CondTy->isVectorType())
+    if (checkConditionalConvertScalarsToVectors(*this, LHS, RHS, CondTy))
+      return QualType();
+  
+  // If both operands have arithmetic type, do the usual arithmetic conversions
+  // to find a common type: C99 6.5.15p3,5.
+  if (LHSTy->isArithmeticType() && RHSTy->isArithmeticType()) {
+    UsualArithmeticConversions(LHS, RHS);
+    if (LHS.isInvalid() || RHS.isInvalid())
+      return QualType();
+    return LHS.get()->getType();
+  }
+
+  // If both operands are the same structure or union type, the result is that
+  // type.
+  if (const RecordType *LHSRT = LHSTy->getAs<RecordType>()) {    // C99 6.5.15p3
+    if (const RecordType *RHSRT = RHSTy->getAs<RecordType>())
+      if (LHSRT->getDecl() == RHSRT->getDecl())
+        // "If both the operands have structure or union type, the result has
+        // that type."  This implies that CV qualifiers are dropped.
+        return LHSTy.getUnqualifiedType();
+    // FIXME: Type of conditional expression must be complete in C mode.
+  }
+
+  // C99 6.5.15p5: "If both operands have void type, the result has void type."
+  // The following || allows only one side to be void (a GCC-ism).
+  if (LHSTy->isVoidType() || RHSTy->isVoidType()) {
+    return checkConditionalVoidType(*this, LHS, RHS);
+  }
+
+  // C99 6.5.15p6 - "if one operand is a null pointer constant, the result has
+  // the type of the other operand."
+  if (!checkConditionalNullPointer(*this, RHS, LHSTy)) return LHSTy;
+  if (!checkConditionalNullPointer(*this, LHS, RHSTy)) return RHSTy;
+
+  // All objective-c pointer type analysis is done here.
+  QualType compositeType = FindCompositeObjCPointerType(LHS, RHS,
+                                                        QuestionLoc);
+  if (LHS.isInvalid() || RHS.isInvalid())
+    return QualType();
+  if (!compositeType.isNull())
+    return compositeType;
+
+
+  // Handle block pointer types.
+  if (LHSTy->isBlockPointerType() || RHSTy->isBlockPointerType())
+    return checkConditionalBlockPointerCompatibility(*this, LHS, RHS,
+                                                     QuestionLoc);
+
+  // Check constraints for C object pointers types (C99 6.5.15p3,6).
+  if (LHSTy->isPointerType() && RHSTy->isPointerType())
+    return checkConditionalObjectPointersCompatibility(*this, LHS, RHS,
+                                                       QuestionLoc);
+
+  // GCC compatibility: soften pointer/integer mismatch.  Note that
+  // null pointers have been filtered out by this point.
+  if (checkPointerIntegerMismatch(*this, LHS, RHS.get(), QuestionLoc,
+      /*isIntFirstExpr=*/true))
+    return RHSTy;
+  if (checkPointerIntegerMismatch(*this, RHS, LHS.get(), QuestionLoc,
+      /*isIntFirstExpr=*/false))
+    return LHSTy;
+
+  // Emit a better diagnostic if one of the expressions is a null pointer
+  // constant and the other is not a pointer type. In this case, the user most
+  // likely forgot to take the address of the other expression.
+  if (DiagnoseConditionalForNull(LHS.get(), RHS.get(), QuestionLoc))
+    return QualType();
+
+  // Otherwise, the operands are not compatible.
+  Diag(QuestionLoc, diag::err_typecheck_cond_incompatible_operands)
+    << LHSTy << RHSTy << LHS.get()->getSourceRange()
+    << RHS.get()->getSourceRange();
+  return QualType();
+}
+
+/// FindCompositeObjCPointerType - Helper method to find composite type of
+/// two objective-c pointer types of the two input expressions.
+QualType Sema::FindCompositeObjCPointerType(ExprResult &LHS, ExprResult &RHS,
+                                            SourceLocation QuestionLoc) {
+  QualType LHSTy = LHS.get()->getType();
+  QualType RHSTy = RHS.get()->getType();
+
+  // Handle things like Class and struct objc_class*.  Here we case the result
+  // to the pseudo-builtin, because that will be implicitly cast back to the
+  // redefinition type if an attempt is made to access its fields.
+  if (LHSTy->isObjCClassType() &&
+      (Context.hasSameType(RHSTy, Context.getObjCClassRedefinitionType()))) {
+    RHS = ImpCastExprToType(RHS.take(), LHSTy, CK_CPointerToObjCPointerCast);
+    return LHSTy;
+  }
+  if (RHSTy->isObjCClassType() &&
+      (Context.hasSameType(LHSTy, Context.getObjCClassRedefinitionType()))) {
+    LHS = ImpCastExprToType(LHS.take(), RHSTy, CK_CPointerToObjCPointerCast);
+    return RHSTy;
+  }
+  // And the same for struct objc_object* / id
+  if (LHSTy->isObjCIdType() &&
+      (Context.hasSameType(RHSTy, Context.getObjCIdRedefinitionType()))) {
+    RHS = ImpCastExprToType(RHS.take(), LHSTy, CK_CPointerToObjCPointerCast);
+    return LHSTy;
+  }
+  if (RHSTy->isObjCIdType() &&
+      (Context.hasSameType(LHSTy, Context.getObjCIdRedefinitionType()))) {
+    LHS = ImpCastExprToType(LHS.take(), RHSTy, CK_CPointerToObjCPointerCast);
+    return RHSTy;
+  }
+  // And the same for struct objc_selector* / SEL
+  if (Context.isObjCSelType(LHSTy) &&
+      (Context.hasSameType(RHSTy, Context.getObjCSelRedefinitionType()))) {
+    RHS = ImpCastExprToType(RHS.take(), LHSTy, CK_BitCast);
+    return LHSTy;
+  }
+  if (Context.isObjCSelType(RHSTy) &&
+      (Context.hasSameType(LHSTy, Context.getObjCSelRedefinitionType()))) {
+    LHS = ImpCastExprToType(LHS.take(), RHSTy, CK_BitCast);
+    return RHSTy;
+  }
+  // Check constraints for Objective-C object pointers types.
+  if (LHSTy->isObjCObjectPointerType() && RHSTy->isObjCObjectPointerType()) {
+
+    if (Context.getCanonicalType(LHSTy) == Context.getCanonicalType(RHSTy)) {
+      // Two identical object pointer types are always compatible.
+      return LHSTy;
+    }
+    const ObjCObjectPointerType *LHSOPT = LHSTy->castAs<ObjCObjectPointerType>();
+    const ObjCObjectPointerType *RHSOPT = RHSTy->castAs<ObjCObjectPointerType>();
+    QualType compositeType = LHSTy;
+
+    // If both operands are interfaces and either operand can be
+    // assigned to the other, use that type as the composite
+    // type. This allows
+    //   xxx ? (A*) a : (B*) b
+    // where B is a subclass of A.
+    //
+    // Additionally, as for assignment, if either type is 'id'
+    // allow silent coercion. Finally, if the types are
+    // incompatible then make sure to use 'id' as the composite
+    // type so the result is acceptable for sending messages to.
+
+    // FIXME: Consider unifying with 'areComparableObjCPointerTypes'.
+    // It could return the composite type.
+    if (Context.canAssignObjCInterfaces(LHSOPT, RHSOPT)) {
+      compositeType = RHSOPT->isObjCBuiltinType() ? RHSTy : LHSTy;
+    } else if (Context.canAssignObjCInterfaces(RHSOPT, LHSOPT)) {
+      compositeType = LHSOPT->isObjCBuiltinType() ? LHSTy : RHSTy;
+    } else if ((LHSTy->isObjCQualifiedIdType() ||
+                RHSTy->isObjCQualifiedIdType()) &&
+               Context.ObjCQualifiedIdTypesAreCompatible(LHSTy, RHSTy, true)) {
+      // Need to handle "id<xx>" explicitly.
+      // GCC allows qualified id and any Objective-C type to devolve to
+      // id. Currently localizing to here until clear this should be
+      // part of ObjCQualifiedIdTypesAreCompatible.
+      compositeType = Context.getObjCIdType();
+    } else if (LHSTy->isObjCIdType() || RHSTy->isObjCIdType()) {
+      compositeType = Context.getObjCIdType();
+    } else if (!(compositeType =
+                 Context.areCommonBaseCompatible(LHSOPT, RHSOPT)).isNull())
+      ;
+    else {
+      Diag(QuestionLoc, diag::ext_typecheck_cond_incompatible_operands)
+      << LHSTy << RHSTy
+      << LHS.get()->getSourceRange() << RHS.get()->getSourceRange();
+      QualType incompatTy = Context.getObjCIdType();
+      LHS = ImpCastExprToType(LHS.take(), incompatTy, CK_BitCast);
+      RHS = ImpCastExprToType(RHS.take(), incompatTy, CK_BitCast);
+      return incompatTy;
+    }
+    // The object pointer types are compatible.
+    LHS = ImpCastExprToType(LHS.take(), compositeType, CK_BitCast);
+    RHS = ImpCastExprToType(RHS.take(), compositeType, CK_BitCast);
+    return compositeType;
+  }
+  // Check Objective-C object pointer types and 'void *'
+  if (LHSTy->isVoidPointerType() && RHSTy->isObjCObjectPointerType()) {
+    if (getLangOpts().ObjCAutoRefCount) {
+      // ARC forbids the implicit conversion of object pointers to 'void *',
+      // so these types are not compatible.
+      Diag(QuestionLoc, diag::err_cond_voidptr_arc) << LHSTy << RHSTy
+          << LHS.get()->getSourceRange() << RHS.get()->getSourceRange();
+      LHS = RHS = true;
+      return QualType();
+    }
+    QualType lhptee = LHSTy->getAs<PointerType>()->getPointeeType();
+    QualType rhptee = RHSTy->getAs<ObjCObjectPointerType>()->getPointeeType();
+    QualType destPointee
+    = Context.getQualifiedType(lhptee, rhptee.getQualifiers());
+    QualType destType = Context.getPointerType(destPointee);
+    // Add qualifiers if necessary.
+    LHS = ImpCastExprToType(LHS.take(), destType, CK_NoOp);
+    // Promote to void*.
+    RHS = ImpCastExprToType(RHS.take(), destType, CK_BitCast);
+    return destType;
+  }
+  if (LHSTy->isObjCObjectPointerType() && RHSTy->isVoidPointerType()) {
+    if (getLangOpts().ObjCAutoRefCount) {
+      // ARC forbids the implicit conversion of object pointers to 'void *',
+      // so these types are not compatible.
+      Diag(QuestionLoc, diag::err_cond_voidptr_arc) << LHSTy << RHSTy
+          << LHS.get()->getSourceRange() << RHS.get()->getSourceRange();
+      LHS = RHS = true;
+      return QualType();
+    }
+    QualType lhptee = LHSTy->getAs<ObjCObjectPointerType>()->getPointeeType();
+    QualType rhptee = RHSTy->getAs<PointerType>()->getPointeeType();
+    QualType destPointee
+    = Context.getQualifiedType(rhptee, lhptee.getQualifiers());
+    QualType destType = Context.getPointerType(destPointee);
+    // Add qualifiers if necessary.
+    RHS = ImpCastExprToType(RHS.take(), destType, CK_NoOp);
+    // Promote to void*.
+    LHS = ImpCastExprToType(LHS.take(), destType, CK_BitCast);
+    return destType;
+  }
+  return QualType();
+}
+
+/// SuggestParentheses - Emit a note with a fixit hint that wraps
+/// ParenRange in parentheses.
+static void SuggestParentheses(Sema &Self, SourceLocation Loc,
+                               const PartialDiagnostic &Note,
+                               SourceRange ParenRange) {
+  SourceLocation EndLoc = Self.PP.getLocForEndOfToken(ParenRange.getEnd());
+  if (ParenRange.getBegin().isFileID() && ParenRange.getEnd().isFileID() &&
+      EndLoc.isValid()) {
+    Self.Diag(Loc, Note)
+      << FixItHint::CreateInsertion(ParenRange.getBegin(), "(")
+      << FixItHint::CreateInsertion(EndLoc, ")");
+  } else {
+    // We can't display the parentheses, so just show the bare note.
+    Self.Diag(Loc, Note) << ParenRange;
+  }
+}
+
+static bool IsArithmeticOp(BinaryOperatorKind Opc) {
+  return Opc >= BO_Mul && Opc <= BO_Shr;
+}
+
+/// IsArithmeticBinaryExpr - Returns true if E is an arithmetic binary
+/// expression, either using a built-in or overloaded operator,
+/// and sets *OpCode to the opcode and *RHSExprs to the right-hand side
+/// expression.
+static bool IsArithmeticBinaryExpr(Expr *E, BinaryOperatorKind *Opcode,
+                                   Expr **RHSExprs) {
+  // Don't strip parenthesis: we should not warn if E is in parenthesis.
+  E = E->IgnoreImpCasts();
+  E = E->IgnoreConversionOperator();
+  E = E->IgnoreImpCasts();
+
+  // Built-in binary operator.
+  if (BinaryOperator *OP = dyn_cast<BinaryOperator>(E)) {
+    if (IsArithmeticOp(OP->getOpcode())) {
+      *Opcode = OP->getOpcode();
+      *RHSExprs = OP->getRHS();
+      return true;
+    }
+  }
+
+  // Overloaded operator.
+  if (CXXOperatorCallExpr *Call = dyn_cast<CXXOperatorCallExpr>(E)) {
+    if (Call->getNumArgs() != 2)
+      return false;
+
+    // Make sure this is really a binary operator that is safe to pass into
+    // BinaryOperator::getOverloadedOpcode(), e.g. it's not a subscript op.
+    OverloadedOperatorKind OO = Call->getOperator();
+    if (OO < OO_Plus || OO > OO_Arrow)
+      return false;
+
+    BinaryOperatorKind OpKind = BinaryOperator::getOverloadedOpcode(OO);
+    if (IsArithmeticOp(OpKind)) {
+      *Opcode = OpKind;
+      *RHSExprs = Call->getArg(1);
+      return true;
+    }
+  }
+
+  return false;
+}
+
+static bool IsLogicOp(BinaryOperatorKind Opc) {
+  return (Opc >= BO_LT && Opc <= BO_NE) || (Opc >= BO_LAnd && Opc <= BO_LOr);
+}
+
+/// ExprLooksBoolean - Returns true if E looks boolean, i.e. it has boolean type
+/// or is a logical expression such as (x==y) which has int type, but is
+/// commonly interpreted as boolean.
+static bool ExprLooksBoolean(Expr *E) {
+  E = E->IgnoreParenImpCasts();
+
+  if (E->getType()->isBooleanType())
+    return true;
+  if (BinaryOperator *OP = dyn_cast<BinaryOperator>(E))
+    return IsLogicOp(OP->getOpcode());
+  if (UnaryOperator *OP = dyn_cast<UnaryOperator>(E))
+    return OP->getOpcode() == UO_LNot;
+
+  return false;
+}
+
+/// DiagnoseConditionalPrecedence - Emit a warning when a conditional operator
+/// and binary operator are mixed in a way that suggests the programmer assumed
+/// the conditional operator has higher precedence, for example:
+/// "int x = a + someBinaryCondition ? 1 : 2".
+static void DiagnoseConditionalPrecedence(Sema &Self,
+                                          SourceLocation OpLoc,
+                                          Expr *Condition,
+                                          Expr *LHSExpr,
+                                          Expr *RHSExpr) {
+  BinaryOperatorKind CondOpcode;
+  Expr *CondRHS;
+
+  if (!IsArithmeticBinaryExpr(Condition, &CondOpcode, &CondRHS))
+    return;
+  if (!ExprLooksBoolean(CondRHS))
+    return;
+
+  // The condition is an arithmetic binary expression, with a right-
+  // hand side that looks boolean, so warn.
+
+  Self.Diag(OpLoc, diag::warn_precedence_conditional)
+      << Condition->getSourceRange()
+      << BinaryOperator::getOpcodeStr(CondOpcode);
+
+  SuggestParentheses(Self, OpLoc,
+    Self.PDiag(diag::note_precedence_conditional_silence)
+      << BinaryOperator::getOpcodeStr(CondOpcode),
+    SourceRange(Condition->getLocStart(), Condition->getLocEnd()));
+
+  SuggestParentheses(Self, OpLoc,
+    Self.PDiag(diag::note_precedence_conditional_first),
+    SourceRange(CondRHS->getLocStart(), RHSExpr->getLocEnd()));
+}
+
+/// ActOnConditionalOp - Parse a ?: operation.  Note that 'LHS' may be null
+/// in the case of a the GNU conditional expr extension.
+ExprResult Sema::ActOnConditionalOp(SourceLocation QuestionLoc,
+                                    SourceLocation ColonLoc,
+                                    Expr *CondExpr, Expr *LHSExpr,
+                                    Expr *RHSExpr) {
+  // If this is the gnu "x ?: y" extension, analyze the types as though the LHS
+  // was the condition.
+  OpaqueValueExpr *opaqueValue = 0;
+  Expr *commonExpr = 0;
+  if (LHSExpr == 0) {
+    commonExpr = CondExpr;
+
+    // We usually want to apply unary conversions *before* saving, except
+    // in the special case of a C++ l-value conditional.
+    if (!(getLangOpts().CPlusPlus
+          && !commonExpr->isTypeDependent()
+          && commonExpr->getValueKind() == RHSExpr->getValueKind()
+          && commonExpr->isGLValue()
+          && commonExpr->isOrdinaryOrBitFieldObject()
+          && RHSExpr->isOrdinaryOrBitFieldObject()
+          && Context.hasSameType(commonExpr->getType(), RHSExpr->getType()))) {
+      ExprResult commonRes = UsualUnaryConversions(commonExpr);
+      if (commonRes.isInvalid())
+        return ExprError();
+      commonExpr = commonRes.take();
+    }
+
+    opaqueValue = new (Context) OpaqueValueExpr(commonExpr->getExprLoc(),
+                                                commonExpr->getType(),
+                                                commonExpr->getValueKind(),
+                                                commonExpr->getObjectKind(),
+                                                commonExpr);
+    LHSExpr = CondExpr = opaqueValue;
+  }
+
+  ExprValueKind VK = VK_RValue;
+  ExprObjectKind OK = OK_Ordinary;
+  ExprResult Cond = Owned(CondExpr), LHS = Owned(LHSExpr), RHS = Owned(RHSExpr);
+  QualType result = CheckConditionalOperands(Cond, LHS, RHS, 
+                                             VK, OK, QuestionLoc);
+  if (result.isNull() || Cond.isInvalid() || LHS.isInvalid() ||
+      RHS.isInvalid())
+    return ExprError();
+
+  DiagnoseConditionalPrecedence(*this, QuestionLoc, Cond.get(), LHS.get(),
+                                RHS.get());
+
+  if (!commonExpr)
+    return Owned(new (Context) ConditionalOperator(Cond.take(), QuestionLoc,
+                                                   LHS.take(), ColonLoc, 
+                                                   RHS.take(), result, VK, OK));
+
+  return Owned(new (Context)
+    BinaryConditionalOperator(commonExpr, opaqueValue, Cond.take(), LHS.take(),
+                              RHS.take(), QuestionLoc, ColonLoc, result, VK,
+                              OK));
+}
+
+// checkPointerTypesForAssignment - This is a very tricky routine (despite
+// being closely modeled after the C99 spec:-). The odd characteristic of this
+// routine is it effectively iqnores the qualifiers on the top level pointee.
+// This circumvents the usual type rules specified in 6.2.7p1 & 6.7.5.[1-3].
+// FIXME: add a couple examples in this comment.
+static Sema::AssignConvertType
+checkPointerTypesForAssignment(Sema &S, QualType LHSType, QualType RHSType) {
+  assert(LHSType.isCanonical() && "LHS not canonicalized!");
+  assert(RHSType.isCanonical() && "RHS not canonicalized!");
+
+  // get the "pointed to" type (ignoring qualifiers at the top level)
+  const Type *lhptee, *rhptee;
+  Qualifiers lhq, rhq;
+  llvm::tie(lhptee, lhq) = cast<PointerType>(LHSType)->getPointeeType().split();
+  llvm::tie(rhptee, rhq) = cast<PointerType>(RHSType)->getPointeeType().split();
+
+  Sema::AssignConvertType ConvTy = Sema::Compatible;
+
+  // C99 6.5.16.1p1: This following citation is common to constraints
+  // 3 & 4 (below). ...and the type *pointed to* by the left has all the
+  // qualifiers of the type *pointed to* by the right;
+  Qualifiers lq;
+
+  // As a special case, 'non-__weak A *' -> 'non-__weak const *' is okay.
+  if (lhq.getObjCLifetime() != rhq.getObjCLifetime() &&
+      lhq.compatiblyIncludesObjCLifetime(rhq)) {
+    // Ignore lifetime for further calculation.
+    lhq.removeObjCLifetime();
+    rhq.removeObjCLifetime();
+  }
+
+  if (!lhq.compatiblyIncludes(rhq)) {
+    // Treat address-space mismatches as fatal.  TODO: address subspaces
+    if (lhq.getAddressSpace() != rhq.getAddressSpace())
+      ConvTy = Sema::IncompatiblePointerDiscardsQualifiers;
+
+    // It's okay to add or remove GC or lifetime qualifiers when converting to
+    // and from void*.
+    else if (lhq.withoutObjCGCAttr().withoutObjCLifetime()
+                        .compatiblyIncludes(
+                                rhq.withoutObjCGCAttr().withoutObjCLifetime())
+             && (lhptee->isVoidType() || rhptee->isVoidType()))
+      ; // keep old
+
+    // Treat lifetime mismatches as fatal.
+    else if (lhq.getObjCLifetime() != rhq.getObjCLifetime())
+      ConvTy = Sema::IncompatiblePointerDiscardsQualifiers;
+    
+    // For GCC compatibility, other qualifier mismatches are treated
+    // as still compatible in C.
+    else ConvTy = Sema::CompatiblePointerDiscardsQualifiers;
+  }
+
+  // C99 6.5.16.1p1 (constraint 4): If one operand is a pointer to an object or
+  // incomplete type and the other is a pointer to a qualified or unqualified
+  // version of void...
+  if (lhptee->isVoidType()) {
+    if (rhptee->isIncompleteOrObjectType())
+      return ConvTy;
+
+    // As an extension, we allow cast to/from void* to function pointer.
+    assert(rhptee->isFunctionType());
+    return Sema::FunctionVoidPointer;
+  }
+
+  if (rhptee->isVoidType()) {
+    if (lhptee->isIncompleteOrObjectType())
+      return ConvTy;
+
+    // As an extension, we allow cast to/from void* to function pointer.
+    assert(lhptee->isFunctionType());
+    return Sema::FunctionVoidPointer;
+  }
+
+  // C99 6.5.16.1p1 (constraint 3): both operands are pointers to qualified or
+  // unqualified versions of compatible types, ...
+  QualType ltrans = QualType(lhptee, 0), rtrans = QualType(rhptee, 0);
+  if (!S.Context.typesAreCompatible(ltrans, rtrans)) {
+    // Check if the pointee types are compatible ignoring the sign.
+    // We explicitly check for char so that we catch "char" vs
+    // "unsigned char" on systems where "char" is unsigned.
+    if (lhptee->isCharType())
+      ltrans = S.Context.UnsignedCharTy;
+    else if (lhptee->hasSignedIntegerRepresentation())
+      ltrans = S.Context.getCorrespondingUnsignedType(ltrans);
+
+    if (rhptee->isCharType())
+      rtrans = S.Context.UnsignedCharTy;
+    else if (rhptee->hasSignedIntegerRepresentation())
+      rtrans = S.Context.getCorrespondingUnsignedType(rtrans);
+
+    if (ltrans == rtrans) {
+      // Types are compatible ignoring the sign. Qualifier incompatibility
+      // takes priority over sign incompatibility because the sign
+      // warning can be disabled.
+      if (ConvTy != Sema::Compatible)
+        return ConvTy;
+
+      return Sema::IncompatiblePointerSign;
+    }
+
+    // If we are a multi-level pointer, it's possible that our issue is simply
+    // one of qualification - e.g. char ** -> const char ** is not allowed. If
+    // the eventual target type is the same and the pointers have the same
+    // level of indirection, this must be the issue.
+    if (isa<PointerType>(lhptee) && isa<PointerType>(rhptee)) {
+      do {
+        lhptee = cast<PointerType>(lhptee)->getPointeeType().getTypePtr();
+        rhptee = cast<PointerType>(rhptee)->getPointeeType().getTypePtr();
+      } while (isa<PointerType>(lhptee) && isa<PointerType>(rhptee));
+
+      if (lhptee == rhptee)
+        return Sema::IncompatibleNestedPointerQualifiers;
+    }
+
+    // General pointer incompatibility takes priority over qualifiers.
+    return Sema::IncompatiblePointer;
+  }
+  if (!S.getLangOpts().CPlusPlus &&
+      S.IsNoReturnConversion(ltrans, rtrans, ltrans))
+    return Sema::IncompatiblePointer;
+  return ConvTy;
+}
+
+/// checkBlockPointerTypesForAssignment - This routine determines whether two
+/// block pointer types are compatible or whether a block and normal pointer
+/// are compatible. It is more restrict than comparing two function pointer
+// types.
+static Sema::AssignConvertType
+checkBlockPointerTypesForAssignment(Sema &S, QualType LHSType,
+                                    QualType RHSType) {
+  assert(LHSType.isCanonical() && "LHS not canonicalized!");
+  assert(RHSType.isCanonical() && "RHS not canonicalized!");
+
+  QualType lhptee, rhptee;
+
+  // get the "pointed to" type (ignoring qualifiers at the top level)
+  lhptee = cast<BlockPointerType>(LHSType)->getPointeeType();
+  rhptee = cast<BlockPointerType>(RHSType)->getPointeeType();
+
+  // In C++, the types have to match exactly.
+  if (S.getLangOpts().CPlusPlus)
+    return Sema::IncompatibleBlockPointer;
+
+  Sema::AssignConvertType ConvTy = Sema::Compatible;
+
+  // For blocks we enforce that qualifiers are identical.
+  if (lhptee.getLocalQualifiers() != rhptee.getLocalQualifiers())
+    ConvTy = Sema::CompatiblePointerDiscardsQualifiers;
+
+  if (!S.Context.typesAreBlockPointerCompatible(LHSType, RHSType))
+    return Sema::IncompatibleBlockPointer;
+
+  return ConvTy;
+}
+
+/// checkObjCPointerTypesForAssignment - Compares two objective-c pointer types
+/// for assignment compatibility.
+static Sema::AssignConvertType
+checkObjCPointerTypesForAssignment(Sema &S, QualType LHSType,
+                                   QualType RHSType) {
+  assert(LHSType.isCanonical() && "LHS was not canonicalized!");
+  assert(RHSType.isCanonical() && "RHS was not canonicalized!");
+
+  if (LHSType->isObjCBuiltinType()) {
+    // Class is not compatible with ObjC object pointers.
+    if (LHSType->isObjCClassType() && !RHSType->isObjCBuiltinType() &&
+        !RHSType->isObjCQualifiedClassType())
+      return Sema::IncompatiblePointer;
+    return Sema::Compatible;
+  }
+  if (RHSType->isObjCBuiltinType()) {
+    if (RHSType->isObjCClassType() && !LHSType->isObjCBuiltinType() &&
+        !LHSType->isObjCQualifiedClassType())
+      return Sema::IncompatiblePointer;
+    return Sema::Compatible;
+  }
+  QualType lhptee = LHSType->getAs<ObjCObjectPointerType>()->getPointeeType();
+  QualType rhptee = RHSType->getAs<ObjCObjectPointerType>()->getPointeeType();
+
+  if (!lhptee.isAtLeastAsQualifiedAs(rhptee) &&
+      // make an exception for id<P>
+      !LHSType->isObjCQualifiedIdType())
+    return Sema::CompatiblePointerDiscardsQualifiers;
+
+  if (S.Context.typesAreCompatible(LHSType, RHSType))
+    return Sema::Compatible;
+  if (LHSType->isObjCQualifiedIdType() || RHSType->isObjCQualifiedIdType())
+    return Sema::IncompatibleObjCQualifiedId;
+  return Sema::IncompatiblePointer;
+}
+
+Sema::AssignConvertType
+Sema::CheckAssignmentConstraints(SourceLocation Loc,
+                                 QualType LHSType, QualType RHSType) {
+  // Fake up an opaque expression.  We don't actually care about what
+  // cast operations are required, so if CheckAssignmentConstraints
+  // adds casts to this they'll be wasted, but fortunately that doesn't
+  // usually happen on valid code.
+  OpaqueValueExpr RHSExpr(Loc, RHSType, VK_RValue);
+  ExprResult RHSPtr = &RHSExpr;
+  CastKind K = CK_Invalid;
+
+  return CheckAssignmentConstraints(LHSType, RHSPtr, K);
+}
+
+/// CheckAssignmentConstraints (C99 6.5.16) - This routine currently
+/// has code to accommodate several GCC extensions when type checking
+/// pointers. Here are some objectionable examples that GCC considers warnings:
+///
+///  int a, *pint;
+///  short *pshort;
+///  struct foo *pfoo;
+///
+///  pint = pshort; // warning: assignment from incompatible pointer type
+///  a = pint; // warning: assignment makes integer from pointer without a cast
+///  pint = a; // warning: assignment makes pointer from integer without a cast
+///  pint = pfoo; // warning: assignment from incompatible pointer type
+///
+/// As a result, the code for dealing with pointers is more complex than the
+/// C99 spec dictates.
+///
+/// Sets 'Kind' for any result kind except Incompatible.
+Sema::AssignConvertType
+Sema::CheckAssignmentConstraints(QualType LHSType, ExprResult &RHS,
+                                 CastKind &Kind) {
+  QualType RHSType = RHS.get()->getType();
+  QualType OrigLHSType = LHSType;
+
+  // Get canonical types.  We're not formatting these types, just comparing
+  // them.
+  LHSType = Context.getCanonicalType(LHSType).getUnqualifiedType();
+  RHSType = Context.getCanonicalType(RHSType).getUnqualifiedType();
+
+
+  // Common case: no conversion required.
+  if (LHSType == RHSType) {
+    Kind = CK_NoOp;
+    return Compatible;
+  }
+
+  if (const AtomicType *AtomicTy = dyn_cast<AtomicType>(LHSType)) {
+    if (AtomicTy->getValueType() == RHSType) {
+      Kind = CK_NonAtomicToAtomic;
+      return Compatible;
+    }
+  }
+
+  if (const AtomicType *AtomicTy = dyn_cast<AtomicType>(RHSType)) {
+    if (AtomicTy->getValueType() == LHSType) {
+      Kind = CK_AtomicToNonAtomic;
+      return Compatible;
+    }
+  }
+
+
+  // If the left-hand side is a reference type, then we are in a
+  // (rare!) case where we've allowed the use of references in C,
+  // e.g., as a parameter type in a built-in function. In this case,
+  // just make sure that the type referenced is compatible with the
+  // right-hand side type. The caller is responsible for adjusting
+  // LHSType so that the resulting expression does not have reference
+  // type.
+  if (const ReferenceType *LHSTypeRef = LHSType->getAs<ReferenceType>()) {
+    if (Context.typesAreCompatible(LHSTypeRef->getPointeeType(), RHSType)) {
+      Kind = CK_LValueBitCast;
+      return Compatible;
+    }
+    return Incompatible;
+  }
+
+  // Allow scalar to ExtVector assignments, and assignments of an ExtVector type
+  // to the same ExtVector type.
+  if (LHSType->isExtVectorType()) {
+    if (RHSType->isExtVectorType())
+      return Incompatible;
+    if (RHSType->isArithmeticType()) {
+      // CK_VectorSplat does T -> vector T, so first cast to the
+      // element type.
+      QualType elType = cast<ExtVectorType>(LHSType)->getElementType();
+      if (elType != RHSType) {
+        Kind = PrepareScalarCast(RHS, elType);
+        RHS = ImpCastExprToType(RHS.take(), elType, Kind);
+      }
+      Kind = CK_VectorSplat;
+      return Compatible;
+    }
+  }
+
+  // Conversions to or from vector type.
+  if (LHSType->isVectorType() || RHSType->isVectorType()) {
+    if (LHSType->isVectorType() && RHSType->isVectorType()) {
+      // Allow assignments of an AltiVec vector type to an equivalent GCC
+      // vector type and vice versa
+      if (Context.areCompatibleVectorTypes(LHSType, RHSType)) {
+        Kind = CK_BitCast;
+        return Compatible;
+      }
+
+      // If we are allowing lax vector conversions, and LHS and RHS are both
+      // vectors, the total size only needs to be the same. This is a bitcast;
+      // no bits are changed but the result type is different.
+      if (getLangOpts().LaxVectorConversions &&
+          (Context.getTypeSize(LHSType) == Context.getTypeSize(RHSType))) {
+        Kind = CK_BitCast;
+        return IncompatibleVectors;
+      }
+    }
+    return Incompatible;
+  }
+
+  // Arithmetic conversions.
+  if (LHSType->isArithmeticType() && RHSType->isArithmeticType() &&
+      !(getLangOpts().CPlusPlus && LHSType->isEnumeralType())) {
+    Kind = PrepareScalarCast(RHS, LHSType);
+    return Compatible;
+  }
+
+  // Conversions to normal pointers.
+  if (const PointerType *LHSPointer = dyn_cast<PointerType>(LHSType)) {
+    // U* -> T*
+    if (isa<PointerType>(RHSType)) {
+      Kind = CK_BitCast;
+      return checkPointerTypesForAssignment(*this, LHSType, RHSType);
+    }
+
+    // int -> T*
+    if (RHSType->isIntegerType()) {
+      Kind = CK_IntegralToPointer; // FIXME: null?
+      return IntToPointer;
+    }
+
+    // C pointers are not compatible with ObjC object pointers,
+    // with two exceptions:
+    if (isa<ObjCObjectPointerType>(RHSType)) {
+      //  - conversions to void*
+      if (LHSPointer->getPointeeType()->isVoidType()) {
+        Kind = CK_BitCast;
+        return Compatible;
+      }
+
+      //  - conversions from 'Class' to the redefinition type
+      if (RHSType->isObjCClassType() &&
+          Context.hasSameType(LHSType, 
+                              Context.getObjCClassRedefinitionType())) {
+        Kind = CK_BitCast;
+        return Compatible;
+      }
+
+      Kind = CK_BitCast;
+      return IncompatiblePointer;
+    }
+
+    // U^ -> void*
+    if (RHSType->getAs<BlockPointerType>()) {
+      if (LHSPointer->getPointeeType()->isVoidType()) {
+        Kind = CK_BitCast;
+        return Compatible;
+      }
+    }
+
+    return Incompatible;
+  }
+
+  // Conversions to block pointers.
+  if (isa<BlockPointerType>(LHSType)) {
+    // U^ -> T^
+    if (RHSType->isBlockPointerType()) {
+      Kind = CK_BitCast;
+      return checkBlockPointerTypesForAssignment(*this, LHSType, RHSType);
+    }
+
+    // int or null -> T^
+    if (RHSType->isIntegerType()) {
+      Kind = CK_IntegralToPointer; // FIXME: null
+      return IntToBlockPointer;
+    }
+
+    // id -> T^
+    if (getLangOpts().ObjC1 && RHSType->isObjCIdType()) {
+      Kind = CK_AnyPointerToBlockPointerCast;
+      return Compatible;
+    }
+
+    // void* -> T^
+    if (const PointerType *RHSPT = RHSType->getAs<PointerType>())
+      if (RHSPT->getPointeeType()->isVoidType()) {
+        Kind = CK_AnyPointerToBlockPointerCast;
+        return Compatible;
+      }
+
+    return Incompatible;
+  }
+
+  // Conversions to Objective-C pointers.
+  if (isa<ObjCObjectPointerType>(LHSType)) {
+    // A* -> B*
+    if (RHSType->isObjCObjectPointerType()) {
+      Kind = CK_BitCast;
+      Sema::AssignConvertType result = 
+        checkObjCPointerTypesForAssignment(*this, LHSType, RHSType);
+      if (getLangOpts().ObjCAutoRefCount &&
+          result == Compatible && 
+          !CheckObjCARCUnavailableWeakConversion(OrigLHSType, RHSType))
+        result = IncompatibleObjCWeakRef;
+      return result;
+    }
+
+    // int or null -> A*
+    if (RHSType->isIntegerType()) {
+      Kind = CK_IntegralToPointer; // FIXME: null
+      return IntToPointer;
+    }
+
+    // In general, C pointers are not compatible with ObjC object pointers,
+    // with two exceptions:
+    if (isa<PointerType>(RHSType)) {
+      Kind = CK_CPointerToObjCPointerCast;
+
+      //  - conversions from 'void*'
+      if (RHSType->isVoidPointerType()) {
+        return Compatible;
+      }
+
+      //  - conversions to 'Class' from its redefinition type
+      if (LHSType->isObjCClassType() &&
+          Context.hasSameType(RHSType, 
+                              Context.getObjCClassRedefinitionType())) {
+        return Compatible;
+      }
+
+      return IncompatiblePointer;
+    }
+
+    // T^ -> A*
+    if (RHSType->isBlockPointerType()) {
+      maybeExtendBlockObject(*this, RHS);
+      Kind = CK_BlockPointerToObjCPointerCast;
+      return Compatible;
+    }
+
+    return Incompatible;
+  }
+
+  // Conversions from pointers that are not covered by the above.
+  if (isa<PointerType>(RHSType)) {
+    // T* -> _Bool
+    if (LHSType == Context.BoolTy) {
+      Kind = CK_PointerToBoolean;
+      return Compatible;
+    }
+
+    // T* -> int
+    if (LHSType->isIntegerType()) {
+      Kind = CK_PointerToIntegral;
+      return PointerToInt;
+    }
+
+    return Incompatible;
+  }
+
+  // Conversions from Objective-C pointers that are not covered by the above.
+  if (isa<ObjCObjectPointerType>(RHSType)) {
+    // T* -> _Bool
+    if (LHSType == Context.BoolTy) {
+      Kind = CK_PointerToBoolean;
+      return Compatible;
+    }
+
+    // T* -> int
+    if (LHSType->isIntegerType()) {
+      Kind = CK_PointerToIntegral;
+      return PointerToInt;
+    }
+
+    return Incompatible;
+  }
+
+  // struct A -> struct B
+  if (isa<TagType>(LHSType) && isa<TagType>(RHSType)) {
+    if (Context.typesAreCompatible(LHSType, RHSType)) {
+      Kind = CK_NoOp;
+      return Compatible;
+    }
+  }
+
+  return Incompatible;
+}
+
+/// \brief Constructs a transparent union from an expression that is
+/// used to initialize the transparent union.
+static void ConstructTransparentUnion(Sema &S, ASTContext &C,
+                                      ExprResult &EResult, QualType UnionType,
+                                      FieldDecl *Field) {
+  // Build an initializer list that designates the appropriate member
+  // of the transparent union.
+  Expr *E = EResult.take();
+  InitListExpr *Initializer = new (C) InitListExpr(C, SourceLocation(),
+                                                   &E, 1,
+                                                   SourceLocation());
+  Initializer->setType(UnionType);
+  Initializer->setInitializedFieldInUnion(Field);
+
+  // Build a compound literal constructing a value of the transparent
+  // union type from this initializer list.
+  TypeSourceInfo *unionTInfo = C.getTrivialTypeSourceInfo(UnionType);
+  EResult = S.Owned(
+    new (C) CompoundLiteralExpr(SourceLocation(), unionTInfo, UnionType,
+                                VK_RValue, Initializer, false));
+}
+
+Sema::AssignConvertType
+Sema::CheckTransparentUnionArgumentConstraints(QualType ArgType,
+                                               ExprResult &RHS) {
+  QualType RHSType = RHS.get()->getType();
+
+  // If the ArgType is a Union type, we want to handle a potential
+  // transparent_union GCC extension.
+  const RecordType *UT = ArgType->getAsUnionType();
+  if (!UT || !UT->getDecl()->hasAttr<TransparentUnionAttr>())
+    return Incompatible;
+
+  // The field to initialize within the transparent union.
+  RecordDecl *UD = UT->getDecl();
+  FieldDecl *InitField = 0;
+  // It's compatible if the expression matches any of the fields.
+  for (RecordDecl::field_iterator it = UD->field_begin(),
+         itend = UD->field_end();
+       it != itend; ++it) {
+    if (it->getType()->isPointerType()) {
+      // If the transparent union contains a pointer type, we allow:
+      // 1) void pointer
+      // 2) null pointer constant
+      if (RHSType->isPointerType())
+        if (RHSType->castAs<PointerType>()->getPointeeType()->isVoidType()) {
+          RHS = ImpCastExprToType(RHS.take(), it->getType(), CK_BitCast);
+          InitField = *it;
+          break;
+        }
+
+      if (RHS.get()->isNullPointerConstant(Context,
+                                           Expr::NPC_ValueDependentIsNull)) {
+        RHS = ImpCastExprToType(RHS.take(), it->getType(),
+                                CK_NullToPointer);
+        InitField = *it;
+        break;
+      }
+    }
+
+    CastKind Kind = CK_Invalid;
+    if (CheckAssignmentConstraints(it->getType(), RHS, Kind)
+          == Compatible) {
+      RHS = ImpCastExprToType(RHS.take(), it->getType(), Kind);
+      InitField = *it;
+      break;
+    }
+  }
+
+  if (!InitField)
+    return Incompatible;
+
+  ConstructTransparentUnion(*this, Context, RHS, ArgType, InitField);
+  return Compatible;
+}
+
+Sema::AssignConvertType
+Sema::CheckSingleAssignmentConstraints(QualType LHSType, ExprResult &RHS,
+                                       bool Diagnose) {
+  if (getLangOpts().CPlusPlus) {
+    if (!LHSType->isRecordType() && !LHSType->isAtomicType()) {
+      // C++ 5.17p3: If the left operand is not of class type, the
+      // expression is implicitly converted (C++ 4) to the
+      // cv-unqualified type of the left operand.
+      ExprResult Res;
+      if (Diagnose) {
+        Res = PerformImplicitConversion(RHS.get(), LHSType.getUnqualifiedType(),
+                                        AA_Assigning);
+      } else {
+        ImplicitConversionSequence ICS =
+            TryImplicitConversion(RHS.get(), LHSType.getUnqualifiedType(),
+                                  /*SuppressUserConversions=*/false,
+                                  /*AllowExplicit=*/false,
+                                  /*InOverloadResolution=*/false,
+                                  /*CStyle=*/false,
+                                  /*AllowObjCWritebackConversion=*/false);
+        if (ICS.isFailure())
+          return Incompatible;
+        Res = PerformImplicitConversion(RHS.get(), LHSType.getUnqualifiedType(),
+                                        ICS, AA_Assigning);
+      }
+      if (Res.isInvalid())
+        return Incompatible;
+      Sema::AssignConvertType result = Compatible;
+      if (getLangOpts().ObjCAutoRefCount &&
+          !CheckObjCARCUnavailableWeakConversion(LHSType,
+                                                 RHS.get()->getType()))
+        result = IncompatibleObjCWeakRef;
+      RHS = move(Res);
+      return result;
+    }
+
+    // FIXME: Currently, we fall through and treat C++ classes like C
+    // structures.
+    // FIXME: We also fall through for atomics; not sure what should
+    // happen there, though.
+  }
+
+  // C99 6.5.16.1p1: the left operand is a pointer and the right is
+  // a null pointer constant.
+  if ((LHSType->isPointerType() ||
+       LHSType->isObjCObjectPointerType() ||
+       LHSType->isBlockPointerType())
+      && RHS.get()->isNullPointerConstant(Context,
+                                          Expr::NPC_ValueDependentIsNull)) {
+    RHS = ImpCastExprToType(RHS.take(), LHSType, CK_NullToPointer);
+    return Compatible;
+  }
+
+  // This check seems unnatural, however it is necessary to ensure the proper
+  // conversion of functions/arrays. If the conversion were done for all
+  // DeclExpr's (created by ActOnIdExpression), it would mess up the unary
+  // expressions that suppress this implicit conversion (&, sizeof).
+  //
+  // Suppress this for references: C++ 8.5.3p5.
+  if (!LHSType->isReferenceType()) {
+    RHS = DefaultFunctionArrayLvalueConversion(RHS.take());
+    if (RHS.isInvalid())
+      return Incompatible;
+  }
+
+  CastKind Kind = CK_Invalid;
+  Sema::AssignConvertType result =
+    CheckAssignmentConstraints(LHSType, RHS, Kind);
+
+  // C99 6.5.16.1p2: The value of the right operand is converted to the
+  // type of the assignment expression.
+  // CheckAssignmentConstraints allows the left-hand side to be a reference,
+  // so that we can use references in built-in functions even in C.
+  // The getNonReferenceType() call makes sure that the resulting expression
+  // does not have reference type.
+  if (result != Incompatible && RHS.get()->getType() != LHSType)
+    RHS = ImpCastExprToType(RHS.take(),
+                            LHSType.getNonLValueExprType(Context), Kind);
+  return result;
+}
+
+QualType Sema::InvalidOperands(SourceLocation Loc, ExprResult &LHS,
+                               ExprResult &RHS) {
+  Diag(Loc, diag::err_typecheck_invalid_operands)
+    << LHS.get()->getType() << RHS.get()->getType()
+    << LHS.get()->getSourceRange() << RHS.get()->getSourceRange();
+  return QualType();
+}
+
+QualType Sema::CheckVectorOperands(ExprResult &LHS, ExprResult &RHS,
+                                   SourceLocation Loc, bool IsCompAssign) {
+  if (!IsCompAssign) {
+    LHS = DefaultFunctionArrayLvalueConversion(LHS.take());
+    if (LHS.isInvalid())
+      return QualType();
+  }
+  RHS = DefaultFunctionArrayLvalueConversion(RHS.take());
+  if (RHS.isInvalid())
+    return QualType();
+
+  // For conversion purposes, we ignore any qualifiers.
+  // For example, "const float" and "float" are equivalent.
+  QualType LHSType =
+    Context.getCanonicalType(LHS.get()->getType()).getUnqualifiedType();
+  QualType RHSType =
+    Context.getCanonicalType(RHS.get()->getType()).getUnqualifiedType();
+
+  // If the vector types are identical, return.
+  if (LHSType == RHSType)
+    return LHSType;
+
+  // Handle the case of equivalent AltiVec and GCC vector types
+  if (LHSType->isVectorType() && RHSType->isVectorType() &&
+      Context.areCompatibleVectorTypes(LHSType, RHSType)) {
+    if (LHSType->isExtVectorType()) {
+      RHS = ImpCastExprToType(RHS.take(), LHSType, CK_BitCast);
+      return LHSType;
+    }
+
+    if (!IsCompAssign)
+      LHS = ImpCastExprToType(LHS.take(), RHSType, CK_BitCast);
+    return RHSType;
+  }
+
+  if (getLangOpts().LaxVectorConversions &&
+      Context.getTypeSize(LHSType) == Context.getTypeSize(RHSType)) {
+    // If we are allowing lax vector conversions, and LHS and RHS are both
+    // vectors, the total size only needs to be the same. This is a
+    // bitcast; no bits are changed but the result type is different.
+    // FIXME: Should we really be allowing this?
+    RHS = ImpCastExprToType(RHS.take(), LHSType, CK_BitCast);
+    return LHSType;
+  }
+
+  // Canonicalize the ExtVector to the LHS, remember if we swapped so we can
+  // swap back (so that we don't reverse the inputs to a subtract, for instance.
+  bool swapped = false;
+  if (RHSType->isExtVectorType() && !IsCompAssign) {
+    swapped = true;
+    std::swap(RHS, LHS);
+    std::swap(RHSType, LHSType);
+  }
+
+  // Handle the case of an ext vector and scalar.
+  if (const ExtVectorType *LV = LHSType->getAs<ExtVectorType>()) {
+    QualType EltTy = LV->getElementType();
+    if (EltTy->isIntegralType(Context) && RHSType->isIntegralType(Context)) {
+      int order = Context.getIntegerTypeOrder(EltTy, RHSType);
+      if (order > 0)
+        RHS = ImpCastExprToType(RHS.take(), EltTy, CK_IntegralCast);
+      if (order >= 0) {
+        RHS = ImpCastExprToType(RHS.take(), LHSType, CK_VectorSplat);
+        if (swapped) std::swap(RHS, LHS);
+        return LHSType;
+      }
+    }
+    if (EltTy->isRealFloatingType() && RHSType->isScalarType() &&
+        RHSType->isRealFloatingType()) {
+      int order = Context.getFloatingTypeOrder(EltTy, RHSType);
+      if (order > 0)
+        RHS = ImpCastExprToType(RHS.take(), EltTy, CK_FloatingCast);
+      if (order >= 0) {
+        RHS = ImpCastExprToType(RHS.take(), LHSType, CK_VectorSplat);
+        if (swapped) std::swap(RHS, LHS);
+        return LHSType;
+      }
+    }
+  }
+
+  // Vectors of different size or scalar and non-ext-vector are errors.
+  if (swapped) std::swap(RHS, LHS);
+  Diag(Loc, diag::err_typecheck_vector_not_convertable)
+    << LHS.get()->getType() << RHS.get()->getType()
+    << LHS.get()->getSourceRange() << RHS.get()->getSourceRange();
+  return QualType();
+}
+
+// checkArithmeticNull - Detect when a NULL constant is used improperly in an
+// expression.  These are mainly cases where the null pointer is used as an
+// integer instead of a pointer.
+static void checkArithmeticNull(Sema &S, ExprResult &LHS, ExprResult &RHS,
+                                SourceLocation Loc, bool IsCompare) {
+  // The canonical way to check for a GNU null is with isNullPointerConstant,
+  // but we use a bit of a hack here for speed; this is a relatively
+  // hot path, and isNullPointerConstant is slow.
+  bool LHSNull = isa<GNUNullExpr>(LHS.get()->IgnoreParenImpCasts());
+  bool RHSNull = isa<GNUNullExpr>(RHS.get()->IgnoreParenImpCasts());
+
+  QualType NonNullType = LHSNull ? RHS.get()->getType() : LHS.get()->getType();
+
+  // Avoid analyzing cases where the result will either be invalid (and
+  // diagnosed as such) or entirely valid and not something to warn about.
+  if ((!LHSNull && !RHSNull) || NonNullType->isBlockPointerType() ||
+      NonNullType->isMemberPointerType() || NonNullType->isFunctionType())
+    return;
+
+  // Comparison operations would not make sense with a null pointer no matter
+  // what the other expression is.
+  if (!IsCompare) {
+    S.Diag(Loc, diag::warn_null_in_arithmetic_operation)
+        << (LHSNull ? LHS.get()->getSourceRange() : SourceRange())
+        << (RHSNull ? RHS.get()->getSourceRange() : SourceRange());
+    return;
+  }
+
+  // The rest of the operations only make sense with a null pointer
+  // if the other expression is a pointer.
+  if (LHSNull == RHSNull || NonNullType->isAnyPointerType() ||
+      NonNullType->canDecayToPointerType())
+    return;
+
+  S.Diag(Loc, diag::warn_null_in_comparison_operation)
+      << LHSNull /* LHS is NULL */ << NonNullType
+      << LHS.get()->getSourceRange() << RHS.get()->getSourceRange();
+}
+
+QualType Sema::CheckMultiplyDivideOperands(ExprResult &LHS, ExprResult &RHS,
+                                           SourceLocation Loc,
+                                           bool IsCompAssign, bool IsDiv) {
+  checkArithmeticNull(*this, LHS, RHS, Loc, /*isCompare=*/false);
+
+  if (LHS.get()->getType()->isVectorType() ||
+      RHS.get()->getType()->isVectorType())
+    return CheckVectorOperands(LHS, RHS, Loc, IsCompAssign);
+
+  QualType compType = UsualArithmeticConversions(LHS, RHS, IsCompAssign);
+  if (LHS.isInvalid() || RHS.isInvalid())
+    return QualType();
+
+
+  if (!LHS.get()->getType()->isArithmeticType() ||
+      !RHS.get()->getType()->isArithmeticType()) {
+    if (IsCompAssign &&
+        LHS.get()->getType()->isAtomicType() &&
+        RHS.get()->getType()->isArithmeticType())
+      return compType;
+    return InvalidOperands(Loc, LHS, RHS);
+  }
+
+  // Check for division by zero.
+  if (IsDiv &&
+      RHS.get()->isNullPointerConstant(Context,
+                                       Expr::NPC_ValueDependentIsNotNull))
+    DiagRuntimeBehavior(Loc, RHS.get(), PDiag(diag::warn_division_by_zero)
+                                          << RHS.get()->getSourceRange());
+
+  return compType;
+}
+
+QualType Sema::CheckRemainderOperands(
+  ExprResult &LHS, ExprResult &RHS, SourceLocation Loc, bool IsCompAssign) {
+  checkArithmeticNull(*this, LHS, RHS, Loc, /*isCompare=*/false);
+
+  if (LHS.get()->getType()->isVectorType() ||
+      RHS.get()->getType()->isVectorType()) {
+    if (LHS.get()->getType()->hasIntegerRepresentation() && 
+        RHS.get()->getType()->hasIntegerRepresentation())
+      return CheckVectorOperands(LHS, RHS, Loc, IsCompAssign);
+    return InvalidOperands(Loc, LHS, RHS);
+  }
+
+  QualType compType = UsualArithmeticConversions(LHS, RHS, IsCompAssign);
+  if (LHS.isInvalid() || RHS.isInvalid())
+    return QualType();
+
+  if (!LHS.get()->getType()->isIntegerType() ||
+      !RHS.get()->getType()->isIntegerType())
+    return InvalidOperands(Loc, LHS, RHS);
+
+  // Check for remainder by zero.
+  if (RHS.get()->isNullPointerConstant(Context,
+                                       Expr::NPC_ValueDependentIsNotNull))
+    DiagRuntimeBehavior(Loc, RHS.get(), PDiag(diag::warn_remainder_by_zero)
+                                 << RHS.get()->getSourceRange());
+
+  return compType;
+}
+
+/// \brief Diagnose invalid arithmetic on two void pointers.
+static void diagnoseArithmeticOnTwoVoidPointers(Sema &S, SourceLocation Loc,
+                                                Expr *LHSExpr, Expr *RHSExpr) {
+  S.Diag(Loc, S.getLangOpts().CPlusPlus
+                ? diag::err_typecheck_pointer_arith_void_type
+                : diag::ext_gnu_void_ptr)
+    << 1 /* two pointers */ << LHSExpr->getSourceRange()
+                            << RHSExpr->getSourceRange();
+}
+
+/// \brief Diagnose invalid arithmetic on a void pointer.
+static void diagnoseArithmeticOnVoidPointer(Sema &S, SourceLocation Loc,
+                                            Expr *Pointer) {
+  S.Diag(Loc, S.getLangOpts().CPlusPlus
+                ? diag::err_typecheck_pointer_arith_void_type
+                : diag::ext_gnu_void_ptr)
+    << 0 /* one pointer */ << Pointer->getSourceRange();
+}
+
+/// \brief Diagnose invalid arithmetic on two function pointers.
+static void diagnoseArithmeticOnTwoFunctionPointers(Sema &S, SourceLocation Loc,
+                                                    Expr *LHS, Expr *RHS) {
+  assert(LHS->getType()->isAnyPointerType());
+  assert(RHS->getType()->isAnyPointerType());
+  S.Diag(Loc, S.getLangOpts().CPlusPlus
+                ? diag::err_typecheck_pointer_arith_function_type
+                : diag::ext_gnu_ptr_func_arith)
+    << 1 /* two pointers */ << LHS->getType()->getPointeeType()
+    // We only show the second type if it differs from the first.
+    << (unsigned)!S.Context.hasSameUnqualifiedType(LHS->getType(),
+                                                   RHS->getType())
+    << RHS->getType()->getPointeeType()
+    << LHS->getSourceRange() << RHS->getSourceRange();
+}
+
+/// \brief Diagnose invalid arithmetic on a function pointer.
+static void diagnoseArithmeticOnFunctionPointer(Sema &S, SourceLocation Loc,
+                                                Expr *Pointer) {
+  assert(Pointer->getType()->isAnyPointerType());
+  S.Diag(Loc, S.getLangOpts().CPlusPlus
+                ? diag::err_typecheck_pointer_arith_function_type
+                : diag::ext_gnu_ptr_func_arith)
+    << 0 /* one pointer */ << Pointer->getType()->getPointeeType()
+    << 0 /* one pointer, so only one type */
+    << Pointer->getSourceRange();
+}
+
+/// \brief Emit error if Operand is incomplete pointer type
+///
+/// \returns True if pointer has incomplete type
+static bool checkArithmeticIncompletePointerType(Sema &S, SourceLocation Loc,
+                                                 Expr *Operand) {
+  if ((Operand->getType()->isPointerType() &&
+       !Operand->getType()->isDependentType()) ||
+      Operand->getType()->isObjCObjectPointerType()) {
+    QualType PointeeTy = Operand->getType()->getPointeeType();
+    if (S.RequireCompleteType(
+          Loc, PointeeTy,
+          S.PDiag(diag::err_typecheck_arithmetic_incomplete_type)
+            << PointeeTy << Operand->getSourceRange()))
+      return true;
+  }
+  return false;
+}
+
+/// \brief Check the validity of an arithmetic pointer operand.
+///
+/// If the operand has pointer type, this code will check for pointer types
+/// which are invalid in arithmetic operations. These will be diagnosed
+/// appropriately, including whether or not the use is supported as an
+/// extension.
+///
+/// \returns True when the operand is valid to use (even if as an extension).
+static bool checkArithmeticOpPointerOperand(Sema &S, SourceLocation Loc,
+                                            Expr *Operand) {
+  if (!Operand->getType()->isAnyPointerType()) return true;
+
+  QualType PointeeTy = Operand->getType()->getPointeeType();
+  if (PointeeTy->isVoidType()) {
+    diagnoseArithmeticOnVoidPointer(S, Loc, Operand);
+    return !S.getLangOpts().CPlusPlus;
+  }
+  if (PointeeTy->isFunctionType()) {
+    diagnoseArithmeticOnFunctionPointer(S, Loc, Operand);
+    return !S.getLangOpts().CPlusPlus;
+  }
+
+  if (checkArithmeticIncompletePointerType(S, Loc, Operand)) return false;
+
+  return true;
+}
+
+/// \brief Check the validity of a binary arithmetic operation w.r.t. pointer
+/// operands.
+///
+/// This routine will diagnose any invalid arithmetic on pointer operands much
+/// like \see checkArithmeticOpPointerOperand. However, it has special logic
+/// for emitting a single diagnostic even for operations where both LHS and RHS
+/// are (potentially problematic) pointers.
+///
+/// \returns True when the operand is valid to use (even if as an extension).
+static bool checkArithmeticBinOpPointerOperands(Sema &S, SourceLocation Loc,
+                                                Expr *LHSExpr, Expr *RHSExpr) {
+  bool isLHSPointer = LHSExpr->getType()->isAnyPointerType();
+  bool isRHSPointer = RHSExpr->getType()->isAnyPointerType();
+  if (!isLHSPointer && !isRHSPointer) return true;
+
+  QualType LHSPointeeTy, RHSPointeeTy;
+  if (isLHSPointer) LHSPointeeTy = LHSExpr->getType()->getPointeeType();
+  if (isRHSPointer) RHSPointeeTy = RHSExpr->getType()->getPointeeType();
+
+  // Check for arithmetic on pointers to incomplete types.
+  bool isLHSVoidPtr = isLHSPointer && LHSPointeeTy->isVoidType();
+  bool isRHSVoidPtr = isRHSPointer && RHSPointeeTy->isVoidType();
+  if (isLHSVoidPtr || isRHSVoidPtr) {
+    if (!isRHSVoidPtr) diagnoseArithmeticOnVoidPointer(S, Loc, LHSExpr);
+    else if (!isLHSVoidPtr) diagnoseArithmeticOnVoidPointer(S, Loc, RHSExpr);
+    else diagnoseArithmeticOnTwoVoidPointers(S, Loc, LHSExpr, RHSExpr);
+
+    return !S.getLangOpts().CPlusPlus;
+  }
+
+  bool isLHSFuncPtr = isLHSPointer && LHSPointeeTy->isFunctionType();
+  bool isRHSFuncPtr = isRHSPointer && RHSPointeeTy->isFunctionType();
+  if (isLHSFuncPtr || isRHSFuncPtr) {
+    if (!isRHSFuncPtr) diagnoseArithmeticOnFunctionPointer(S, Loc, LHSExpr);
+    else if (!isLHSFuncPtr) diagnoseArithmeticOnFunctionPointer(S, Loc,
+                                                                RHSExpr);
+    else diagnoseArithmeticOnTwoFunctionPointers(S, Loc, LHSExpr, RHSExpr);
+
+    return !S.getLangOpts().CPlusPlus;
+  }
+
+  if (checkArithmeticIncompletePointerType(S, Loc, LHSExpr)) return false;
+  if (checkArithmeticIncompletePointerType(S, Loc, RHSExpr)) return false;
+
+  return true;
+}
+
+/// \brief Check bad cases where we step over interface counts.
+static bool checkArithmethicPointerOnNonFragileABI(Sema &S,
+                                                   SourceLocation OpLoc,
+                                                   Expr *Op) {
+  assert(Op->getType()->isAnyPointerType());
+  QualType PointeeTy = Op->getType()->getPointeeType();
+  if (!PointeeTy->isObjCObjectType() || !S.LangOpts.ObjCNonFragileABI)
+    return true;
+
+  S.Diag(OpLoc, diag::err_arithmetic_nonfragile_interface)
+    << PointeeTy << Op->getSourceRange();
+  return false;
+}
+
+/// diagnoseStringPlusInt - Emit a warning when adding an integer to a string
+/// literal.
+static void diagnoseStringPlusInt(Sema &Self, SourceLocation OpLoc,
+                                  Expr *LHSExpr, Expr *RHSExpr) {
+  StringLiteral* StrExpr = dyn_cast<StringLiteral>(LHSExpr->IgnoreImpCasts());
+  Expr* IndexExpr = RHSExpr;
+  if (!StrExpr) {
+    StrExpr = dyn_cast<StringLiteral>(RHSExpr->IgnoreImpCasts());
+    IndexExpr = LHSExpr;
+  }
+
+  bool IsStringPlusInt = StrExpr &&
+      IndexExpr->getType()->isIntegralOrUnscopedEnumerationType();
+  if (!IsStringPlusInt)
+    return;
+
+  llvm::APSInt index;
+  if (IndexExpr->EvaluateAsInt(index, Self.getASTContext())) {
+    unsigned StrLenWithNull = StrExpr->getLength() + 1;
+    if (index.isNonNegative() &&
+        index <= llvm::APSInt(llvm::APInt(index.getBitWidth(), StrLenWithNull),
+                              index.isUnsigned()))
+      return;
+  }
+
+  SourceRange DiagRange(LHSExpr->getLocStart(), RHSExpr->getLocEnd());
+  Self.Diag(OpLoc, diag::warn_string_plus_int)
+      << DiagRange << IndexExpr->IgnoreImpCasts()->getType();
+
+  // Only print a fixit for "str" + int, not for int + "str".
+  if (IndexExpr == RHSExpr) {
+    SourceLocation EndLoc = Self.PP.getLocForEndOfToken(RHSExpr->getLocEnd());
+    Self.Diag(OpLoc, diag::note_string_plus_int_silence)
+        << FixItHint::CreateInsertion(LHSExpr->getLocStart(), "&")
+        << FixItHint::CreateReplacement(SourceRange(OpLoc), "[")
+        << FixItHint::CreateInsertion(EndLoc, "]");
+  } else
+    Self.Diag(OpLoc, diag::note_string_plus_int_silence);
+}
+
+/// \brief Emit error when two pointers are incompatible.
+static void diagnosePointerIncompatibility(Sema &S, SourceLocation Loc,
+                                           Expr *LHSExpr, Expr *RHSExpr) {
+  assert(LHSExpr->getType()->isAnyPointerType());
+  assert(RHSExpr->getType()->isAnyPointerType());
+  S.Diag(Loc, diag::err_typecheck_sub_ptr_compatible)
+    << LHSExpr->getType() << RHSExpr->getType() << LHSExpr->getSourceRange()
+    << RHSExpr->getSourceRange();
+}
+
+QualType Sema::CheckAdditionOperands( // C99 6.5.6
+    ExprResult &LHS, ExprResult &RHS, SourceLocation Loc, unsigned Opc,
+    QualType* CompLHSTy) {
+  checkArithmeticNull(*this, LHS, RHS, Loc, /*isCompare=*/false);
+
+  if (LHS.get()->getType()->isVectorType() ||
+      RHS.get()->getType()->isVectorType()) {
+    QualType compType = CheckVectorOperands(LHS, RHS, Loc, CompLHSTy);
+    if (CompLHSTy) *CompLHSTy = compType;
+    return compType;
+  }
+
+  QualType compType = UsualArithmeticConversions(LHS, RHS, CompLHSTy);
+  if (LHS.isInvalid() || RHS.isInvalid())
+    return QualType();
+
+  // Diagnose "string literal" '+' int.
+  if (Opc == BO_Add)
+    diagnoseStringPlusInt(*this, Loc, LHS.get(), RHS.get());
+
+  // handle the common case first (both operands are arithmetic).
+  if (LHS.get()->getType()->isArithmeticType() &&
+      RHS.get()->getType()->isArithmeticType()) {
+    if (CompLHSTy) *CompLHSTy = compType;
+    return compType;
+  }
+
+  if (LHS.get()->getType()->isAtomicType() &&
+      RHS.get()->getType()->isArithmeticType()) {
+    *CompLHSTy = LHS.get()->getType();
+    return compType;
+  }
+
+  // Put any potential pointer into PExp
+  Expr* PExp = LHS.get(), *IExp = RHS.get();
+  if (IExp->getType()->isAnyPointerType())
+    std::swap(PExp, IExp);
+
+  if (!PExp->getType()->isAnyPointerType())
+    return InvalidOperands(Loc, LHS, RHS);
+
+  if (!IExp->getType()->isIntegerType())
+    return InvalidOperands(Loc, LHS, RHS);
+
+  if (!checkArithmeticOpPointerOperand(*this, Loc, PExp))
+    return QualType();
+
+  // Diagnose bad cases where we step over interface counts.
+  if (!checkArithmethicPointerOnNonFragileABI(*this, Loc, PExp))
+    return QualType();
+
+  // Check array bounds for pointer arithemtic
+  CheckArrayAccess(PExp, IExp);
+
+  if (CompLHSTy) {
+    QualType LHSTy = Context.isPromotableBitField(LHS.get());
+    if (LHSTy.isNull()) {
+      LHSTy = LHS.get()->getType();
+      if (LHSTy->isPromotableIntegerType())
+        LHSTy = Context.getPromotedIntegerType(LHSTy);
+    }
+    *CompLHSTy = LHSTy;
+  }
+
+  return PExp->getType();
+}
+
+// C99 6.5.6
+QualType Sema::CheckSubtractionOperands(ExprResult &LHS, ExprResult &RHS,
+                                        SourceLocation Loc,
+                                        QualType* CompLHSTy) {
+  checkArithmeticNull(*this, LHS, RHS, Loc, /*isCompare=*/false);
+
+  if (LHS.get()->getType()->isVectorType() ||
+      RHS.get()->getType()->isVectorType()) {
+    QualType compType = CheckVectorOperands(LHS, RHS, Loc, CompLHSTy);
+    if (CompLHSTy) *CompLHSTy = compType;
+    return compType;
+  }
+
+  QualType compType = UsualArithmeticConversions(LHS, RHS, CompLHSTy);
+  if (LHS.isInvalid() || RHS.isInvalid())
+    return QualType();
+
+  // Enforce type constraints: C99 6.5.6p3.
+
+  // Handle the common case first (both operands are arithmetic).
+  if (LHS.get()->getType()->isArithmeticType() &&
+      RHS.get()->getType()->isArithmeticType()) {
+    if (CompLHSTy) *CompLHSTy = compType;
+    return compType;
+  }
+
+  if (LHS.get()->getType()->isAtomicType() &&
+      RHS.get()->getType()->isArithmeticType()) {
+    *CompLHSTy = LHS.get()->getType();
+    return compType;
+  }
+
+  // Either ptr - int   or   ptr - ptr.
+  if (LHS.get()->getType()->isAnyPointerType()) {
+    QualType lpointee = LHS.get()->getType()->getPointeeType();
+
+    // Diagnose bad cases where we step over interface counts.
+    if (!checkArithmethicPointerOnNonFragileABI(*this, Loc, LHS.get()))
+      return QualType();
+
+    // The result type of a pointer-int computation is the pointer type.
+    if (RHS.get()->getType()->isIntegerType()) {
+      if (!checkArithmeticOpPointerOperand(*this, Loc, LHS.get()))
+        return QualType();
+
+      // Check array bounds for pointer arithemtic
+      CheckArrayAccess(LHS.get(), RHS.get(), /*ArraySubscriptExpr*/0,
+                       /*AllowOnePastEnd*/true, /*IndexNegated*/true);
+
+      if (CompLHSTy) *CompLHSTy = LHS.get()->getType();
+      return LHS.get()->getType();
+    }
+
+    // Handle pointer-pointer subtractions.
+    if (const PointerType *RHSPTy
+          = RHS.get()->getType()->getAs<PointerType>()) {
+      QualType rpointee = RHSPTy->getPointeeType();
+
+      if (getLangOpts().CPlusPlus) {
+        // Pointee types must be the same: C++ [expr.add]
+        if (!Context.hasSameUnqualifiedType(lpointee, rpointee)) {
+          diagnosePointerIncompatibility(*this, Loc, LHS.get(), RHS.get());
+        }
+      } else {
+        // Pointee types must be compatible C99 6.5.6p3
+        if (!Context.typesAreCompatible(
+                Context.getCanonicalType(lpointee).getUnqualifiedType(),
+                Context.getCanonicalType(rpointee).getUnqualifiedType())) {
+          diagnosePointerIncompatibility(*this, Loc, LHS.get(), RHS.get());
+          return QualType();
+        }
+      }
+
+      if (!checkArithmeticBinOpPointerOperands(*this, Loc,
+                                               LHS.get(), RHS.get()))
+        return QualType();
+
+      if (CompLHSTy) *CompLHSTy = LHS.get()->getType();
+      return Context.getPointerDiffType();
+    }
+  }
+
+  return InvalidOperands(Loc, LHS, RHS);
+}
+
+static bool isScopedEnumerationType(QualType T) {
+  if (const EnumType *ET = dyn_cast<EnumType>(T))
+    return ET->getDecl()->isScoped();
+  return false;
+}
+
+static void DiagnoseBadShiftValues(Sema& S, ExprResult &LHS, ExprResult &RHS,
+                                   SourceLocation Loc, unsigned Opc,
+                                   QualType LHSType) {
+  llvm::APSInt Right;
+  // Check right/shifter operand
+  if (RHS.get()->isValueDependent() ||
+      !RHS.get()->isIntegerConstantExpr(Right, S.Context))
+    return;
+
+  if (Right.isNegative()) {
+    S.DiagRuntimeBehavior(Loc, RHS.get(),
+                          S.PDiag(diag::warn_shift_negative)
+                            << RHS.get()->getSourceRange());
+    return;
+  }
+  llvm::APInt LeftBits(Right.getBitWidth(),
+                       S.Context.getTypeSize(LHS.get()->getType()));
+  if (Right.uge(LeftBits)) {
+    S.DiagRuntimeBehavior(Loc, RHS.get(),
+                          S.PDiag(diag::warn_shift_gt_typewidth)
+                            << RHS.get()->getSourceRange());
+    return;
+  }
+  if (Opc != BO_Shl)
+    return;
+
+  // When left shifting an ICE which is signed, we can check for overflow which
+  // according to C++ has undefined behavior ([expr.shift] 5.8/2). Unsigned
+  // integers have defined behavior modulo one more than the maximum value
+  // representable in the result type, so never warn for those.
+  llvm::APSInt Left;
+  if (LHS.get()->isValueDependent() ||
+      !LHS.get()->isIntegerConstantExpr(Left, S.Context) ||
+      LHSType->hasUnsignedIntegerRepresentation())
+    return;
+  llvm::APInt ResultBits =
+      static_cast<llvm::APInt&>(Right) + Left.getMinSignedBits();
+  if (LeftBits.uge(ResultBits))
+    return;
+  llvm::APSInt Result = Left.extend(ResultBits.getLimitedValue());
+  Result = Result.shl(Right);
+
+  // Print the bit representation of the signed integer as an unsigned
+  // hexadecimal number.
+  SmallString<40> HexResult;
+  Result.toString(HexResult, 16, /*Signed =*/false, /*Literal =*/true);
+
+  // If we are only missing a sign bit, this is less likely to result in actual
+  // bugs -- if the result is cast back to an unsigned type, it will have the
+  // expected value. Thus we place this behind a different warning that can be
+  // turned off separately if needed.
+  if (LeftBits == ResultBits - 1) {
+    S.Diag(Loc, diag::warn_shift_result_sets_sign_bit)
+        << HexResult.str() << LHSType
+        << LHS.get()->getSourceRange() << RHS.get()->getSourceRange();
+    return;
+  }
+
+  S.Diag(Loc, diag::warn_shift_result_gt_typewidth)
+    << HexResult.str() << Result.getMinSignedBits() << LHSType
+    << Left.getBitWidth() << LHS.get()->getSourceRange()
+    << RHS.get()->getSourceRange();
+}
+
+// C99 6.5.7
+QualType Sema::CheckShiftOperands(ExprResult &LHS, ExprResult &RHS,
+                                  SourceLocation Loc, unsigned Opc,
+                                  bool IsCompAssign) {
+  checkArithmeticNull(*this, LHS, RHS, Loc, /*isCompare=*/false);
+
+  // C99 6.5.7p2: Each of the operands shall have integer type.
+  if (!LHS.get()->getType()->hasIntegerRepresentation() || 
+      !RHS.get()->getType()->hasIntegerRepresentation())
+    return InvalidOperands(Loc, LHS, RHS);
+
+  // C++0x: Don't allow scoped enums. FIXME: Use something better than
+  // hasIntegerRepresentation() above instead of this.
+  if (isScopedEnumerationType(LHS.get()->getType()) ||
+      isScopedEnumerationType(RHS.get()->getType())) {
+    return InvalidOperands(Loc, LHS, RHS);
+  }
+
+  // Vector shifts promote their scalar inputs to vector type.
+  if (LHS.get()->getType()->isVectorType() ||
+      RHS.get()->getType()->isVectorType())
+    return CheckVectorOperands(LHS, RHS, Loc, IsCompAssign);
+
+  // Shifts don't perform usual arithmetic conversions, they just do integer
+  // promotions on each operand. C99 6.5.7p3
+
+  // For the LHS, do usual unary conversions, but then reset them away
+  // if this is a compound assignment.
+  ExprResult OldLHS = LHS;
+  LHS = UsualUnaryConversions(LHS.take());
+  if (LHS.isInvalid())
+    return QualType();
+  QualType LHSType = LHS.get()->getType();
+  if (IsCompAssign) LHS = OldLHS;
+
+  // The RHS is simpler.
+  RHS = UsualUnaryConversions(RHS.take());
+  if (RHS.isInvalid())
+    return QualType();
+
+  // Sanity-check shift operands
+  DiagnoseBadShiftValues(*this, LHS, RHS, Loc, Opc, LHSType);
+
+  // "The type of the result is that of the promoted left operand."
+  return LHSType;
+}
+
+static bool IsWithinTemplateSpecialization(Decl *D) {
+  if (DeclContext *DC = D->getDeclContext()) {
+    if (isa<ClassTemplateSpecializationDecl>(DC))
+      return true;
+    if (FunctionDecl *FD = dyn_cast<FunctionDecl>(DC))
+      return FD->isFunctionTemplateSpecialization();
+  }
+  return false;
+}
+
+/// If two different enums are compared, raise a warning.
+static void checkEnumComparison(Sema &S, SourceLocation Loc, ExprResult &LHS,
+                                ExprResult &RHS) {
+  QualType LHSStrippedType = LHS.get()->IgnoreParenImpCasts()->getType();
+  QualType RHSStrippedType = RHS.get()->IgnoreParenImpCasts()->getType();
+
+  const EnumType *LHSEnumType = LHSStrippedType->getAs<EnumType>();
+  if (!LHSEnumType)
+    return;
+  const EnumType *RHSEnumType = RHSStrippedType->getAs<EnumType>();
+  if (!RHSEnumType)
+    return;
+
+  // Ignore anonymous enums.
+  if (!LHSEnumType->getDecl()->getIdentifier())
+    return;
+  if (!RHSEnumType->getDecl()->getIdentifier())
+    return;
+
+  if (S.Context.hasSameUnqualifiedType(LHSStrippedType, RHSStrippedType))
+    return;
+
+  S.Diag(Loc, diag::warn_comparison_of_mixed_enum_types)
+      << LHSStrippedType << RHSStrippedType
+      << LHS.get()->getSourceRange() << RHS.get()->getSourceRange();
+}
+
+/// \brief Diagnose bad pointer comparisons.
+static void diagnoseDistinctPointerComparison(Sema &S, SourceLocation Loc,
+                                              ExprResult &LHS, ExprResult &RHS,
+                                              bool IsError) {
+  S.Diag(Loc, IsError ? diag::err_typecheck_comparison_of_distinct_pointers
+                      : diag::ext_typecheck_comparison_of_distinct_pointers)
+    << LHS.get()->getType() << RHS.get()->getType()
+    << LHS.get()->getSourceRange() << RHS.get()->getSourceRange();
+}
+
+/// \brief Returns false if the pointers are converted to a composite type,
+/// true otherwise.
+static bool convertPointersToCompositeType(Sema &S, SourceLocation Loc,
+                                           ExprResult &LHS, ExprResult &RHS) {
+  // C++ [expr.rel]p2:
+  //   [...] Pointer conversions (4.10) and qualification
+  //   conversions (4.4) are performed on pointer operands (or on
+  //   a pointer operand and a null pointer constant) to bring
+  //   them to their composite pointer type. [...]
+  //
+  // C++ [expr.eq]p1 uses the same notion for (in)equality
+  // comparisons of pointers.
+
+  // C++ [expr.eq]p2:
+  //   In addition, pointers to members can be compared, or a pointer to
+  //   member and a null pointer constant. Pointer to member conversions
+  //   (4.11) and qualification conversions (4.4) are performed to bring
+  //   them to a common type. If one operand is a null pointer constant,
+  //   the common type is the type of the other operand. Otherwise, the
+  //   common type is a pointer to member type similar (4.4) to the type
+  //   of one of the operands, with a cv-qualification signature (4.4)
+  //   that is the union of the cv-qualification signatures of the operand
+  //   types.
+
+  QualType LHSType = LHS.get()->getType();
+  QualType RHSType = RHS.get()->getType();
+  assert((LHSType->isPointerType() && RHSType->isPointerType()) ||
+         (LHSType->isMemberPointerType() && RHSType->isMemberPointerType()));
+
+  bool NonStandardCompositeType = false;
+  bool *BoolPtr = S.isSFINAEContext() ? 0 : &NonStandardCompositeType;
+  QualType T = S.FindCompositePointerType(Loc, LHS, RHS, BoolPtr);
+  if (T.isNull()) {
+    diagnoseDistinctPointerComparison(S, Loc, LHS, RHS, /*isError*/true);
+    return true;
+  }
+
+  if (NonStandardCompositeType)
+    S.Diag(Loc, diag::ext_typecheck_comparison_of_distinct_pointers_nonstandard)
+      << LHSType << RHSType << T << LHS.get()->getSourceRange()
+      << RHS.get()->getSourceRange();
+
+  LHS = S.ImpCastExprToType(LHS.take(), T, CK_BitCast);
+  RHS = S.ImpCastExprToType(RHS.take(), T, CK_BitCast);
+  return false;
+}
+
+static void diagnoseFunctionPointerToVoidComparison(Sema &S, SourceLocation Loc,
+                                                    ExprResult &LHS,
+                                                    ExprResult &RHS,
+                                                    bool IsError) {
+  S.Diag(Loc, IsError ? diag::err_typecheck_comparison_of_fptr_to_void
+                      : diag::ext_typecheck_comparison_of_fptr_to_void)
+    << LHS.get()->getType() << RHS.get()->getType()
+    << LHS.get()->getSourceRange() << RHS.get()->getSourceRange();
+}
+
+// C99 6.5.8, C++ [expr.rel]
+QualType Sema::CheckCompareOperands(ExprResult &LHS, ExprResult &RHS,
+                                    SourceLocation Loc, unsigned OpaqueOpc,
+                                    bool IsRelational) {
+  checkArithmeticNull(*this, LHS, RHS, Loc, /*isCompare=*/true);
+
+  BinaryOperatorKind Opc = (BinaryOperatorKind) OpaqueOpc;
+
+  // Handle vector comparisons separately.
+  if (LHS.get()->getType()->isVectorType() ||
+      RHS.get()->getType()->isVectorType())
+    return CheckVectorCompareOperands(LHS, RHS, Loc, IsRelational);
+
+  QualType LHSType = LHS.get()->getType();
+  QualType RHSType = RHS.get()->getType();
+
+  Expr *LHSStripped = LHS.get()->IgnoreParenImpCasts();
+  Expr *RHSStripped = RHS.get()->IgnoreParenImpCasts();
+
+  checkEnumComparison(*this, Loc, LHS, RHS);
+
+  if (!LHSType->hasFloatingRepresentation() &&
+      !(LHSType->isBlockPointerType() && IsRelational) &&
+      !LHS.get()->getLocStart().isMacroID() &&
+      !RHS.get()->getLocStart().isMacroID()) {
+    // For non-floating point types, check for self-comparisons of the form
+    // x == x, x != x, x < x, etc.  These always evaluate to a constant, and
+    // often indicate logic errors in the program.
+    //
+    // NOTE: Don't warn about comparison expressions resulting from macro
+    // expansion. Also don't warn about comparisons which are only self
+    // comparisons within a template specialization. The warnings should catch
+    // obvious cases in the definition of the template anyways. The idea is to
+    // warn when the typed comparison operator will always evaluate to the same
+    // result.
+    if (DeclRefExpr* DRL = dyn_cast<DeclRefExpr>(LHSStripped)) {
+      if (DeclRefExpr* DRR = dyn_cast<DeclRefExpr>(RHSStripped)) {
+        if (DRL->getDecl() == DRR->getDecl() &&
+            !IsWithinTemplateSpecialization(DRL->getDecl())) {
+          DiagRuntimeBehavior(Loc, 0, PDiag(diag::warn_comparison_always)
+                              << 0 // self-
+                              << (Opc == BO_EQ
+                                  || Opc == BO_LE
+                                  || Opc == BO_GE));
+        } else if (LHSType->isArrayType() && RHSType->isArrayType() &&
+                   !DRL->getDecl()->getType()->isReferenceType() &&
+                   !DRR->getDecl()->getType()->isReferenceType()) {
+            // what is it always going to eval to?
+            char always_evals_to;
+            switch(Opc) {
+            case BO_EQ: // e.g. array1 == array2
+              always_evals_to = 0; // false
+              break;
+            case BO_NE: // e.g. array1 != array2
+              always_evals_to = 1; // true
+              break;
+            default:
+              // best we can say is 'a constant'
+              always_evals_to = 2; // e.g. array1 <= array2
+              break;
+            }
+            DiagRuntimeBehavior(Loc, 0, PDiag(diag::warn_comparison_always)
+                                << 1 // array
+                                << always_evals_to);
+        }
+      }
+    }
+
+    if (isa<CastExpr>(LHSStripped))
+      LHSStripped = LHSStripped->IgnoreParenCasts();
+    if (isa<CastExpr>(RHSStripped))
+      RHSStripped = RHSStripped->IgnoreParenCasts();
+
+    // Warn about comparisons against a string constant (unless the other
+    // operand is null), the user probably wants strcmp.
+    Expr *literalString = 0;
+    Expr *literalStringStripped = 0;
+    if ((isa<StringLiteral>(LHSStripped) || isa<ObjCEncodeExpr>(LHSStripped)) &&
+        !RHSStripped->isNullPointerConstant(Context,
+                                            Expr::NPC_ValueDependentIsNull)) {
+      literalString = LHS.get();
+      literalStringStripped = LHSStripped;
+    } else if ((isa<StringLiteral>(RHSStripped) ||
+                isa<ObjCEncodeExpr>(RHSStripped)) &&
+               !LHSStripped->isNullPointerConstant(Context,
+                                            Expr::NPC_ValueDependentIsNull)) {
+      literalString = RHS.get();
+      literalStringStripped = RHSStripped;
+    }
+
+    if (literalString) {
+      std::string resultComparison;
+      switch (Opc) {
+      case BO_LT: resultComparison = ") < 0"; break;
+      case BO_GT: resultComparison = ") > 0"; break;
+      case BO_LE: resultComparison = ") <= 0"; break;
+      case BO_GE: resultComparison = ") >= 0"; break;
+      case BO_EQ: resultComparison = ") == 0"; break;
+      case BO_NE: resultComparison = ") != 0"; break;
+      default: llvm_unreachable("Invalid comparison operator");
+      }
+
+      DiagRuntimeBehavior(Loc, 0,
+        PDiag(diag::warn_stringcompare)
+          << isa<ObjCEncodeExpr>(literalStringStripped)
+          << literalString->getSourceRange());
+    }
+  }
+
+  // C99 6.5.8p3 / C99 6.5.9p4
+  if (LHS.get()->getType()->isArithmeticType() &&
+      RHS.get()->getType()->isArithmeticType()) {
+    UsualArithmeticConversions(LHS, RHS);
+    if (LHS.isInvalid() || RHS.isInvalid())
+      return QualType();
+  }
+  else {
+    LHS = UsualUnaryConversions(LHS.take());
+    if (LHS.isInvalid())
+      return QualType();
+
+    RHS = UsualUnaryConversions(RHS.take());
+    if (RHS.isInvalid())
+      return QualType();
+  }
+
+  LHSType = LHS.get()->getType();
+  RHSType = RHS.get()->getType();
+
+  // The result of comparisons is 'bool' in C++, 'int' in C.
+  QualType ResultTy = Context.getLogicalOperationType();
+
+  if (IsRelational) {
+    if (LHSType->isRealType() && RHSType->isRealType())
+      return ResultTy;
+  } else {
+    // Check for comparisons of floating point operands using != and ==.
+    if (LHSType->hasFloatingRepresentation())
+      CheckFloatComparison(Loc, LHS.get(), RHS.get());
+
+    if (LHSType->isArithmeticType() && RHSType->isArithmeticType())
+      return ResultTy;
+  }
+
+  bool LHSIsNull = LHS.get()->isNullPointerConstant(Context,
+                                              Expr::NPC_ValueDependentIsNull);
+  bool RHSIsNull = RHS.get()->isNullPointerConstant(Context,
+                                              Expr::NPC_ValueDependentIsNull);
+
+  // All of the following pointer-related warnings are GCC extensions, except
+  // when handling null pointer constants. 
+  if (LHSType->isPointerType() && RHSType->isPointerType()) { // C99 6.5.8p2
+    QualType LCanPointeeTy =
+      LHSType->castAs<PointerType>()->getPointeeType().getCanonicalType();
+    QualType RCanPointeeTy =
+      RHSType->castAs<PointerType>()->getPointeeType().getCanonicalType();
+
+    if (getLangOpts().CPlusPlus) {
+      if (LCanPointeeTy == RCanPointeeTy)
+        return ResultTy;
+      if (!IsRelational &&
+          (LCanPointeeTy->isVoidType() || RCanPointeeTy->isVoidType())) {
+        // Valid unless comparison between non-null pointer and function pointer
+        // This is a gcc extension compatibility comparison.
+        // In a SFINAE context, we treat this as a hard error to maintain
+        // conformance with the C++ standard.
+        if ((LCanPointeeTy->isFunctionType() || RCanPointeeTy->isFunctionType())
+            && !LHSIsNull && !RHSIsNull) {
+          diagnoseFunctionPointerToVoidComparison(
+              *this, Loc, LHS, RHS, /*isError*/ isSFINAEContext());
+          
+          if (isSFINAEContext())
+            return QualType();
+          
+          RHS = ImpCastExprToType(RHS.take(), LHSType, CK_BitCast);
+          return ResultTy;
+        }
+      }
+
+      if (convertPointersToCompositeType(*this, Loc, LHS, RHS))
+        return QualType();
+      else
+        return ResultTy;
+    }
+    // C99 6.5.9p2 and C99 6.5.8p2
+    if (Context.typesAreCompatible(LCanPointeeTy.getUnqualifiedType(),
+                                   RCanPointeeTy.getUnqualifiedType())) {
+      // Valid unless a relational comparison of function pointers
+      if (IsRelational && LCanPointeeTy->isFunctionType()) {
+        Diag(Loc, diag::ext_typecheck_ordered_comparison_of_function_pointers)
+          << LHSType << RHSType << LHS.get()->getSourceRange()
+          << RHS.get()->getSourceRange();
+      }
+    } else if (!IsRelational &&
+               (LCanPointeeTy->isVoidType() || RCanPointeeTy->isVoidType())) {
+      // Valid unless comparison between non-null pointer and function pointer
+      if ((LCanPointeeTy->isFunctionType() || RCanPointeeTy->isFunctionType())
+          && !LHSIsNull && !RHSIsNull)
+        diagnoseFunctionPointerToVoidComparison(*this, Loc, LHS, RHS,
+                                                /*isError*/false);
+    } else {
+      // Invalid
+      diagnoseDistinctPointerComparison(*this, Loc, LHS, RHS, /*isError*/false);
+    }
+    if (LCanPointeeTy != RCanPointeeTy) {
+      if (LHSIsNull && !RHSIsNull)
+        LHS = ImpCastExprToType(LHS.take(), RHSType, CK_BitCast);
+      else
+        RHS = ImpCastExprToType(RHS.take(), LHSType, CK_BitCast);
+    }
+    return ResultTy;
+  }
+
+  if (getLangOpts().CPlusPlus) {
+    // Comparison of nullptr_t with itself.
+    if (LHSType->isNullPtrType() && RHSType->isNullPtrType())
+      return ResultTy;
+    
+    // Comparison of pointers with null pointer constants and equality
+    // comparisons of member pointers to null pointer constants.
+    if (RHSIsNull &&
+        ((LHSType->isAnyPointerType() || LHSType->isNullPtrType()) ||
+         (!IsRelational && 
+          (LHSType->isMemberPointerType() || LHSType->isBlockPointerType())))) {
+      RHS = ImpCastExprToType(RHS.take(), LHSType, 
+                        LHSType->isMemberPointerType()
+                          ? CK_NullToMemberPointer
+                          : CK_NullToPointer);
+      return ResultTy;
+    }
+    if (LHSIsNull &&
+        ((RHSType->isAnyPointerType() || RHSType->isNullPtrType()) ||
+         (!IsRelational && 
+          (RHSType->isMemberPointerType() || RHSType->isBlockPointerType())))) {
+      LHS = ImpCastExprToType(LHS.take(), RHSType, 
+                        RHSType->isMemberPointerType()
+                          ? CK_NullToMemberPointer
+                          : CK_NullToPointer);
+      return ResultTy;
+    }
+
+    // Comparison of member pointers.
+    if (!IsRelational &&
+        LHSType->isMemberPointerType() && RHSType->isMemberPointerType()) {
+      if (convertPointersToCompositeType(*this, Loc, LHS, RHS))
+        return QualType();
+      else
+        return ResultTy;
+    }
+
+    // Handle scoped enumeration types specifically, since they don't promote
+    // to integers.
+    if (LHS.get()->getType()->isEnumeralType() &&
+        Context.hasSameUnqualifiedType(LHS.get()->getType(),
+                                       RHS.get()->getType()))
+      return ResultTy;
+  }
+
+  // Handle block pointer types.
+  if (!IsRelational && LHSType->isBlockPointerType() &&
+      RHSType->isBlockPointerType()) {
+    QualType lpointee = LHSType->castAs<BlockPointerType>()->getPointeeType();
+    QualType rpointee = RHSType->castAs<BlockPointerType>()->getPointeeType();
+
+    if (!LHSIsNull && !RHSIsNull &&
+        !Context.typesAreCompatible(lpointee, rpointee)) {
+      Diag(Loc, diag::err_typecheck_comparison_of_distinct_blocks)
+        << LHSType << RHSType << LHS.get()->getSourceRange()
+        << RHS.get()->getSourceRange();
+    }
+    RHS = ImpCastExprToType(RHS.take(), LHSType, CK_BitCast);
+    return ResultTy;
+  }
+
+  // Allow block pointers to be compared with null pointer constants.
+  if (!IsRelational
+      && ((LHSType->isBlockPointerType() && RHSType->isPointerType())
+          || (LHSType->isPointerType() && RHSType->isBlockPointerType()))) {
+    if (!LHSIsNull && !RHSIsNull) {
+      if (!((RHSType->isPointerType() && RHSType->castAs<PointerType>()
+             ->getPointeeType()->isVoidType())
+            || (LHSType->isPointerType() && LHSType->castAs<PointerType>()
+                ->getPointeeType()->isVoidType())))
+        Diag(Loc, diag::err_typecheck_comparison_of_distinct_blocks)
+          << LHSType << RHSType << LHS.get()->getSourceRange()
+          << RHS.get()->getSourceRange();
+    }
+    if (LHSIsNull && !RHSIsNull)
+      LHS = ImpCastExprToType(LHS.take(), RHSType,
+                              RHSType->isPointerType() ? CK_BitCast
+                                : CK_AnyPointerToBlockPointerCast);
+    else
+      RHS = ImpCastExprToType(RHS.take(), LHSType,
+                              LHSType->isPointerType() ? CK_BitCast
+                                : CK_AnyPointerToBlockPointerCast);
+    return ResultTy;
+  }
+
+  if (LHSType->isObjCObjectPointerType() ||
+      RHSType->isObjCObjectPointerType()) {
+    const PointerType *LPT = LHSType->getAs<PointerType>();
+    const PointerType *RPT = RHSType->getAs<PointerType>();
+    if (LPT || RPT) {
+      bool LPtrToVoid = LPT ? LPT->getPointeeType()->isVoidType() : false;
+      bool RPtrToVoid = RPT ? RPT->getPointeeType()->isVoidType() : false;
+
+      if (!LPtrToVoid && !RPtrToVoid &&
+          !Context.typesAreCompatible(LHSType, RHSType)) {
+        diagnoseDistinctPointerComparison(*this, Loc, LHS, RHS,
+                                          /*isError*/false);
+      }
+      if (LHSIsNull && !RHSIsNull)
+        LHS = ImpCastExprToType(LHS.take(), RHSType,
+                                RPT ? CK_BitCast :CK_CPointerToObjCPointerCast);
+      else
+        RHS = ImpCastExprToType(RHS.take(), LHSType,
+                                LPT ? CK_BitCast :CK_CPointerToObjCPointerCast);
+      return ResultTy;
+    }
+    if (LHSType->isObjCObjectPointerType() &&
+        RHSType->isObjCObjectPointerType()) {
+      if (!Context.areComparableObjCPointerTypes(LHSType, RHSType))
+        diagnoseDistinctPointerComparison(*this, Loc, LHS, RHS,
+                                          /*isError*/false);
+      if (LHSIsNull && !RHSIsNull)
+        LHS = ImpCastExprToType(LHS.take(), RHSType, CK_BitCast);
+      else
+        RHS = ImpCastExprToType(RHS.take(), LHSType, CK_BitCast);
+      return ResultTy;
+    }
+  }
+  if ((LHSType->isAnyPointerType() && RHSType->isIntegerType()) ||
+      (LHSType->isIntegerType() && RHSType->isAnyPointerType())) {
+    unsigned DiagID = 0;
+    bool isError = false;
+    if ((LHSIsNull && LHSType->isIntegerType()) ||
+        (RHSIsNull && RHSType->isIntegerType())) {
+      if (IsRelational && !getLangOpts().CPlusPlus)
+        DiagID = diag::ext_typecheck_ordered_comparison_of_pointer_and_zero;
+    } else if (IsRelational && !getLangOpts().CPlusPlus)
+      DiagID = diag::ext_typecheck_ordered_comparison_of_pointer_integer;
+    else if (getLangOpts().CPlusPlus) {
+      DiagID = diag::err_typecheck_comparison_of_pointer_integer;
+      isError = true;
+    } else
+      DiagID = diag::ext_typecheck_comparison_of_pointer_integer;
+
+    if (DiagID) {
+      Diag(Loc, DiagID)
+        << LHSType << RHSType << LHS.get()->getSourceRange()
+        << RHS.get()->getSourceRange();
+      if (isError)
+        return QualType();
+    }
+    
+    if (LHSType->isIntegerType())
+      LHS = ImpCastExprToType(LHS.take(), RHSType,
+                        LHSIsNull ? CK_NullToPointer : CK_IntegralToPointer);
+    else
+      RHS = ImpCastExprToType(RHS.take(), LHSType,
+                        RHSIsNull ? CK_NullToPointer : CK_IntegralToPointer);
+    return ResultTy;
+  }
+  
+  // Handle block pointers.
+  if (!IsRelational && RHSIsNull
+      && LHSType->isBlockPointerType() && RHSType->isIntegerType()) {
+    RHS = ImpCastExprToType(RHS.take(), LHSType, CK_NullToPointer);
+    return ResultTy;
+  }
+  if (!IsRelational && LHSIsNull
+      && LHSType->isIntegerType() && RHSType->isBlockPointerType()) {
+    LHS = ImpCastExprToType(LHS.take(), RHSType, CK_NullToPointer);
+    return ResultTy;
+  }
+
+  return InvalidOperands(Loc, LHS, RHS);
+}
+
+
+// Return a signed type that is of identical size and number of elements.
+// For floating point vectors, return an integer type of identical size 
+// and number of elements.
+QualType Sema::GetSignedVectorType(QualType V) {
+  const VectorType *VTy = V->getAs<VectorType>();
+  unsigned TypeSize = Context.getTypeSize(VTy->getElementType());
+  if (TypeSize == Context.getTypeSize(Context.CharTy))
+    return Context.getExtVectorType(Context.CharTy, VTy->getNumElements());
+  else if (TypeSize == Context.getTypeSize(Context.ShortTy))
+    return Context.getExtVectorType(Context.ShortTy, VTy->getNumElements());
+  else if (TypeSize == Context.getTypeSize(Context.IntTy))
+    return Context.getExtVectorType(Context.IntTy, VTy->getNumElements());
+  else if (TypeSize == Context.getTypeSize(Context.LongTy))
+    return Context.getExtVectorType(Context.LongTy, VTy->getNumElements());
+  assert(TypeSize == Context.getTypeSize(Context.LongLongTy) &&
+         "Unhandled vector element size in vector compare");
+  return Context.getExtVectorType(Context.LongLongTy, VTy->getNumElements());
+}
+
+/// CheckVectorCompareOperands - vector comparisons are a clang extension that
+/// operates on extended vector types.  Instead of producing an IntTy result,
+/// like a scalar comparison, a vector comparison produces a vector of integer
+/// types.
+QualType Sema::CheckVectorCompareOperands(ExprResult &LHS, ExprResult &RHS,
+                                          SourceLocation Loc,
+                                          bool IsRelational) {
+  // Check to make sure we're operating on vectors of the same type and width,
+  // Allowing one side to be a scalar of element type.
+  QualType vType = CheckVectorOperands(LHS, RHS, Loc, /*isCompAssign*/false);
+  if (vType.isNull())
+    return vType;
+
+  QualType LHSType = LHS.get()->getType();
+
+  // If AltiVec, the comparison results in a numeric type, i.e.
+  // bool for C++, int for C
+  if (vType->getAs<VectorType>()->getVectorKind() == VectorType::AltiVecVector)
+    return Context.getLogicalOperationType();
+
+  // For non-floating point types, check for self-comparisons of the form
+  // x == x, x != x, x < x, etc.  These always evaluate to a constant, and
+  // often indicate logic errors in the program.
+  if (!LHSType->hasFloatingRepresentation()) {
+    if (DeclRefExpr* DRL
+          = dyn_cast<DeclRefExpr>(LHS.get()->IgnoreParenImpCasts()))
+      if (DeclRefExpr* DRR
+            = dyn_cast<DeclRefExpr>(RHS.get()->IgnoreParenImpCasts()))
+        if (DRL->getDecl() == DRR->getDecl())
+          DiagRuntimeBehavior(Loc, 0,
+                              PDiag(diag::warn_comparison_always)
+                                << 0 // self-
+                                << 2 // "a constant"
+                              );
+  }
+
+  // Check for comparisons of floating point operands using != and ==.
+  if (!IsRelational && LHSType->hasFloatingRepresentation()) {
+    assert (RHS.get()->getType()->hasFloatingRepresentation());
+    CheckFloatComparison(Loc, LHS.get(), RHS.get());
+  }
+  
+  // Return a signed type for the vector.
+  return GetSignedVectorType(LHSType);
+}
+
+QualType Sema::CheckVectorLogicalOperands(ExprResult &LHS, ExprResult &RHS,
+                                          SourceLocation Loc) {
+  // Ensure that either both operands are of the same vector type, or
+  // one operand is of a vector type and the other is of its element type.
+  QualType vType = CheckVectorOperands(LHS, RHS, Loc, false);
+  if (vType.isNull() || vType->isFloatingType())
+    return InvalidOperands(Loc, LHS, RHS);
+  
+  return GetSignedVectorType(LHS.get()->getType());
+}
+
+inline QualType Sema::CheckBitwiseOperands(
+  ExprResult &LHS, ExprResult &RHS, SourceLocation Loc, bool IsCompAssign) {
+  checkArithmeticNull(*this, LHS, RHS, Loc, /*isCompare=*/false);
+
+  if (LHS.get()->getType()->isVectorType() ||
+      RHS.get()->getType()->isVectorType()) {
+    if (LHS.get()->getType()->hasIntegerRepresentation() &&
+        RHS.get()->getType()->hasIntegerRepresentation())
+      return CheckVectorOperands(LHS, RHS, Loc, IsCompAssign);
+    
+    return InvalidOperands(Loc, LHS, RHS);
+  }
+
+  ExprResult LHSResult = Owned(LHS), RHSResult = Owned(RHS);
+  QualType compType = UsualArithmeticConversions(LHSResult, RHSResult,
+                                                 IsCompAssign);
+  if (LHSResult.isInvalid() || RHSResult.isInvalid())
+    return QualType();
+  LHS = LHSResult.take();
+  RHS = RHSResult.take();
+
+  if (LHS.get()->getType()->isIntegralOrUnscopedEnumerationType() &&
+      RHS.get()->getType()->isIntegralOrUnscopedEnumerationType())
+    return compType;
+  return InvalidOperands(Loc, LHS, RHS);
+}
+
+inline QualType Sema::CheckLogicalOperands( // C99 6.5.[13,14]
+  ExprResult &LHS, ExprResult &RHS, SourceLocation Loc, unsigned Opc) {
+  
+  // Check vector operands differently.
+  if (LHS.get()->getType()->isVectorType() || RHS.get()->getType()->isVectorType())
+    return CheckVectorLogicalOperands(LHS, RHS, Loc);
+  
+  // Diagnose cases where the user write a logical and/or but probably meant a
+  // bitwise one.  We do this when the LHS is a non-bool integer and the RHS
+  // is a constant.
+  if (LHS.get()->getType()->isIntegerType() &&
+      !LHS.get()->getType()->isBooleanType() &&
+      RHS.get()->getType()->isIntegerType() && !RHS.get()->isValueDependent() &&
+      // Don't warn in macros or template instantiations.
+      !Loc.isMacroID() && ActiveTemplateInstantiations.empty()) {
+    // If the RHS can be constant folded, and if it constant folds to something
+    // that isn't 0 or 1 (which indicate a potential logical operation that
+    // happened to fold to true/false) then warn.
+    // Parens on the RHS are ignored.
+    llvm::APSInt Result;
+    if (RHS.get()->EvaluateAsInt(Result, Context))
+      if ((getLangOpts().Bool && !RHS.get()->getType()->isBooleanType()) ||
+          (Result != 0 && Result != 1)) {
+        Diag(Loc, diag::warn_logical_instead_of_bitwise)
+          << RHS.get()->getSourceRange()
+          << (Opc == BO_LAnd ? "&&" : "||");
+        // Suggest replacing the logical operator with the bitwise version
+        Diag(Loc, diag::note_logical_instead_of_bitwise_change_operator)
+            << (Opc == BO_LAnd ? "&" : "|")
+            << FixItHint::CreateReplacement(SourceRange(
+                Loc, Lexer::getLocForEndOfToken(Loc, 0, getSourceManager(),
+                                                getLangOpts())),
+                                            Opc == BO_LAnd ? "&" : "|");
+        if (Opc == BO_LAnd)
+          // Suggest replacing "Foo() && kNonZero" with "Foo()"
+          Diag(Loc, diag::note_logical_instead_of_bitwise_remove_constant)
+              << FixItHint::CreateRemoval(
+                  SourceRange(
+                      Lexer::getLocForEndOfToken(LHS.get()->getLocEnd(),
+                                                 0, getSourceManager(),
+                                                 getLangOpts()),
+                      RHS.get()->getLocEnd()));
+      }
+  }
+  
+  if (!Context.getLangOpts().CPlusPlus) {
+    LHS = UsualUnaryConversions(LHS.take());
+    if (LHS.isInvalid())
+      return QualType();
+
+    RHS = UsualUnaryConversions(RHS.take());
+    if (RHS.isInvalid())
+      return QualType();
+
+    if (!LHS.get()->getType()->isScalarType() ||
+        !RHS.get()->getType()->isScalarType())
+      return InvalidOperands(Loc, LHS, RHS);
+
+    return Context.IntTy;
+  }
+
+  // The following is safe because we only use this method for
+  // non-overloadable operands.
+
+  // C++ [expr.log.and]p1
+  // C++ [expr.log.or]p1
+  // The operands are both contextually converted to type bool.
+  ExprResult LHSRes = PerformContextuallyConvertToBool(LHS.get());
+  if (LHSRes.isInvalid())
+    return InvalidOperands(Loc, LHS, RHS);
+  LHS = move(LHSRes);
+
+  ExprResult RHSRes = PerformContextuallyConvertToBool(RHS.get());
+  if (RHSRes.isInvalid())
+    return InvalidOperands(Loc, LHS, RHS);
+  RHS = move(RHSRes);
+
+  // C++ [expr.log.and]p2
+  // C++ [expr.log.or]p2
+  // The result is a bool.
+  return Context.BoolTy;
+}
+
+/// IsReadonlyProperty - Verify that otherwise a valid l-value expression
+/// is a read-only property; return true if so. A readonly property expression
+/// depends on various declarations and thus must be treated specially.
+///
+static bool IsReadonlyProperty(Expr *E, Sema &S) {
+  const ObjCPropertyRefExpr *PropExpr = dyn_cast<ObjCPropertyRefExpr>(E);
+  if (!PropExpr) return false;
+  if (PropExpr->isImplicitProperty()) return false;
+
+  ObjCPropertyDecl *PDecl = PropExpr->getExplicitProperty();
+  QualType BaseType = PropExpr->isSuperReceiver() ? 
+                            PropExpr->getSuperReceiverType() :  
+                            PropExpr->getBase()->getType();
+      
+  if (const ObjCObjectPointerType *OPT =
+      BaseType->getAsObjCInterfacePointerType())
+    if (ObjCInterfaceDecl *IFace = OPT->getInterfaceDecl())
+      if (S.isPropertyReadonly(PDecl, IFace))
+        return true;
+  return false;
+}
+
+static bool IsReadonlyMessage(Expr *E, Sema &S) {
+  const MemberExpr *ME = dyn_cast<MemberExpr>(E);
+  if (!ME) return false;
+  if (!isa<FieldDecl>(ME->getMemberDecl())) return false;
+  ObjCMessageExpr *Base =
+    dyn_cast<ObjCMessageExpr>(ME->getBase()->IgnoreParenImpCasts());
+  if (!Base) return false;
+  return Base->getMethodDecl() != 0;
+}
+
+/// Is the given expression (which must be 'const') a reference to a
+/// variable which was originally non-const, but which has become
+/// 'const' due to being captured within a block?
+enum NonConstCaptureKind { NCCK_None, NCCK_Block, NCCK_Lambda };
+static NonConstCaptureKind isReferenceToNonConstCapture(Sema &S, Expr *E) {
+  assert(E->isLValue() && E->getType().isConstQualified());
+  E = E->IgnoreParens();
+
+  // Must be a reference to a declaration from an enclosing scope.
+  DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E);
+  if (!DRE) return NCCK_None;
+  if (!DRE->refersToEnclosingLocal()) return NCCK_None;
+
+  // The declaration must be a variable which is not declared 'const'.
+  VarDecl *var = dyn_cast<VarDecl>(DRE->getDecl());
+  if (!var) return NCCK_None;
+  if (var->getType().isConstQualified()) return NCCK_None;
+  assert(var->hasLocalStorage() && "capture added 'const' to non-local?");
+
+  // Decide whether the first capture was for a block or a lambda.
+  DeclContext *DC = S.CurContext;
+  while (DC->getParent() != var->getDeclContext())
+    DC = DC->getParent();
+  return (isa<BlockDecl>(DC) ? NCCK_Block : NCCK_Lambda);
+}
+
+/// CheckForModifiableLvalue - Verify that E is a modifiable lvalue.  If not,
+/// emit an error and return true.  If so, return false.
+static bool CheckForModifiableLvalue(Expr *E, SourceLocation Loc, Sema &S) {
+  assert(!E->hasPlaceholderType(BuiltinType::PseudoObject));
+  SourceLocation OrigLoc = Loc;
+  Expr::isModifiableLvalueResult IsLV = E->isModifiableLvalue(S.Context,
+                                                              &Loc);
+  if (IsLV == Expr::MLV_Valid && IsReadonlyProperty(E, S))
+    IsLV = Expr::MLV_ReadonlyProperty;
+  else if (IsLV == Expr::MLV_ClassTemporary && IsReadonlyMessage(E, S))
+    IsLV = Expr::MLV_InvalidMessageExpression;
+  if (IsLV == Expr::MLV_Valid)
+    return false;
+
+  unsigned Diag = 0;
+  bool NeedType = false;
+  switch (IsLV) { // C99 6.5.16p2
+  case Expr::MLV_ConstQualified:
+    Diag = diag::err_typecheck_assign_const;
+
+    // Use a specialized diagnostic when we're assigning to an object
+    // from an enclosing function or block.
+    if (NonConstCaptureKind NCCK = isReferenceToNonConstCapture(S, E)) {
+      if (NCCK == NCCK_Block)
+        Diag = diag::err_block_decl_ref_not_modifiable_lvalue;
+      else
+        Diag = diag::err_lambda_decl_ref_not_modifiable_lvalue;
+      break;
+    }
+
+    // In ARC, use some specialized diagnostics for occasions where we
+    // infer 'const'.  These are always pseudo-strong variables.
+    if (S.getLangOpts().ObjCAutoRefCount) {
+      DeclRefExpr *declRef = dyn_cast<DeclRefExpr>(E->IgnoreParenCasts());
+      if (declRef && isa<VarDecl>(declRef->getDecl())) {
+        VarDecl *var = cast<VarDecl>(declRef->getDecl());
+
+        // Use the normal diagnostic if it's pseudo-__strong but the
+        // user actually wrote 'const'.
+        if (var->isARCPseudoStrong() &&
+            (!var->getTypeSourceInfo() ||
+             !var->getTypeSourceInfo()->getType().isConstQualified())) {
+          // There are two pseudo-strong cases:
+          //  - self
+          ObjCMethodDecl *method = S.getCurMethodDecl();
+          if (method && var == method->getSelfDecl())
+            Diag = method->isClassMethod()
+              ? diag::err_typecheck_arc_assign_self_class_method
+              : diag::err_typecheck_arc_assign_self;
+
+          //  - fast enumeration variables
+          else
+            Diag = diag::err_typecheck_arr_assign_enumeration;
+
+          SourceRange Assign;
+          if (Loc != OrigLoc)
+            Assign = SourceRange(OrigLoc, OrigLoc);
+          S.Diag(Loc, Diag) << E->getSourceRange() << Assign;
+          // We need to preserve the AST regardless, so migration tool 
+          // can do its job.
+          return false;
+        }
+      }
+    }
+
+    break;
+  case Expr::MLV_ArrayType:
+    Diag = diag::err_typecheck_array_not_modifiable_lvalue;
+    NeedType = true;
+    break;
+  case Expr::MLV_NotObjectType:
+    Diag = diag::err_typecheck_non_object_not_modifiable_lvalue;
+    NeedType = true;
+    break;
+  case Expr::MLV_LValueCast:
+    Diag = diag::err_typecheck_lvalue_casts_not_supported;
+    break;
+  case Expr::MLV_Valid:
+    llvm_unreachable("did not take early return for MLV_Valid");
+  case Expr::MLV_InvalidExpression:
+  case Expr::MLV_MemberFunction:
+  case Expr::MLV_ClassTemporary:
+    Diag = diag::err_typecheck_expression_not_modifiable_lvalue;
+    break;
+  case Expr::MLV_IncompleteType:
+  case Expr::MLV_IncompleteVoidType:
+    return S.RequireCompleteType(Loc, E->getType(),
+              S.PDiag(diag::err_typecheck_incomplete_type_not_modifiable_lvalue)
+                  << E->getSourceRange());
+  case Expr::MLV_DuplicateVectorComponents:
+    Diag = diag::err_typecheck_duplicate_vector_components_not_mlvalue;
+    break;
+  case Expr::MLV_ReadonlyProperty:
+  case Expr::MLV_NoSetterProperty:
+    llvm_unreachable("readonly properties should be processed differently");
+  case Expr::MLV_InvalidMessageExpression:
+    Diag = diag::error_readonly_message_assignment;
+    break;
+  case Expr::MLV_SubObjCPropertySetting:
+    Diag = diag::error_no_subobject_property_setting;
+    break;
+  }
+
+  SourceRange Assign;
+  if (Loc != OrigLoc)
+    Assign = SourceRange(OrigLoc, OrigLoc);
+  if (NeedType)
+    S.Diag(Loc, Diag) << E->getType() << E->getSourceRange() << Assign;
+  else
+    S.Diag(Loc, Diag) << E->getSourceRange() << Assign;
+  return true;
+}
+
+
+
+// C99 6.5.16.1
+QualType Sema::CheckAssignmentOperands(Expr *LHSExpr, ExprResult &RHS,
+                                       SourceLocation Loc,
+                                       QualType CompoundType) {
+  assert(!LHSExpr->hasPlaceholderType(BuiltinType::PseudoObject));
+
+  // Verify that LHS is a modifiable lvalue, and emit error if not.
+  if (CheckForModifiableLvalue(LHSExpr, Loc, *this))
+    return QualType();
+
+  QualType LHSType = LHSExpr->getType();
+  QualType RHSType = CompoundType.isNull() ? RHS.get()->getType() :
+                                             CompoundType;
+  AssignConvertType ConvTy;
+  if (CompoundType.isNull()) {
+    QualType LHSTy(LHSType);
+    ConvTy = CheckSingleAssignmentConstraints(LHSTy, RHS);
+    if (RHS.isInvalid())
+      return QualType();
+    // Special case of NSObject attributes on c-style pointer types.
+    if (ConvTy == IncompatiblePointer &&
+        ((Context.isObjCNSObjectType(LHSType) &&
+          RHSType->isObjCObjectPointerType()) ||
+         (Context.isObjCNSObjectType(RHSType) &&
+          LHSType->isObjCObjectPointerType())))
+      ConvTy = Compatible;
+
+    if (ConvTy == Compatible &&
+        LHSType->isObjCObjectType())
+        Diag(Loc, diag::err_objc_object_assignment)
+          << LHSType;
+
+    // If the RHS is a unary plus or minus, check to see if they = and + are
+    // right next to each other.  If so, the user may have typo'd "x =+ 4"
+    // instead of "x += 4".
+    Expr *RHSCheck = RHS.get();
+    if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(RHSCheck))
+      RHSCheck = ICE->getSubExpr();
+    if (UnaryOperator *UO = dyn_cast<UnaryOperator>(RHSCheck)) {
+      if ((UO->getOpcode() == UO_Plus ||
+           UO->getOpcode() == UO_Minus) &&
+          Loc.isFileID() && UO->getOperatorLoc().isFileID() &&
+          // Only if the two operators are exactly adjacent.
+          Loc.getLocWithOffset(1) == UO->getOperatorLoc() &&
+          // And there is a space or other character before the subexpr of the
+          // unary +/-.  We don't want to warn on "x=-1".
+          Loc.getLocWithOffset(2) != UO->getSubExpr()->getLocStart() &&
+          UO->getSubExpr()->getLocStart().isFileID()) {
+        Diag(Loc, diag::warn_not_compound_assign)
+          << (UO->getOpcode() == UO_Plus ? "+" : "-")
+          << SourceRange(UO->getOperatorLoc(), UO->getOperatorLoc());
+      }
+    }
+
+    if (ConvTy == Compatible) {
+      if (LHSType.getObjCLifetime() == Qualifiers::OCL_Strong)
+        checkRetainCycles(LHSExpr, RHS.get());
+      else if (getLangOpts().ObjCAutoRefCount)
+        checkUnsafeExprAssigns(Loc, LHSExpr, RHS.get());
+    }
+  } else {
+    // Compound assignment "x += y"
+    ConvTy = CheckAssignmentConstraints(Loc, LHSType, RHSType);
+  }
+
+  if (DiagnoseAssignmentResult(ConvTy, Loc, LHSType, RHSType,
+                               RHS.get(), AA_Assigning))
+    return QualType();
+
+  CheckForNullPointerDereference(*this, LHSExpr);
+
+  // C99 6.5.16p3: The type of an assignment expression is the type of the
+  // left operand unless the left operand has qualified type, in which case
+  // it is the unqualified version of the type of the left operand.
+  // C99 6.5.16.1p2: In simple assignment, the value of the right operand
+  // is converted to the type of the assignment expression (above).
+  // C++ 5.17p1: the type of the assignment expression is that of its left
+  // operand.
+  return (getLangOpts().CPlusPlus
+          ? LHSType : LHSType.getUnqualifiedType());
+}
+
+// C99 6.5.17
+static QualType CheckCommaOperands(Sema &S, ExprResult &LHS, ExprResult &RHS,
+                                   SourceLocation Loc) {
+  S.DiagnoseUnusedExprResult(LHS.get());
+
+  LHS = S.CheckPlaceholderExpr(LHS.take());
+  RHS = S.CheckPlaceholderExpr(RHS.take());
+  if (LHS.isInvalid() || RHS.isInvalid())
+    return QualType();
+
+  // C's comma performs lvalue conversion (C99 6.3.2.1) on both its
+  // operands, but not unary promotions.
+  // C++'s comma does not do any conversions at all (C++ [expr.comma]p1).
+
+  // So we treat the LHS as a ignored value, and in C++ we allow the
+  // containing site to determine what should be done with the RHS.
+  LHS = S.IgnoredValueConversions(LHS.take());
+  if (LHS.isInvalid())
+    return QualType();
+
+  if (!S.getLangOpts().CPlusPlus) {
+    RHS = S.DefaultFunctionArrayLvalueConversion(RHS.take());
+    if (RHS.isInvalid())
+      return QualType();
+    if (!RHS.get()->getType()->isVoidType())
+      S.RequireCompleteType(Loc, RHS.get()->getType(),
+                            diag::err_incomplete_type);
+  }
+
+  return RHS.get()->getType();
+}
+
+/// CheckIncrementDecrementOperand - unlike most "Check" methods, this routine
+/// doesn't need to call UsualUnaryConversions or UsualArithmeticConversions.
+static QualType CheckIncrementDecrementOperand(Sema &S, Expr *Op,
+                                               ExprValueKind &VK,
+                                               SourceLocation OpLoc,
+                                               bool IsInc, bool IsPrefix) {
+  if (Op->isTypeDependent())
+    return S.Context.DependentTy;
+
+  QualType ResType = Op->getType();
+  // Atomic types can be used for increment / decrement where the non-atomic
+  // versions can, so ignore the _Atomic() specifier for the purpose of
+  // checking.
+  if (const AtomicType *ResAtomicType = ResType->getAs<AtomicType>())
+    ResType = ResAtomicType->getValueType();
+
+  assert(!ResType.isNull() && "no type for increment/decrement expression");
+
+  if (S.getLangOpts().CPlusPlus && ResType->isBooleanType()) {
+    // Decrement of bool is not allowed.
+    if (!IsInc) {
+      S.Diag(OpLoc, diag::err_decrement_bool) << Op->getSourceRange();
+      return QualType();
+    }
+    // Increment of bool sets it to true, but is deprecated.
+    S.Diag(OpLoc, diag::warn_increment_bool) << Op->getSourceRange();
+  } else if (ResType->isRealType()) {
+    // OK!
+  } else if (ResType->isAnyPointerType()) {
+    // C99 6.5.2.4p2, 6.5.6p2
+    if (!checkArithmeticOpPointerOperand(S, OpLoc, Op))
+      return QualType();
+
+    // Diagnose bad cases where we step over interface counts.
+    else if (!checkArithmethicPointerOnNonFragileABI(S, OpLoc, Op))
+      return QualType();
+  } else if (ResType->isAnyComplexType()) {
+    // C99 does not support ++/-- on complex types, we allow as an extension.
+    S.Diag(OpLoc, diag::ext_integer_increment_complex)
+      << ResType << Op->getSourceRange();
+  } else if (ResType->isPlaceholderType()) {
+    ExprResult PR = S.CheckPlaceholderExpr(Op);
+    if (PR.isInvalid()) return QualType();
+    return CheckIncrementDecrementOperand(S, PR.take(), VK, OpLoc,
+                                          IsInc, IsPrefix);
+  } else if (S.getLangOpts().AltiVec && ResType->isVectorType()) {
+    // OK! ( C/C++ Language Extensions for CBEA(Version 2.6) 10.3 )
+  } else {
+    S.Diag(OpLoc, diag::err_typecheck_illegal_increment_decrement)
+      << ResType << int(IsInc) << Op->getSourceRange();
+    return QualType();
+  }
+  // At this point, we know we have a real, complex or pointer type.
+  // Now make sure the operand is a modifiable lvalue.
+  if (CheckForModifiableLvalue(Op, OpLoc, S))
+    return QualType();
+  // In C++, a prefix increment is the same type as the operand. Otherwise
+  // (in C or with postfix), the increment is the unqualified type of the
+  // operand.
+  if (IsPrefix && S.getLangOpts().CPlusPlus) {
+    VK = VK_LValue;
+    return ResType;
+  } else {
+    VK = VK_RValue;
+    return ResType.getUnqualifiedType();
+  }
+}
+  
+
+/// getPrimaryDecl - Helper function for CheckAddressOfOperand().
+/// This routine allows us to typecheck complex/recursive expressions
+/// where the declaration is needed for type checking. We only need to
+/// handle cases when the expression references a function designator
+/// or is an lvalue. Here are some examples:
+///  - &(x) => x
+///  - &*****f => f for f a function designator.
+///  - &s.xx => s
+///  - &s.zz[1].yy -> s, if zz is an array
+///  - *(x + 1) -> x, if x is an array
+///  - &"123"[2] -> 0
+///  - & __real__ x -> x
+static ValueDecl *getPrimaryDecl(Expr *E) {
+  switch (E->getStmtClass()) {
+  case Stmt::DeclRefExprClass:
+    return cast<DeclRefExpr>(E)->getDecl();
+  case Stmt::MemberExprClass:
+    // If this is an arrow operator, the address is an offset from
+    // the base's value, so the object the base refers to is
+    // irrelevant.
+    if (cast<MemberExpr>(E)->isArrow())
+      return 0;
+    // Otherwise, the expression refers to a part of the base
+    return getPrimaryDecl(cast<MemberExpr>(E)->getBase());
+  case Stmt::ArraySubscriptExprClass: {
+    // FIXME: This code shouldn't be necessary!  We should catch the implicit
+    // promotion of register arrays earlier.
+    Expr* Base = cast<ArraySubscriptExpr>(E)->getBase();
+    if (ImplicitCastExpr* ICE = dyn_cast<ImplicitCastExpr>(Base)) {
+      if (ICE->getSubExpr()->getType()->isArrayType())
+        return getPrimaryDecl(ICE->getSubExpr());
+    }
+    return 0;
+  }
+  case Stmt::UnaryOperatorClass: {
+    UnaryOperator *UO = cast<UnaryOperator>(E);
+
+    switch(UO->getOpcode()) {
+    case UO_Real:
+    case UO_Imag:
+    case UO_Extension:
+      return getPrimaryDecl(UO->getSubExpr());
+    default:
+      return 0;
+    }
+  }
+  case Stmt::ParenExprClass:
+    return getPrimaryDecl(cast<ParenExpr>(E)->getSubExpr());
+  case Stmt::ImplicitCastExprClass:
+    // If the result of an implicit cast is an l-value, we care about
+    // the sub-expression; otherwise, the result here doesn't matter.
+    return getPrimaryDecl(cast<ImplicitCastExpr>(E)->getSubExpr());
+  default:
+    return 0;
+  }
+}
+
+namespace {
+  enum {
+    AO_Bit_Field = 0,
+    AO_Vector_Element = 1,
+    AO_Property_Expansion = 2,
+    AO_Register_Variable = 3,
+    AO_No_Error = 4
+  };
+}
+/// \brief Diagnose invalid operand for address of operations.
+///
+/// \param Type The type of operand which cannot have its address taken.
+static void diagnoseAddressOfInvalidType(Sema &S, SourceLocation Loc,
+                                         Expr *E, unsigned Type) {
+  S.Diag(Loc, diag::err_typecheck_address_of) << Type << E->getSourceRange();
+}
+
+/// CheckAddressOfOperand - The operand of & must be either a function
+/// designator or an lvalue designating an object. If it is an lvalue, the
+/// object cannot be declared with storage class register or be a bit field.
+/// Note: The usual conversions are *not* applied to the operand of the &
+/// operator (C99 6.3.2.1p[2-4]), and its result is never an lvalue.
+/// In C++, the operand might be an overloaded function name, in which case
+/// we allow the '&' but retain the overloaded-function type.
+static QualType CheckAddressOfOperand(Sema &S, ExprResult &OrigOp,
+                                      SourceLocation OpLoc) {
+  if (const BuiltinType *PTy = OrigOp.get()->getType()->getAsPlaceholderType()){
+    if (PTy->getKind() == BuiltinType::Overload) {
+      if (!isa<OverloadExpr>(OrigOp.get()->IgnoreParens())) {
+        S.Diag(OpLoc, diag::err_typecheck_invalid_lvalue_addrof)
+          << OrigOp.get()->getSourceRange();
+        return QualType();
+      }
+                  
+      return S.Context.OverloadTy;
+    }
+
+    if (PTy->getKind() == BuiltinType::UnknownAny)
+      return S.Context.UnknownAnyTy;
+
+    if (PTy->getKind() == BuiltinType::BoundMember) {
+      S.Diag(OpLoc, diag::err_invalid_form_pointer_member_function)
+        << OrigOp.get()->getSourceRange();
+      return QualType();
+    }
+
+    OrigOp = S.CheckPlaceholderExpr(OrigOp.take());
+    if (OrigOp.isInvalid()) return QualType();
+  }
+
+  if (OrigOp.get()->isTypeDependent())
+    return S.Context.DependentTy;
+
+  assert(!OrigOp.get()->getType()->isPlaceholderType());
+
+  // Make sure to ignore parentheses in subsequent checks
+  Expr *op = OrigOp.get()->IgnoreParens();
+
+  if (S.getLangOpts().C99) {
+    // Implement C99-only parts of addressof rules.
+    if (UnaryOperator* uOp = dyn_cast<UnaryOperator>(op)) {
+      if (uOp->getOpcode() == UO_Deref)
+        // Per C99 6.5.3.2, the address of a deref always returns a valid result
+        // (assuming the deref expression is valid).
+        return uOp->getSubExpr()->getType();
+    }
+    // Technically, there should be a check for array subscript
+    // expressions here, but the result of one is always an lvalue anyway.
+  }
+  ValueDecl *dcl = getPrimaryDecl(op);
+  Expr::LValueClassification lval = op->ClassifyLValue(S.Context);
+  unsigned AddressOfError = AO_No_Error;
+
+  if (lval == Expr::LV_ClassTemporary) { 
+    bool sfinae = S.isSFINAEContext();
+    S.Diag(OpLoc, sfinae ? diag::err_typecheck_addrof_class_temporary
+                         : diag::ext_typecheck_addrof_class_temporary)
+      << op->getType() << op->getSourceRange();
+    if (sfinae)
+      return QualType();
+  } else if (isa<ObjCSelectorExpr>(op)) {
+    return S.Context.getPointerType(op->getType());
+  } else if (lval == Expr::LV_MemberFunction) {
+    // If it's an instance method, make a member pointer.
+    // The expression must have exactly the form &A::foo.
+
+    // If the underlying expression isn't a decl ref, give up.
+    if (!isa<DeclRefExpr>(op)) {
+      S.Diag(OpLoc, diag::err_invalid_form_pointer_member_function)
+        << OrigOp.get()->getSourceRange();
+      return QualType();
+    }
+    DeclRefExpr *DRE = cast<DeclRefExpr>(op);
+    CXXMethodDecl *MD = cast<CXXMethodDecl>(DRE->getDecl());
+
+    // The id-expression was parenthesized.
+    if (OrigOp.get() != DRE) {
+      S.Diag(OpLoc, diag::err_parens_pointer_member_function)
+        << OrigOp.get()->getSourceRange();
+
+    // The method was named without a qualifier.
+    } else if (!DRE->getQualifier()) {
+      S.Diag(OpLoc, diag::err_unqualified_pointer_member_function)
+        << op->getSourceRange();
+    }
+
+    return S.Context.getMemberPointerType(op->getType(),
+              S.Context.getTypeDeclType(MD->getParent()).getTypePtr());
+  } else if (lval != Expr::LV_Valid && lval != Expr::LV_IncompleteVoidType) {
+    // C99 6.5.3.2p1
+    // The operand must be either an l-value or a function designator
+    if (!op->getType()->isFunctionType()) {
+      // Use a special diagnostic for loads from property references.
+      if (isa<PseudoObjectExpr>(op)) {
+        AddressOfError = AO_Property_Expansion;
+      } else {
+        // FIXME: emit more specific diag...
+        S.Diag(OpLoc, diag::err_typecheck_invalid_lvalue_addrof)
+          << op->getSourceRange();
+        return QualType();
+      }
+    }
+  } else if (op->getObjectKind() == OK_BitField) { // C99 6.5.3.2p1
+    // The operand cannot be a bit-field
+    AddressOfError = AO_Bit_Field;
+  } else if (op->getObjectKind() == OK_VectorComponent) {
+    // The operand cannot be an element of a vector
+    AddressOfError = AO_Vector_Element;
+  } else if (dcl) { // C99 6.5.3.2p1
+    // We have an lvalue with a decl. Make sure the decl is not declared
+    // with the register storage-class specifier.
+    if (const VarDecl *vd = dyn_cast<VarDecl>(dcl)) {
+      // in C++ it is not error to take address of a register
+      // variable (c++03 7.1.1P3)
+      if (vd->getStorageClass() == SC_Register &&
+          !S.getLangOpts().CPlusPlus) {
+        AddressOfError = AO_Register_Variable;
+      }
+    } else if (isa<FunctionTemplateDecl>(dcl)) {
+      return S.Context.OverloadTy;
+    } else if (isa<FieldDecl>(dcl) || isa<IndirectFieldDecl>(dcl)) {
+      // Okay: we can take the address of a field.
+      // Could be a pointer to member, though, if there is an explicit
+      // scope qualifier for the class.
+      if (isa<DeclRefExpr>(op) && cast<DeclRefExpr>(op)->getQualifier()) {
+        DeclContext *Ctx = dcl->getDeclContext();
+        if (Ctx && Ctx->isRecord()) {
+          if (dcl->getType()->isReferenceType()) {
+            S.Diag(OpLoc,
+                   diag::err_cannot_form_pointer_to_member_of_reference_type)
+              << dcl->getDeclName() << dcl->getType();
+            return QualType();
+          }
+
+          while (cast<RecordDecl>(Ctx)->isAnonymousStructOrUnion())
+            Ctx = Ctx->getParent();
+          return S.Context.getMemberPointerType(op->getType(),
+                S.Context.getTypeDeclType(cast<RecordDecl>(Ctx)).getTypePtr());
+        }
+      }
+    } else if (!isa<FunctionDecl>(dcl) && !isa<NonTypeTemplateParmDecl>(dcl))
+      llvm_unreachable("Unknown/unexpected decl type");
+  }
+
+  if (AddressOfError != AO_No_Error) {
+    diagnoseAddressOfInvalidType(S, OpLoc, op, AddressOfError);
+    return QualType();
+  }
+
+  if (lval == Expr::LV_IncompleteVoidType) {
+    // Taking the address of a void variable is technically illegal, but we
+    // allow it in cases which are otherwise valid.
+    // Example: "extern void x; void* y = &x;".
+    S.Diag(OpLoc, diag::ext_typecheck_addrof_void) << op->getSourceRange();
+  }
+
+  // If the operand has type "type", the result has type "pointer to type".
+  if (op->getType()->isObjCObjectType())
+    return S.Context.getObjCObjectPointerType(op->getType());
+  return S.Context.getPointerType(op->getType());
+}
+
+/// CheckIndirectionOperand - Type check unary indirection (prefix '*').
+static QualType CheckIndirectionOperand(Sema &S, Expr *Op, ExprValueKind &VK,
+                                        SourceLocation OpLoc) {
+  if (Op->isTypeDependent())
+    return S.Context.DependentTy;
+
+  ExprResult ConvResult = S.UsualUnaryConversions(Op);
+  if (ConvResult.isInvalid())
+    return QualType();
+  Op = ConvResult.take();
+  QualType OpTy = Op->getType();
+  QualType Result;
+
+  if (isa<CXXReinterpretCastExpr>(Op)) {
+    QualType OpOrigType = Op->IgnoreParenCasts()->getType();
+    S.CheckCompatibleReinterpretCast(OpOrigType, OpTy, /*IsDereference*/true,
+                                     Op->getSourceRange());
+  }
+
+  // Note that per both C89 and C99, indirection is always legal, even if OpTy
+  // is an incomplete type or void.  It would be possible to warn about
+  // dereferencing a void pointer, but it's completely well-defined, and such a
+  // warning is unlikely to catch any mistakes.
+  if (const PointerType *PT = OpTy->getAs<PointerType>())
+    Result = PT->getPointeeType();
+  else if (const ObjCObjectPointerType *OPT =
+             OpTy->getAs<ObjCObjectPointerType>())
+    Result = OPT->getPointeeType();
+  else {
+    ExprResult PR = S.CheckPlaceholderExpr(Op);
+    if (PR.isInvalid()) return QualType();
+    if (PR.take() != Op)
+      return CheckIndirectionOperand(S, PR.take(), VK, OpLoc);
+  }
+
+  if (Result.isNull()) {
+    S.Diag(OpLoc, diag::err_typecheck_indirection_requires_pointer)
+      << OpTy << Op->getSourceRange();
+    return QualType();
+  }
+
+  // Dereferences are usually l-values...
+  VK = VK_LValue;
+
+  // ...except that certain expressions are never l-values in C.
+  if (!S.getLangOpts().CPlusPlus && Result.isCForbiddenLValueType())
+    VK = VK_RValue;
+  
+  return Result;
+}
+
+static inline BinaryOperatorKind ConvertTokenKindToBinaryOpcode(
+  tok::TokenKind Kind) {
+  BinaryOperatorKind Opc;
+  switch (Kind) {
+  default: llvm_unreachable("Unknown binop!");
+  case tok::periodstar:           Opc = BO_PtrMemD; break;
+  case tok::arrowstar:            Opc = BO_PtrMemI; break;
+  case tok::star:                 Opc = BO_Mul; break;
+  case tok::slash:                Opc = BO_Div; break;
+  case tok::percent:              Opc = BO_Rem; break;
+  case tok::plus:                 Opc = BO_Add; break;
+  case tok::minus:                Opc = BO_Sub; break;
+  case tok::lessless:             Opc = BO_Shl; break;
+  case tok::greatergreater:       Opc = BO_Shr; break;
+  case tok::lessequal:            Opc = BO_LE; break;
+  case tok::less:                 Opc = BO_LT; break;
+  case tok::greaterequal:         Opc = BO_GE; break;
+  case tok::greater:              Opc = BO_GT; break;
+  case tok::exclaimequal:         Opc = BO_NE; break;
+  case tok::equalequal:           Opc = BO_EQ; break;
+  case tok::amp:                  Opc = BO_And; break;
+  case tok::caret:                Opc = BO_Xor; break;
+  case tok::pipe:                 Opc = BO_Or; break;
+  case tok::ampamp:               Opc = BO_LAnd; break;
+  case tok::pipepipe:             Opc = BO_LOr; break;
+  case tok::equal:                Opc = BO_Assign; break;
+  case tok::starequal:            Opc = BO_MulAssign; break;
+  case tok::slashequal:           Opc = BO_DivAssign; break;
+  case tok::percentequal:         Opc = BO_RemAssign; break;
+  case tok::plusequal:            Opc = BO_AddAssign; break;
+  case tok::minusequal:           Opc = BO_SubAssign; break;
+  case tok::lesslessequal:        Opc = BO_ShlAssign; break;
+  case tok::greatergreaterequal:  Opc = BO_ShrAssign; break;
+  case tok::ampequal:             Opc = BO_AndAssign; break;
+  case tok::caretequal:           Opc = BO_XorAssign; break;
+  case tok::pipeequal:            Opc = BO_OrAssign; break;
+  case tok::comma:                Opc = BO_Comma; break;
+  }
+  return Opc;
+}
+
+static inline UnaryOperatorKind ConvertTokenKindToUnaryOpcode(
+  tok::TokenKind Kind) {
+  UnaryOperatorKind Opc;
+  switch (Kind) {
+  default: llvm_unreachable("Unknown unary op!");
+  case tok::plusplus:     Opc = UO_PreInc; break;
+  case tok::minusminus:   Opc = UO_PreDec; break;
+  case tok::amp:          Opc = UO_AddrOf; break;
+  case tok::star:         Opc = UO_Deref; break;
+  case tok::plus:         Opc = UO_Plus; break;
+  case tok::minus:        Opc = UO_Minus; break;
+  case tok::tilde:        Opc = UO_Not; break;
+  case tok::exclaim:      Opc = UO_LNot; break;
+  case tok::kw___real:    Opc = UO_Real; break;
+  case tok::kw___imag:    Opc = UO_Imag; break;
+  case tok::kw___extension__: Opc = UO_Extension; break;
+  }
+  return Opc;
+}
+
+/// DiagnoseSelfAssignment - Emits a warning if a value is assigned to itself.
+/// This warning is only emitted for builtin assignment operations. It is also
+/// suppressed in the event of macro expansions.
+static void DiagnoseSelfAssignment(Sema &S, Expr *LHSExpr, Expr *RHSExpr,
+                                   SourceLocation OpLoc) {
+  if (!S.ActiveTemplateInstantiations.empty())
+    return;
+  if (OpLoc.isInvalid() || OpLoc.isMacroID())
+    return;
+  LHSExpr = LHSExpr->IgnoreParenImpCasts();
+  RHSExpr = RHSExpr->IgnoreParenImpCasts();
+  const DeclRefExpr *LHSDeclRef = dyn_cast<DeclRefExpr>(LHSExpr);
+  const DeclRefExpr *RHSDeclRef = dyn_cast<DeclRefExpr>(RHSExpr);
+  if (!LHSDeclRef || !RHSDeclRef ||
+      LHSDeclRef->getLocation().isMacroID() ||
+      RHSDeclRef->getLocation().isMacroID())
+    return;
+  const ValueDecl *LHSDecl =
+    cast<ValueDecl>(LHSDeclRef->getDecl()->getCanonicalDecl());
+  const ValueDecl *RHSDecl =
+    cast<ValueDecl>(RHSDeclRef->getDecl()->getCanonicalDecl());
+  if (LHSDecl != RHSDecl)
+    return;
+  if (LHSDecl->getType().isVolatileQualified())
+    return;
+  if (const ReferenceType *RefTy = LHSDecl->getType()->getAs<ReferenceType>())
+    if (RefTy->getPointeeType().isVolatileQualified())
+      return;
+
+  S.Diag(OpLoc, diag::warn_self_assignment)
+      << LHSDeclRef->getType()
+      << LHSExpr->getSourceRange() << RHSExpr->getSourceRange();
+}
+
+/// CreateBuiltinBinOp - Creates a new built-in binary operation with
+/// operator @p Opc at location @c TokLoc. This routine only supports
+/// built-in operations; ActOnBinOp handles overloaded operators.
+ExprResult Sema::CreateBuiltinBinOp(SourceLocation OpLoc,
+                                    BinaryOperatorKind Opc,
+                                    Expr *LHSExpr, Expr *RHSExpr) {
+  if (getLangOpts().CPlusPlus0x && isa<InitListExpr>(RHSExpr)) {
+    // The syntax only allows initializer lists on the RHS of assignment,
+    // so we don't need to worry about accepting invalid code for
+    // non-assignment operators.
+    // C++11 5.17p9:
+    //   The meaning of x = {v} [...] is that of x = T(v) [...]. The meaning
+    //   of x = {} is x = T().
+    InitializationKind Kind =
+        InitializationKind::CreateDirectList(RHSExpr->getLocStart());
+    InitializedEntity Entity =
+        InitializedEntity::InitializeTemporary(LHSExpr->getType());
+    InitializationSequence InitSeq(*this, Entity, Kind, &RHSExpr, 1);
+    ExprResult Init = InitSeq.Perform(*this, Entity, Kind,
+                                      MultiExprArg(&RHSExpr, 1));
+    if (Init.isInvalid())
+      return Init;
+    RHSExpr = Init.take();
+  }
+
+  ExprResult LHS = Owned(LHSExpr), RHS = Owned(RHSExpr);
+  QualType ResultTy;     // Result type of the binary operator.
+  // The following two variables are used for compound assignment operators
+  QualType CompLHSTy;    // Type of LHS after promotions for computation
+  QualType CompResultTy; // Type of computation result
+  ExprValueKind VK = VK_RValue;
+  ExprObjectKind OK = OK_Ordinary;
+
+  switch (Opc) {
+  case BO_Assign:
+    ResultTy = CheckAssignmentOperands(LHS.get(), RHS, OpLoc, QualType());
+    if (getLangOpts().CPlusPlus &&
+        LHS.get()->getObjectKind() != OK_ObjCProperty) {
+      VK = LHS.get()->getValueKind();
+      OK = LHS.get()->getObjectKind();
+    }
+    if (!ResultTy.isNull())
+      DiagnoseSelfAssignment(*this, LHS.get(), RHS.get(), OpLoc);
+    break;
+  case BO_PtrMemD:
+  case BO_PtrMemI:
+    ResultTy = CheckPointerToMemberOperands(LHS, RHS, VK, OpLoc,
+                                            Opc == BO_PtrMemI);
+    break;
+  case BO_Mul:
+  case BO_Div:
+    ResultTy = CheckMultiplyDivideOperands(LHS, RHS, OpLoc, false,
+                                           Opc == BO_Div);
+    break;
+  case BO_Rem:
+    ResultTy = CheckRemainderOperands(LHS, RHS, OpLoc);
+    break;
+  case BO_Add:
+    ResultTy = CheckAdditionOperands(LHS, RHS, OpLoc, Opc);
+    break;
+  case BO_Sub:
+    ResultTy = CheckSubtractionOperands(LHS, RHS, OpLoc);
+    break;
+  case BO_Shl:
+  case BO_Shr:
+    ResultTy = CheckShiftOperands(LHS, RHS, OpLoc, Opc);
+    break;
+  case BO_LE:
+  case BO_LT:
+  case BO_GE:
+  case BO_GT:
+    ResultTy = CheckCompareOperands(LHS, RHS, OpLoc, Opc, true);
+    break;
+  case BO_EQ:
+  case BO_NE:
+    ResultTy = CheckCompareOperands(LHS, RHS, OpLoc, Opc, false);
+    break;
+  case BO_And:
+  case BO_Xor:
+  case BO_Or:
+    ResultTy = CheckBitwiseOperands(LHS, RHS, OpLoc);
+    break;
+  case BO_LAnd:
+  case BO_LOr:
+    ResultTy = CheckLogicalOperands(LHS, RHS, OpLoc, Opc);
+    break;
+  case BO_MulAssign:
+  case BO_DivAssign:
+    CompResultTy = CheckMultiplyDivideOperands(LHS, RHS, OpLoc, true,
+                                               Opc == BO_DivAssign);
+    CompLHSTy = CompResultTy;
+    if (!CompResultTy.isNull() && !LHS.isInvalid() && !RHS.isInvalid())
+      ResultTy = CheckAssignmentOperands(LHS.get(), RHS, OpLoc, CompResultTy);
+    break;
+  case BO_RemAssign:
+    CompResultTy = CheckRemainderOperands(LHS, RHS, OpLoc, true);
+    CompLHSTy = CompResultTy;
+    if (!CompResultTy.isNull() && !LHS.isInvalid() && !RHS.isInvalid())
+      ResultTy = CheckAssignmentOperands(LHS.get(), RHS, OpLoc, CompResultTy);
+    break;
+  case BO_AddAssign:
+    CompResultTy = CheckAdditionOperands(LHS, RHS, OpLoc, Opc, &CompLHSTy);
+    if (!CompResultTy.isNull() && !LHS.isInvalid() && !RHS.isInvalid())
+      ResultTy = CheckAssignmentOperands(LHS.get(), RHS, OpLoc, CompResultTy);
+    break;
+  case BO_SubAssign:
+    CompResultTy = CheckSubtractionOperands(LHS, RHS, OpLoc, &CompLHSTy);
+    if (!CompResultTy.isNull() && !LHS.isInvalid() && !RHS.isInvalid())
+      ResultTy = CheckAssignmentOperands(LHS.get(), RHS, OpLoc, CompResultTy);
+    break;
+  case BO_ShlAssign:
+  case BO_ShrAssign:
+    CompResultTy = CheckShiftOperands(LHS, RHS, OpLoc, Opc, true);
+    CompLHSTy = CompResultTy;
+    if (!CompResultTy.isNull() && !LHS.isInvalid() && !RHS.isInvalid())
+      ResultTy = CheckAssignmentOperands(LHS.get(), RHS, OpLoc, CompResultTy);
+    break;
+  case BO_AndAssign:
+  case BO_XorAssign:
+  case BO_OrAssign:
+    CompResultTy = CheckBitwiseOperands(LHS, RHS, OpLoc, true);
+    CompLHSTy = CompResultTy;
+    if (!CompResultTy.isNull() && !LHS.isInvalid() && !RHS.isInvalid())
+      ResultTy = CheckAssignmentOperands(LHS.get(), RHS, OpLoc, CompResultTy);
+    break;
+  case BO_Comma:
+    ResultTy = CheckCommaOperands(*this, LHS, RHS, OpLoc);
+    if (getLangOpts().CPlusPlus && !RHS.isInvalid()) {
+      VK = RHS.get()->getValueKind();
+      OK = RHS.get()->getObjectKind();
+    }
+    break;
+  }
+  if (ResultTy.isNull() || LHS.isInvalid() || RHS.isInvalid())
+    return ExprError();
+
+  // Check for array bounds violations for both sides of the BinaryOperator
+  CheckArrayAccess(LHS.get());
+  CheckArrayAccess(RHS.get());
+
+  if (CompResultTy.isNull())
+    return Owned(new (Context) BinaryOperator(LHS.take(), RHS.take(), Opc,
+                                              ResultTy, VK, OK, OpLoc));
+  if (getLangOpts().CPlusPlus && LHS.get()->getObjectKind() !=
+      OK_ObjCProperty) {
+    VK = VK_LValue;
+    OK = LHS.get()->getObjectKind();
+  }
+  return Owned(new (Context) CompoundAssignOperator(LHS.take(), RHS.take(), Opc,
+                                                    ResultTy, VK, OK, CompLHSTy,
+                                                    CompResultTy, OpLoc));
+}
+
+/// DiagnoseBitwisePrecedence - Emit a warning when bitwise and comparison
+/// operators are mixed in a way that suggests that the programmer forgot that
+/// comparison operators have higher precedence. The most typical example of
+/// such code is "flags & 0x0020 != 0", which is equivalent to "flags & 1".
+static void DiagnoseBitwisePrecedence(Sema &Self, BinaryOperatorKind Opc,
+                                      SourceLocation OpLoc, Expr *LHSExpr,
+                                      Expr *RHSExpr) {
+  typedef BinaryOperator BinOp;
+  BinOp::Opcode LHSopc = static_cast<BinOp::Opcode>(-1),
+                RHSopc = static_cast<BinOp::Opcode>(-1);
+  if (BinOp *BO = dyn_cast<BinOp>(LHSExpr))
+    LHSopc = BO->getOpcode();
+  if (BinOp *BO = dyn_cast<BinOp>(RHSExpr))
+    RHSopc = BO->getOpcode();
+
+  // Subs are not binary operators.
+  if (LHSopc == -1 && RHSopc == -1)
+    return;
+
+  // Bitwise operations are sometimes used as eager logical ops.
+  // Don't diagnose this.
+  if ((BinOp::isComparisonOp(LHSopc) || BinOp::isBitwiseOp(LHSopc)) &&
+      (BinOp::isComparisonOp(RHSopc) || BinOp::isBitwiseOp(RHSopc)))
+    return;
+
+  bool isLeftComp = BinOp::isComparisonOp(LHSopc);
+  bool isRightComp = BinOp::isComparisonOp(RHSopc);
+  if (!isLeftComp && !isRightComp) return;
+
+  SourceRange DiagRange = isLeftComp ? SourceRange(LHSExpr->getLocStart(),
+                                                   OpLoc)
+                                     : SourceRange(OpLoc, RHSExpr->getLocEnd());
+  std::string OpStr = isLeftComp ? BinOp::getOpcodeStr(LHSopc)
+                                 : BinOp::getOpcodeStr(RHSopc);
+  SourceRange ParensRange = isLeftComp ?
+      SourceRange(cast<BinOp>(LHSExpr)->getRHS()->getLocStart(),
+                  RHSExpr->getLocEnd())
+    : SourceRange(LHSExpr->getLocStart(),
+                  cast<BinOp>(RHSExpr)->getLHS()->getLocStart());
+
+  Self.Diag(OpLoc, diag::warn_precedence_bitwise_rel)
+    << DiagRange << BinOp::getOpcodeStr(Opc) << OpStr;
+  SuggestParentheses(Self, OpLoc,
+    Self.PDiag(diag::note_precedence_bitwise_silence) << OpStr,
+    RHSExpr->getSourceRange());
+  SuggestParentheses(Self, OpLoc,
+    Self.PDiag(diag::note_precedence_bitwise_first) << BinOp::getOpcodeStr(Opc),
+    ParensRange);
+}
+
+/// \brief It accepts a '&' expr that is inside a '|' one.
+/// Emit a diagnostic together with a fixit hint that wraps the '&' expression
+/// in parentheses.
+static void
+EmitDiagnosticForBitwiseAndInBitwiseOr(Sema &Self, SourceLocation OpLoc,
+                                       BinaryOperator *Bop) {
+  assert(Bop->getOpcode() == BO_And);
+  Self.Diag(Bop->getOperatorLoc(), diag::warn_bitwise_and_in_bitwise_or)
+      << Bop->getSourceRange() << OpLoc;
+  SuggestParentheses(Self, Bop->getOperatorLoc(),
+    Self.PDiag(diag::note_bitwise_and_in_bitwise_or_silence),
+    Bop->getSourceRange());
+}
+
+/// \brief It accepts a '&&' expr that is inside a '||' one.
+/// Emit a diagnostic together with a fixit hint that wraps the '&&' expression
+/// in parentheses.
+static void
+EmitDiagnosticForLogicalAndInLogicalOr(Sema &Self, SourceLocation OpLoc,
+                                       BinaryOperator *Bop) {
+  assert(Bop->getOpcode() == BO_LAnd);
+  Self.Diag(Bop->getOperatorLoc(), diag::warn_logical_and_in_logical_or)
+      << Bop->getSourceRange() << OpLoc;
+  SuggestParentheses(Self, Bop->getOperatorLoc(),
+    Self.PDiag(diag::note_logical_and_in_logical_or_silence),
+    Bop->getSourceRange());
+}
+
+/// \brief Returns true if the given expression can be evaluated as a constant
+/// 'true'.
+static bool EvaluatesAsTrue(Sema &S, Expr *E) {
+  bool Res;
+  return E->EvaluateAsBooleanCondition(Res, S.getASTContext()) && Res;
+}
+
+/// \brief Returns true if the given expression can be evaluated as a constant
+/// 'false'.
+static bool EvaluatesAsFalse(Sema &S, Expr *E) {
+  bool Res;
+  return E->EvaluateAsBooleanCondition(Res, S.getASTContext()) && !Res;
+}
+
+/// \brief Look for '&&' in the left hand of a '||' expr.
+static void DiagnoseLogicalAndInLogicalOrLHS(Sema &S, SourceLocation OpLoc,
+                                             Expr *LHSExpr, Expr *RHSExpr) {
+  if (BinaryOperator *Bop = dyn_cast<BinaryOperator>(LHSExpr)) {
+    if (Bop->getOpcode() == BO_LAnd) {
+      // If it's "a && b || 0" don't warn since the precedence doesn't matter.
+      if (EvaluatesAsFalse(S, RHSExpr))
+        return;
+      // If it's "1 && a || b" don't warn since the precedence doesn't matter.
+      if (!EvaluatesAsTrue(S, Bop->getLHS()))
+        return EmitDiagnosticForLogicalAndInLogicalOr(S, OpLoc, Bop);
+    } else if (Bop->getOpcode() == BO_LOr) {
+      if (BinaryOperator *RBop = dyn_cast<BinaryOperator>(Bop->getRHS())) {
+        // If it's "a || b && 1 || c" we didn't warn earlier for
+        // "a || b && 1", but warn now.
+        if (RBop->getOpcode() == BO_LAnd && EvaluatesAsTrue(S, RBop->getRHS()))
+          return EmitDiagnosticForLogicalAndInLogicalOr(S, OpLoc, RBop);
+      }
+    }
+  }
+}
+
+/// \brief Look for '&&' in the right hand of a '||' expr.
+static void DiagnoseLogicalAndInLogicalOrRHS(Sema &S, SourceLocation OpLoc,
+                                             Expr *LHSExpr, Expr *RHSExpr) {
+  if (BinaryOperator *Bop = dyn_cast<BinaryOperator>(RHSExpr)) {
+    if (Bop->getOpcode() == BO_LAnd) {
+      // If it's "0 || a && b" don't warn since the precedence doesn't matter.
+      if (EvaluatesAsFalse(S, LHSExpr))
+        return;
+      // If it's "a || b && 1" don't warn since the precedence doesn't matter.
+      if (!EvaluatesAsTrue(S, Bop->getRHS()))
+        return EmitDiagnosticForLogicalAndInLogicalOr(S, OpLoc, Bop);
+    }
+  }
+}
+
+/// \brief Look for '&' in the left or right hand of a '|' expr.
+static void DiagnoseBitwiseAndInBitwiseOr(Sema &S, SourceLocation OpLoc,
+                                             Expr *OrArg) {
+  if (BinaryOperator *Bop = dyn_cast<BinaryOperator>(OrArg)) {
+    if (Bop->getOpcode() == BO_And)
+      return EmitDiagnosticForBitwiseAndInBitwiseOr(S, OpLoc, Bop);
+  }
+}
+
+/// DiagnoseBinOpPrecedence - Emit warnings for expressions with tricky
+/// precedence.
+static void DiagnoseBinOpPrecedence(Sema &Self, BinaryOperatorKind Opc,
+                                    SourceLocation OpLoc, Expr *LHSExpr,
+                                    Expr *RHSExpr){
+  // Diagnose "arg1 'bitwise' arg2 'eq' arg3".
+  if (BinaryOperator::isBitwiseOp(Opc))
+    DiagnoseBitwisePrecedence(Self, Opc, OpLoc, LHSExpr, RHSExpr);
+
+  // Diagnose "arg1 & arg2 | arg3"
+  if (Opc == BO_Or && !OpLoc.isMacroID()/* Don't warn in macros. */) {
+    DiagnoseBitwiseAndInBitwiseOr(Self, OpLoc, LHSExpr);
+    DiagnoseBitwiseAndInBitwiseOr(Self, OpLoc, RHSExpr);
+  }
+
+  // Warn about arg1 || arg2 && arg3, as GCC 4.3+ does.
+  // We don't warn for 'assert(a || b && "bad")' since this is safe.
+  if (Opc == BO_LOr && !OpLoc.isMacroID()/* Don't warn in macros. */) {
+    DiagnoseLogicalAndInLogicalOrLHS(Self, OpLoc, LHSExpr, RHSExpr);
+    DiagnoseLogicalAndInLogicalOrRHS(Self, OpLoc, LHSExpr, RHSExpr);
+  }
+}
+
+// Binary Operators.  'Tok' is the token for the operator.
+ExprResult Sema::ActOnBinOp(Scope *S, SourceLocation TokLoc,
+                            tok::TokenKind Kind,
+                            Expr *LHSExpr, Expr *RHSExpr) {
+  BinaryOperatorKind Opc = ConvertTokenKindToBinaryOpcode(Kind);
+  assert((LHSExpr != 0) && "ActOnBinOp(): missing left expression");
+  assert((RHSExpr != 0) && "ActOnBinOp(): missing right expression");
+
+  // Emit warnings for tricky precedence issues, e.g. "bitfield & 0x4 == 0"
+  DiagnoseBinOpPrecedence(*this, Opc, TokLoc, LHSExpr, RHSExpr);
+
+  return BuildBinOp(S, TokLoc, Opc, LHSExpr, RHSExpr);
+}
+
+/// Build an overloaded binary operator expression in the given scope.
+static ExprResult BuildOverloadedBinOp(Sema &S, Scope *Sc, SourceLocation OpLoc,
+                                       BinaryOperatorKind Opc,
+                                       Expr *LHS, Expr *RHS) {
+  // Find all of the overloaded operators visible from this
+  // point. We perform both an operator-name lookup from the local
+  // scope and an argument-dependent lookup based on the types of
+  // the arguments.
+  UnresolvedSet<16> Functions;
+  OverloadedOperatorKind OverOp
+    = BinaryOperator::getOverloadedOperator(Opc);
+  if (Sc && OverOp != OO_None)
+    S.LookupOverloadedOperatorName(OverOp, Sc, LHS->getType(),
+                                   RHS->getType(), Functions);
+
+  // Build the (potentially-overloaded, potentially-dependent)
+  // binary operation.
+  return S.CreateOverloadedBinOp(OpLoc, Opc, Functions, LHS, RHS);
+}
+
+ExprResult Sema::BuildBinOp(Scope *S, SourceLocation OpLoc,
+                            BinaryOperatorKind Opc,
+                            Expr *LHSExpr, Expr *RHSExpr) {
+  // We want to end up calling one of checkPseudoObjectAssignment
+  // (if the LHS is a pseudo-object), BuildOverloadedBinOp (if
+  // both expressions are overloadable or either is type-dependent),
+  // or CreateBuiltinBinOp (in any other case).  We also want to get
+  // any placeholder types out of the way.
+
+  // Handle pseudo-objects in the LHS.
+  if (const BuiltinType *pty = LHSExpr->getType()->getAsPlaceholderType()) {
+    // Assignments with a pseudo-object l-value need special analysis.
+    if (pty->getKind() == BuiltinType::PseudoObject &&
+        BinaryOperator::isAssignmentOp(Opc))
+      return checkPseudoObjectAssignment(S, OpLoc, Opc, LHSExpr, RHSExpr);
+
+    // Don't resolve overloads if the other type is overloadable.
+    if (pty->getKind() == BuiltinType::Overload) {
+      // We can't actually test that if we still have a placeholder,
+      // though.  Fortunately, none of the exceptions we see in that
+      // code below are valid when the LHS is an overload set.  Note
+      // that an overload set can be dependently-typed, but it never
+      // instantiates to having an overloadable type.
+      ExprResult resolvedRHS = CheckPlaceholderExpr(RHSExpr);
+      if (resolvedRHS.isInvalid()) return ExprError();
+      RHSExpr = resolvedRHS.take();
+
+      if (RHSExpr->isTypeDependent() ||
+          RHSExpr->getType()->isOverloadableType())
+        return BuildOverloadedBinOp(*this, S, OpLoc, Opc, LHSExpr, RHSExpr);
+    }
+        
+    ExprResult LHS = CheckPlaceholderExpr(LHSExpr);
+    if (LHS.isInvalid()) return ExprError();
+    LHSExpr = LHS.take();
+  }
+
+  // Handle pseudo-objects in the RHS.
+  if (const BuiltinType *pty = RHSExpr->getType()->getAsPlaceholderType()) {
+    // An overload in the RHS can potentially be resolved by the type
+    // being assigned to.
+    if (Opc == BO_Assign && pty->getKind() == BuiltinType::Overload) {
+      if (LHSExpr->isTypeDependent() || RHSExpr->isTypeDependent())
+        return BuildOverloadedBinOp(*this, S, OpLoc, Opc, LHSExpr, RHSExpr);
+
+      if (LHSExpr->getType()->isOverloadableType())
+        return BuildOverloadedBinOp(*this, S, OpLoc, Opc, LHSExpr, RHSExpr);
+
+      return CreateBuiltinBinOp(OpLoc, Opc, LHSExpr, RHSExpr);
+    }
+
+    // Don't resolve overloads if the other type is overloadable.
+    if (pty->getKind() == BuiltinType::Overload &&
+        LHSExpr->getType()->isOverloadableType())
+      return BuildOverloadedBinOp(*this, S, OpLoc, Opc, LHSExpr, RHSExpr);
+
+    ExprResult resolvedRHS = CheckPlaceholderExpr(RHSExpr);
+    if (!resolvedRHS.isUsable()) return ExprError();
+    RHSExpr = resolvedRHS.take();
+  }
+
+  if (getLangOpts().CPlusPlus) {
+    // If either expression is type-dependent, always build an
+    // overloaded op.
+    if (LHSExpr->isTypeDependent() || RHSExpr->isTypeDependent())
+      return BuildOverloadedBinOp(*this, S, OpLoc, Opc, LHSExpr, RHSExpr);
+
+    // Otherwise, build an overloaded op if either expression has an
+    // overloadable type.
+    if (LHSExpr->getType()->isOverloadableType() ||
+        RHSExpr->getType()->isOverloadableType())
+      return BuildOverloadedBinOp(*this, S, OpLoc, Opc, LHSExpr, RHSExpr);
+  }
+
+  // Build a built-in binary operation.
+  return CreateBuiltinBinOp(OpLoc, Opc, LHSExpr, RHSExpr);
+}
+
+ExprResult Sema::CreateBuiltinUnaryOp(SourceLocation OpLoc,
+                                      UnaryOperatorKind Opc,
+                                      Expr *InputExpr) {
+  ExprResult Input = Owned(InputExpr);
+  ExprValueKind VK = VK_RValue;
+  ExprObjectKind OK = OK_Ordinary;
+  QualType resultType;
+  switch (Opc) {
+  case UO_PreInc:
+  case UO_PreDec:
+  case UO_PostInc:
+  case UO_PostDec:
+    resultType = CheckIncrementDecrementOperand(*this, Input.get(), VK, OpLoc,
+                                                Opc == UO_PreInc ||
+                                                Opc == UO_PostInc,
+                                                Opc == UO_PreInc ||
+                                                Opc == UO_PreDec);
+    break;
+  case UO_AddrOf:
+    resultType = CheckAddressOfOperand(*this, Input, OpLoc);
+    break;
+  case UO_Deref: {
+    Input = DefaultFunctionArrayLvalueConversion(Input.take());
+    resultType = CheckIndirectionOperand(*this, Input.get(), VK, OpLoc);
+    break;
+  }
+  case UO_Plus:
+  case UO_Minus:
+    Input = UsualUnaryConversions(Input.take());
+    if (Input.isInvalid()) return ExprError();
+    resultType = Input.get()->getType();
+    if (resultType->isDependentType())
+      break;
+    if (resultType->isArithmeticType() || // C99 6.5.3.3p1
+        resultType->isVectorType()) 
+      break;
+    else if (getLangOpts().CPlusPlus && // C++ [expr.unary.op]p6-7
+             resultType->isEnumeralType())
+      break;
+    else if (getLangOpts().CPlusPlus && // C++ [expr.unary.op]p6
+             Opc == UO_Plus &&
+             resultType->isPointerType())
+      break;
+
+    return ExprError(Diag(OpLoc, diag::err_typecheck_unary_expr)
+      << resultType << Input.get()->getSourceRange());
+
+  case UO_Not: // bitwise complement
+    Input = UsualUnaryConversions(Input.take());
+    if (Input.isInvalid()) return ExprError();
+    resultType = Input.get()->getType();
+    if (resultType->isDependentType())
+      break;
+    // C99 6.5.3.3p1. We allow complex int and float as a GCC extension.
+    if (resultType->isComplexType() || resultType->isComplexIntegerType())
+      // C99 does not support '~' for complex conjugation.
+      Diag(OpLoc, diag::ext_integer_complement_complex)
+        << resultType << Input.get()->getSourceRange();
+    else if (resultType->hasIntegerRepresentation())
+      break;
+    else {
+      return ExprError(Diag(OpLoc, diag::err_typecheck_unary_expr)
+        << resultType << Input.get()->getSourceRange());
+    }
+    break;
+
+  case UO_LNot: // logical negation
+    // Unlike +/-/~, integer promotions aren't done here (C99 6.5.3.3p5).
+    Input = DefaultFunctionArrayLvalueConversion(Input.take());
+    if (Input.isInvalid()) return ExprError();
+    resultType = Input.get()->getType();
+
+    // Though we still have to promote half FP to float...
+    if (resultType->isHalfType()) {
+      Input = ImpCastExprToType(Input.take(), Context.FloatTy, CK_FloatingCast).take();
+      resultType = Context.FloatTy;
+    }
+
+    if (resultType->isDependentType())
+      break;
+    if (resultType->isScalarType()) {
+      // C99 6.5.3.3p1: ok, fallthrough;
+      if (Context.getLangOpts().CPlusPlus) {
+        // C++03 [expr.unary.op]p8, C++0x [expr.unary.op]p9:
+        // operand contextually converted to bool.
+        Input = ImpCastExprToType(Input.take(), Context.BoolTy,
+                                  ScalarTypeToBooleanCastKind(resultType));
+      }
+    } else if (resultType->isExtVectorType()) {
+      // Vector logical not returns the signed variant of the operand type.
+      resultType = GetSignedVectorType(resultType);
+      break;
+    } else {
+      return ExprError(Diag(OpLoc, diag::err_typecheck_unary_expr)
+        << resultType << Input.get()->getSourceRange());
+    }
+    
+    // LNot always has type int. C99 6.5.3.3p5.
+    // In C++, it's bool. C++ 5.3.1p8
+    resultType = Context.getLogicalOperationType();
+    break;
+  case UO_Real:
+  case UO_Imag:
+    resultType = CheckRealImagOperand(*this, Input, OpLoc, Opc == UO_Real);
+    // _Real maps ordinary l-values into ordinary l-values. _Imag maps ordinary
+    // complex l-values to ordinary l-values and all other values to r-values.
+    if (Input.isInvalid()) return ExprError();
+    if (Opc == UO_Real || Input.get()->getType()->isAnyComplexType()) {
+      if (Input.get()->getValueKind() != VK_RValue &&
+          Input.get()->getObjectKind() == OK_Ordinary)
+        VK = Input.get()->getValueKind();
+    } else if (!getLangOpts().CPlusPlus) {
+      // In C, a volatile scalar is read by __imag. In C++, it is not.
+      Input = DefaultLvalueConversion(Input.take());
+    }
+    break;
+  case UO_Extension:
+    resultType = Input.get()->getType();
+    VK = Input.get()->getValueKind();
+    OK = Input.get()->getObjectKind();
+    break;
+  }
+  if (resultType.isNull() || Input.isInvalid())
+    return ExprError();
+
+  // Check for array bounds violations in the operand of the UnaryOperator,
+  // except for the '*' and '&' operators that have to be handled specially
+  // by CheckArrayAccess (as there are special cases like &array[arraysize]
+  // that are explicitly defined as valid by the standard).
+  if (Opc != UO_AddrOf && Opc != UO_Deref)
+    CheckArrayAccess(Input.get());
+
+  return Owned(new (Context) UnaryOperator(Input.take(), Opc, resultType,
+                                           VK, OK, OpLoc));
+}
+
+/// \brief Determine whether the given expression is a qualified member
+/// access expression, of a form that could be turned into a pointer to member
+/// with the address-of operator.
+static bool isQualifiedMemberAccess(Expr *E) {
+  if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) {
+    if (!DRE->getQualifier())
+      return false;
+    
+    ValueDecl *VD = DRE->getDecl();
+    if (!VD->isCXXClassMember())
+      return false;
+    
+    if (isa<FieldDecl>(VD) || isa<IndirectFieldDecl>(VD))
+      return true;
+    if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(VD))
+      return Method->isInstance();
+      
+    return false;
+  }
+  
+  if (UnresolvedLookupExpr *ULE = dyn_cast<UnresolvedLookupExpr>(E)) {
+    if (!ULE->getQualifier())
+      return false;
+    
+    for (UnresolvedLookupExpr::decls_iterator D = ULE->decls_begin(),
+                                           DEnd = ULE->decls_end();
+         D != DEnd; ++D) {
+      if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(*D)) {
+        if (Method->isInstance())
+          return true;
+      } else {
+        // Overload set does not contain methods.
+        break;
+      }
+    }
+    
+    return false;
+  }
+  
+  return false;
+}
+
+ExprResult Sema::BuildUnaryOp(Scope *S, SourceLocation OpLoc,
+                              UnaryOperatorKind Opc, Expr *Input) {
+  // First things first: handle placeholders so that the
+  // overloaded-operator check considers the right type.
+  if (const BuiltinType *pty = Input->getType()->getAsPlaceholderType()) {
+    // Increment and decrement of pseudo-object references.
+    if (pty->getKind() == BuiltinType::PseudoObject &&
+        UnaryOperator::isIncrementDecrementOp(Opc))
+      return checkPseudoObjectIncDec(S, OpLoc, Opc, Input);
+
+    // extension is always a builtin operator.
+    if (Opc == UO_Extension)
+      return CreateBuiltinUnaryOp(OpLoc, Opc, Input);
+
+    // & gets special logic for several kinds of placeholder.
+    // The builtin code knows what to do.
+    if (Opc == UO_AddrOf &&
+        (pty->getKind() == BuiltinType::Overload ||
+         pty->getKind() == BuiltinType::UnknownAny ||
+         pty->getKind() == BuiltinType::BoundMember))
+      return CreateBuiltinUnaryOp(OpLoc, Opc, Input);
+
+    // Anything else needs to be handled now.
+    ExprResult Result = CheckPlaceholderExpr(Input);
+    if (Result.isInvalid()) return ExprError();
+    Input = Result.take();
+  }
+
+  if (getLangOpts().CPlusPlus && Input->getType()->isOverloadableType() &&
+      UnaryOperator::getOverloadedOperator(Opc) != OO_None &&
+      !(Opc == UO_AddrOf && isQualifiedMemberAccess(Input))) {
+    // Find all of the overloaded operators visible from this
+    // point. We perform both an operator-name lookup from the local
+    // scope and an argument-dependent lookup based on the types of
+    // the arguments.
+    UnresolvedSet<16> Functions;
+    OverloadedOperatorKind OverOp = UnaryOperator::getOverloadedOperator(Opc);
+    if (S && OverOp != OO_None)
+      LookupOverloadedOperatorName(OverOp, S, Input->getType(), QualType(),
+                                   Functions);
+
+    return CreateOverloadedUnaryOp(OpLoc, Opc, Functions, Input);
+  }
+
+  return CreateBuiltinUnaryOp(OpLoc, Opc, Input);
+}
+
+// Unary Operators.  'Tok' is the token for the operator.
+ExprResult Sema::ActOnUnaryOp(Scope *S, SourceLocation OpLoc,
+                              tok::TokenKind Op, Expr *Input) {
+  return BuildUnaryOp(S, OpLoc, ConvertTokenKindToUnaryOpcode(Op), Input);
+}
+
+/// ActOnAddrLabel - Parse the GNU address of label extension: "&&foo".
+ExprResult Sema::ActOnAddrLabel(SourceLocation OpLoc, SourceLocation LabLoc,
+                                LabelDecl *TheDecl) {
+  TheDecl->setUsed();
+  // Create the AST node.  The address of a label always has type 'void*'.
+  return Owned(new (Context) AddrLabelExpr(OpLoc, LabLoc, TheDecl,
+                                       Context.getPointerType(Context.VoidTy)));
+}
+
+/// Given the last statement in a statement-expression, check whether
+/// the result is a producing expression (like a call to an
+/// ns_returns_retained function) and, if so, rebuild it to hoist the
+/// release out of the full-expression.  Otherwise, return null.
+/// Cannot fail.
+static Expr *maybeRebuildARCConsumingStmt(Stmt *Statement) {
+  // Should always be wrapped with one of these.
+  ExprWithCleanups *cleanups = dyn_cast<ExprWithCleanups>(Statement);
+  if (!cleanups) return 0;
+
+  ImplicitCastExpr *cast = dyn_cast<ImplicitCastExpr>(cleanups->getSubExpr());
+  if (!cast || cast->getCastKind() != CK_ARCConsumeObject)
+    return 0;
+
+  // Splice out the cast.  This shouldn't modify any interesting
+  // features of the statement.
+  Expr *producer = cast->getSubExpr();
+  assert(producer->getType() == cast->getType());
+  assert(producer->getValueKind() == cast->getValueKind());
+  cleanups->setSubExpr(producer);
+  return cleanups;
+}
+
+void Sema::ActOnStartStmtExpr() {
+  PushExpressionEvaluationContext(ExprEvalContexts.back().Context);
+}
+
+void Sema::ActOnStmtExprError() {
+  // Note that function is also called by TreeTransform when leaving a
+  // StmtExpr scope without rebuilding anything.
+
+  DiscardCleanupsInEvaluationContext();
+  PopExpressionEvaluationContext();
+}
+
+ExprResult
+Sema::ActOnStmtExpr(SourceLocation LPLoc, Stmt *SubStmt,
+                    SourceLocation RPLoc) { // "({..})"
+  assert(SubStmt && isa<CompoundStmt>(SubStmt) && "Invalid action invocation!");
+  CompoundStmt *Compound = cast<CompoundStmt>(SubStmt);
+
+  if (hasAnyUnrecoverableErrorsInThisFunction())
+    DiscardCleanupsInEvaluationContext();
+  assert(!ExprNeedsCleanups && "cleanups within StmtExpr not correctly bound!");
+  PopExpressionEvaluationContext();
+
+  bool isFileScope
+    = (getCurFunctionOrMethodDecl() == 0) && (getCurBlock() == 0);
+  if (isFileScope)
+    return ExprError(Diag(LPLoc, diag::err_stmtexpr_file_scope));
+
+  // FIXME: there are a variety of strange constraints to enforce here, for
+  // example, it is not possible to goto into a stmt expression apparently.
+  // More semantic analysis is needed.
+
+  // If there are sub stmts in the compound stmt, take the type of the last one
+  // as the type of the stmtexpr.
+  QualType Ty = Context.VoidTy;
+  bool StmtExprMayBindToTemp = false;
+  if (!Compound->body_empty()) {
+    Stmt *LastStmt = Compound->body_back();
+    LabelStmt *LastLabelStmt = 0;
+    // If LastStmt is a label, skip down through into the body.
+    while (LabelStmt *Label = dyn_cast<LabelStmt>(LastStmt)) {
+      LastLabelStmt = Label;
+      LastStmt = Label->getSubStmt();
+    }
+
+    if (Expr *LastE = dyn_cast<Expr>(LastStmt)) {
+      // Do function/array conversion on the last expression, but not
+      // lvalue-to-rvalue.  However, initialize an unqualified type.
+      ExprResult LastExpr = DefaultFunctionArrayConversion(LastE);
+      if (LastExpr.isInvalid())
+        return ExprError();
+      Ty = LastExpr.get()->getType().getUnqualifiedType();
+
+      if (!Ty->isDependentType() && !LastExpr.get()->isTypeDependent()) {
+        // In ARC, if the final expression ends in a consume, splice
+        // the consume out and bind it later.  In the alternate case
+        // (when dealing with a retainable type), the result
+        // initialization will create a produce.  In both cases the
+        // result will be +1, and we'll need to balance that out with
+        // a bind.
+        if (Expr *rebuiltLastStmt
+              = maybeRebuildARCConsumingStmt(LastExpr.get())) {
+          LastExpr = rebuiltLastStmt;
+        } else {
+          LastExpr = PerformCopyInitialization(
+                            InitializedEntity::InitializeResult(LPLoc, 
+                                                                Ty,
+                                                                false),
+                                                   SourceLocation(),
+                                               LastExpr);
+        }
+
+        if (LastExpr.isInvalid())
+          return ExprError();
+        if (LastExpr.get() != 0) {
+          if (!LastLabelStmt)
+            Compound->setLastStmt(LastExpr.take());
+          else
+            LastLabelStmt->setSubStmt(LastExpr.take());
+          StmtExprMayBindToTemp = true;
+        }
+      }
+    }
+  }
+
+  // FIXME: Check that expression type is complete/non-abstract; statement
+  // expressions are not lvalues.
+  Expr *ResStmtExpr = new (Context) StmtExpr(Compound, Ty, LPLoc, RPLoc);
+  if (StmtExprMayBindToTemp)
+    return MaybeBindToTemporary(ResStmtExpr);
+  return Owned(ResStmtExpr);
+}
+
+ExprResult Sema::BuildBuiltinOffsetOf(SourceLocation BuiltinLoc,
+                                      TypeSourceInfo *TInfo,
+                                      OffsetOfComponent *CompPtr,
+                                      unsigned NumComponents,
+                                      SourceLocation RParenLoc) {
+  QualType ArgTy = TInfo->getType();
+  bool Dependent = ArgTy->isDependentType();
+  SourceRange TypeRange = TInfo->getTypeLoc().getLocalSourceRange();
+  
+  // We must have at least one component that refers to the type, and the first
+  // one is known to be a field designator.  Verify that the ArgTy represents
+  // a struct/union/class.
+  if (!Dependent && !ArgTy->isRecordType())
+    return ExprError(Diag(BuiltinLoc, diag::err_offsetof_record_type) 
+                       << ArgTy << TypeRange);
+  
+  // Type must be complete per C99 7.17p3 because a declaring a variable
+  // with an incomplete type would be ill-formed.
+  if (!Dependent 
+      && RequireCompleteType(BuiltinLoc, ArgTy,
+                             PDiag(diag::err_offsetof_incomplete_type)
+                               << TypeRange))
+    return ExprError();
+  
+  // offsetof with non-identifier designators (e.g. "offsetof(x, a.b[c])") are a
+  // GCC extension, diagnose them.
+  // FIXME: This diagnostic isn't actually visible because the location is in
+  // a system header!
+  if (NumComponents != 1)
+    Diag(BuiltinLoc, diag::ext_offsetof_extended_field_designator)
+      << SourceRange(CompPtr[1].LocStart, CompPtr[NumComponents-1].LocEnd);
+  
+  bool DidWarnAboutNonPOD = false;
+  QualType CurrentType = ArgTy;
+  typedef OffsetOfExpr::OffsetOfNode OffsetOfNode;
+  SmallVector<OffsetOfNode, 4> Comps;
+  SmallVector<Expr*, 4> Exprs;
+  for (unsigned i = 0; i != NumComponents; ++i) {
+    const OffsetOfComponent &OC = CompPtr[i];
+    if (OC.isBrackets) {
+      // Offset of an array sub-field.  TODO: Should we allow vector elements?
+      if (!CurrentType->isDependentType()) {
+        const ArrayType *AT = Context.getAsArrayType(CurrentType);
+        if(!AT)
+          return ExprError(Diag(OC.LocEnd, diag::err_offsetof_array_type)
+                           << CurrentType);
+        CurrentType = AT->getElementType();
+      } else
+        CurrentType = Context.DependentTy;
+      
+      ExprResult IdxRval = DefaultLvalueConversion(static_cast<Expr*>(OC.U.E));
+      if (IdxRval.isInvalid())
+        return ExprError();
+      Expr *Idx = IdxRval.take();
+
+      // The expression must be an integral expression.
+      // FIXME: An integral constant expression?
+      if (!Idx->isTypeDependent() && !Idx->isValueDependent() &&
+          !Idx->getType()->isIntegerType())
+        return ExprError(Diag(Idx->getLocStart(),
+                              diag::err_typecheck_subscript_not_integer)
+                         << Idx->getSourceRange());
+
+      // Record this array index.
+      Comps.push_back(OffsetOfNode(OC.LocStart, Exprs.size(), OC.LocEnd));
+      Exprs.push_back(Idx);
+      continue;
+    }
+    
+    // Offset of a field.
+    if (CurrentType->isDependentType()) {
+      // We have the offset of a field, but we can't look into the dependent
+      // type. Just record the identifier of the field.
+      Comps.push_back(OffsetOfNode(OC.LocStart, OC.U.IdentInfo, OC.LocEnd));
+      CurrentType = Context.DependentTy;
+      continue;
+    }
+    
+    // We need to have a complete type to look into.
+    if (RequireCompleteType(OC.LocStart, CurrentType,
+                            diag::err_offsetof_incomplete_type))
+      return ExprError();
+    
+    // Look for the designated field.
+    const RecordType *RC = CurrentType->getAs<RecordType>();
+    if (!RC) 
+      return ExprError(Diag(OC.LocEnd, diag::err_offsetof_record_type)
+                       << CurrentType);
+    RecordDecl *RD = RC->getDecl();
+    
+    // C++ [lib.support.types]p5:
+    //   The macro offsetof accepts a restricted set of type arguments in this
+    //   International Standard. type shall be a POD structure or a POD union
+    //   (clause 9).
+    if (CXXRecordDecl *CRD = dyn_cast<CXXRecordDecl>(RD)) {
+      if (!CRD->isPOD() && !DidWarnAboutNonPOD &&
+          DiagRuntimeBehavior(BuiltinLoc, 0,
+                              PDiag(diag::warn_offsetof_non_pod_type)
+                              << SourceRange(CompPtr[0].LocStart, OC.LocEnd)
+                              << CurrentType))
+        DidWarnAboutNonPOD = true;
+    }
+    
+    // Look for the field.
+    LookupResult R(*this, OC.U.IdentInfo, OC.LocStart, LookupMemberName);
+    LookupQualifiedName(R, RD);
+    FieldDecl *MemberDecl = R.getAsSingle<FieldDecl>();
+    IndirectFieldDecl *IndirectMemberDecl = 0;
+    if (!MemberDecl) {
+      if ((IndirectMemberDecl = R.getAsSingle<IndirectFieldDecl>()))
+        MemberDecl = IndirectMemberDecl->getAnonField();
+    }
+
+    if (!MemberDecl)
+      return ExprError(Diag(BuiltinLoc, diag::err_no_member)
+                       << OC.U.IdentInfo << RD << SourceRange(OC.LocStart, 
+                                                              OC.LocEnd));
+    
+    // C99 7.17p3:
+    //   (If the specified member is a bit-field, the behavior is undefined.)
+    //
+    // We diagnose this as an error.
+    if (MemberDecl->isBitField()) {
+      Diag(OC.LocEnd, diag::err_offsetof_bitfield)
+        << MemberDecl->getDeclName()
+        << SourceRange(BuiltinLoc, RParenLoc);
+      Diag(MemberDecl->getLocation(), diag::note_bitfield_decl);
+      return ExprError();
+    }
+
+    RecordDecl *Parent = MemberDecl->getParent();
+    if (IndirectMemberDecl)
+      Parent = cast<RecordDecl>(IndirectMemberDecl->getDeclContext());
+
+    // If the member was found in a base class, introduce OffsetOfNodes for
+    // the base class indirections.
+    CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
+                       /*DetectVirtual=*/false);
+    if (IsDerivedFrom(CurrentType, Context.getTypeDeclType(Parent), Paths)) {
+      CXXBasePath &Path = Paths.front();
+      for (CXXBasePath::iterator B = Path.begin(), BEnd = Path.end();
+           B != BEnd; ++B)
+        Comps.push_back(OffsetOfNode(B->Base));
+    }
+
+    if (IndirectMemberDecl) {
+      for (IndirectFieldDecl::chain_iterator FI =
+           IndirectMemberDecl->chain_begin(),
+           FEnd = IndirectMemberDecl->chain_end(); FI != FEnd; FI++) {
+        assert(isa<FieldDecl>(*FI));
+        Comps.push_back(OffsetOfNode(OC.LocStart,
+                                     cast<FieldDecl>(*FI), OC.LocEnd));
+      }
+    } else
+      Comps.push_back(OffsetOfNode(OC.LocStart, MemberDecl, OC.LocEnd));
+
+    CurrentType = MemberDecl->getType().getNonReferenceType(); 
+  }
+  
+  return Owned(OffsetOfExpr::Create(Context, Context.getSizeType(), BuiltinLoc, 
+                                    TInfo, Comps.data(), Comps.size(),
+                                    Exprs.data(), Exprs.size(), RParenLoc));  
+}
+
+ExprResult Sema::ActOnBuiltinOffsetOf(Scope *S,
+                                      SourceLocation BuiltinLoc,
+                                      SourceLocation TypeLoc,
+                                      ParsedType ParsedArgTy,
+                                      OffsetOfComponent *CompPtr,
+                                      unsigned NumComponents,
+                                      SourceLocation RParenLoc) {
+  
+  TypeSourceInfo *ArgTInfo;
+  QualType ArgTy = GetTypeFromParser(ParsedArgTy, &ArgTInfo);
+  if (ArgTy.isNull())
+    return ExprError();
+
+  if (!ArgTInfo)
+    ArgTInfo = Context.getTrivialTypeSourceInfo(ArgTy, TypeLoc);
+
+  return BuildBuiltinOffsetOf(BuiltinLoc, ArgTInfo, CompPtr, NumComponents, 
+                              RParenLoc);
+}
+
+
+ExprResult Sema::ActOnChooseExpr(SourceLocation BuiltinLoc,
+                                 Expr *CondExpr,
+                                 Expr *LHSExpr, Expr *RHSExpr,
+                                 SourceLocation RPLoc) {
+  assert((CondExpr && LHSExpr && RHSExpr) && "Missing type argument(s)");
+
+  ExprValueKind VK = VK_RValue;
+  ExprObjectKind OK = OK_Ordinary;
+  QualType resType;
+  bool ValueDependent = false;
+  if (CondExpr->isTypeDependent() || CondExpr->isValueDependent()) {
+    resType = Context.DependentTy;
+    ValueDependent = true;
+  } else {
+    // The conditional expression is required to be a constant expression.
+    llvm::APSInt condEval(32);
+    ExprResult CondICE = VerifyIntegerConstantExpression(CondExpr, &condEval,
+      PDiag(diag::err_typecheck_choose_expr_requires_constant), false);
+    if (CondICE.isInvalid())
+      return ExprError();
+    CondExpr = CondICE.take();
+
+    // If the condition is > zero, then the AST type is the same as the LSHExpr.
+    Expr *ActiveExpr = condEval.getZExtValue() ? LHSExpr : RHSExpr;
+
+    resType = ActiveExpr->getType();
+    ValueDependent = ActiveExpr->isValueDependent();
+    VK = ActiveExpr->getValueKind();
+    OK = ActiveExpr->getObjectKind();
+  }
+
+  return Owned(new (Context) ChooseExpr(BuiltinLoc, CondExpr, LHSExpr, RHSExpr,
+                                        resType, VK, OK, RPLoc,
+                                        resType->isDependentType(),
+                                        ValueDependent));
+}
+
+//===----------------------------------------------------------------------===//
+// Clang Extensions.
+//===----------------------------------------------------------------------===//
+
+/// ActOnBlockStart - This callback is invoked when a block literal is started.
+void Sema::ActOnBlockStart(SourceLocation CaretLoc, Scope *CurScope) {
+  BlockDecl *Block = BlockDecl::Create(Context, CurContext, CaretLoc);
+  PushBlockScope(CurScope, Block);
+  CurContext->addDecl(Block);
+  if (CurScope)
+    PushDeclContext(CurScope, Block);
+  else
+    CurContext = Block;
+
+  getCurBlock()->HasImplicitReturnType = true;
+
+  // Enter a new evaluation context to insulate the block from any
+  // cleanups from the enclosing full-expression.
+  PushExpressionEvaluationContext(PotentiallyEvaluated);  
+}
+
+void Sema::ActOnBlockArguments(Declarator &ParamInfo, Scope *CurScope) {
+  assert(ParamInfo.getIdentifier()==0 && "block-id should have no identifier!");
+  assert(ParamInfo.getContext() == Declarator::BlockLiteralContext);
+  BlockScopeInfo *CurBlock = getCurBlock();
+
+  TypeSourceInfo *Sig = GetTypeForDeclarator(ParamInfo, CurScope);
+  QualType T = Sig->getType();
+
+  // GetTypeForDeclarator always produces a function type for a block
+  // literal signature.  Furthermore, it is always a FunctionProtoType
+  // unless the function was written with a typedef.
+  assert(T->isFunctionType() &&
+         "GetTypeForDeclarator made a non-function block signature");
+
+  // Look for an explicit signature in that function type.
+  FunctionProtoTypeLoc ExplicitSignature;
+
+  TypeLoc tmp = Sig->getTypeLoc().IgnoreParens();
+  if (isa<FunctionProtoTypeLoc>(tmp)) {
+    ExplicitSignature = cast<FunctionProtoTypeLoc>(tmp);
+
+    // Check whether that explicit signature was synthesized by
+    // GetTypeForDeclarator.  If so, don't save that as part of the
+    // written signature.
+    if (ExplicitSignature.getLocalRangeBegin() ==
+        ExplicitSignature.getLocalRangeEnd()) {
+      // This would be much cheaper if we stored TypeLocs instead of
+      // TypeSourceInfos.
+      TypeLoc Result = ExplicitSignature.getResultLoc();
+      unsigned Size = Result.getFullDataSize();
+      Sig = Context.CreateTypeSourceInfo(Result.getType(), Size);
+      Sig->getTypeLoc().initializeFullCopy(Result, Size);
+
+      ExplicitSignature = FunctionProtoTypeLoc();
+    }
+  }
+
+  CurBlock->TheDecl->setSignatureAsWritten(Sig);
+  CurBlock->FunctionType = T;
+
+  const FunctionType *Fn = T->getAs<FunctionType>();
+  QualType RetTy = Fn->getResultType();
+  bool isVariadic =
+    (isa<FunctionProtoType>(Fn) && cast<FunctionProtoType>(Fn)->isVariadic());
+
+  CurBlock->TheDecl->setIsVariadic(isVariadic);
+
+  // Don't allow returning a objc interface by value.
+  if (RetTy->isObjCObjectType()) {
+    Diag(ParamInfo.getLocStart(),
+         diag::err_object_cannot_be_passed_returned_by_value) << 0 << RetTy;
+    return;
+  }
+
+  // Context.DependentTy is used as a placeholder for a missing block
+  // return type.  TODO:  what should we do with declarators like:
+  //   ^ * { ... }
+  // If the answer is "apply template argument deduction"....
+  if (RetTy != Context.DependentTy) {
+    CurBlock->ReturnType = RetTy;
+    CurBlock->TheDecl->setBlockMissingReturnType(false);
+    CurBlock->HasImplicitReturnType = false;
+  }
+
+  // Push block parameters from the declarator if we had them.
+  SmallVector<ParmVarDecl*, 8> Params;
+  if (ExplicitSignature) {
+    for (unsigned I = 0, E = ExplicitSignature.getNumArgs(); I != E; ++I) {
+      ParmVarDecl *Param = ExplicitSignature.getArg(I);
+      if (Param->getIdentifier() == 0 &&
+          !Param->isImplicit() &&
+          !Param->isInvalidDecl() &&
+          !getLangOpts().CPlusPlus)
+        Diag(Param->getLocation(), diag::err_parameter_name_omitted);
+      Params.push_back(Param);
+    }
+
+  // Fake up parameter variables if we have a typedef, like
+  //   ^ fntype { ... }
+  } else if (const FunctionProtoType *Fn = T->getAs<FunctionProtoType>()) {
+    for (FunctionProtoType::arg_type_iterator
+           I = Fn->arg_type_begin(), E = Fn->arg_type_end(); I != E; ++I) {
+      ParmVarDecl *Param =
+        BuildParmVarDeclForTypedef(CurBlock->TheDecl,
+                                   ParamInfo.getLocStart(),
+                                   *I);
+      Params.push_back(Param);
+    }
+  }
+
+  // Set the parameters on the block decl.
+  if (!Params.empty()) {
+    CurBlock->TheDecl->setParams(Params);
+    CheckParmsForFunctionDef(CurBlock->TheDecl->param_begin(),
+                             CurBlock->TheDecl->param_end(),
+                             /*CheckParameterNames=*/false);
+  }
+  
+  // Finally we can process decl attributes.
+  ProcessDeclAttributes(CurScope, CurBlock->TheDecl, ParamInfo);
+
+  // Put the parameter variables in scope.  We can bail out immediately
+  // if we don't have any.
+  if (Params.empty())
+    return;
+
+  for (BlockDecl::param_iterator AI = CurBlock->TheDecl->param_begin(),
+         E = CurBlock->TheDecl->param_end(); AI != E; ++AI) {
+    (*AI)->setOwningFunction(CurBlock->TheDecl);
+
+    // If this has an identifier, add it to the scope stack.
+    if ((*AI)->getIdentifier()) {
+      CheckShadow(CurBlock->TheScope, *AI);
+
+      PushOnScopeChains(*AI, CurBlock->TheScope);
+    }
+  }
+}
+
+/// ActOnBlockError - If there is an error parsing a block, this callback
+/// is invoked to pop the information about the block from the action impl.
+void Sema::ActOnBlockError(SourceLocation CaretLoc, Scope *CurScope) {
+  // Leave the expression-evaluation context.
+  DiscardCleanupsInEvaluationContext();
+  PopExpressionEvaluationContext();
+
+  // Pop off CurBlock, handle nested blocks.
+  PopDeclContext();
+  PopFunctionScopeInfo();
+}
+
+/// ActOnBlockStmtExpr - This is called when the body of a block statement
+/// literal was successfully completed.  ^(int x){...}
+ExprResult Sema::ActOnBlockStmtExpr(SourceLocation CaretLoc,
+                                    Stmt *Body, Scope *CurScope) {
+  // If blocks are disabled, emit an error.
+  if (!LangOpts.Blocks)
+    Diag(CaretLoc, diag::err_blocks_disable);
+
+  // Leave the expression-evaluation context.
+  if (hasAnyUnrecoverableErrorsInThisFunction())
+    DiscardCleanupsInEvaluationContext();
+  assert(!ExprNeedsCleanups && "cleanups within block not correctly bound!");
+  PopExpressionEvaluationContext();
+
+  BlockScopeInfo *BSI = cast<BlockScopeInfo>(FunctionScopes.back());
+  
+  PopDeclContext();
+
+  QualType RetTy = Context.VoidTy;
+  if (!BSI->ReturnType.isNull())
+    RetTy = BSI->ReturnType;
+
+  bool NoReturn = BSI->TheDecl->getAttr<NoReturnAttr>();
+  QualType BlockTy;
+
+  // Set the captured variables on the block.
+  // FIXME: Share capture structure between BlockDecl and CapturingScopeInfo!
+  SmallVector<BlockDecl::Capture, 4> Captures;
+  for (unsigned i = 0, e = BSI->Captures.size(); i != e; i++) {
+    CapturingScopeInfo::Capture &Cap = BSI->Captures[i];
+    if (Cap.isThisCapture())
+      continue;
+    BlockDecl::Capture NewCap(Cap.getVariable(), Cap.isBlockCapture(),
+                              Cap.isNested(), Cap.getCopyExpr());
+    Captures.push_back(NewCap);
+  }
+  BSI->TheDecl->setCaptures(Context, Captures.begin(), Captures.end(),
+                            BSI->CXXThisCaptureIndex != 0);
+
+  // If the user wrote a function type in some form, try to use that.
+  if (!BSI->FunctionType.isNull()) {
+    const FunctionType *FTy = BSI->FunctionType->getAs<FunctionType>();
+
+    FunctionType::ExtInfo Ext = FTy->getExtInfo();
+    if (NoReturn && !Ext.getNoReturn()) Ext = Ext.withNoReturn(true);
+    
+    // Turn protoless block types into nullary block types.
+    if (isa<FunctionNoProtoType>(FTy)) {
+      FunctionProtoType::ExtProtoInfo EPI;
+      EPI.ExtInfo = Ext;
+      BlockTy = Context.getFunctionType(RetTy, 0, 0, EPI);
+
+    // Otherwise, if we don't need to change anything about the function type,
+    // preserve its sugar structure.
+    } else if (FTy->getResultType() == RetTy &&
+               (!NoReturn || FTy->getNoReturnAttr())) {
+      BlockTy = BSI->FunctionType;
+
+    // Otherwise, make the minimal modifications to the function type.
+    } else {
+      const FunctionProtoType *FPT = cast<FunctionProtoType>(FTy);
+      FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo();
+      EPI.TypeQuals = 0; // FIXME: silently?
+      EPI.ExtInfo = Ext;
+      BlockTy = Context.getFunctionType(RetTy,
+                                        FPT->arg_type_begin(),
+                                        FPT->getNumArgs(),
+                                        EPI);
+    }
+
+  // If we don't have a function type, just build one from nothing.
+  } else {
+    FunctionProtoType::ExtProtoInfo EPI;
+    EPI.ExtInfo = FunctionType::ExtInfo().withNoReturn(NoReturn);
+    BlockTy = Context.getFunctionType(RetTy, 0, 0, EPI);
+  }
+
+  DiagnoseUnusedParameters(BSI->TheDecl->param_begin(),
+                           BSI->TheDecl->param_end());
+  BlockTy = Context.getBlockPointerType(BlockTy);
+
+  // If needed, diagnose invalid gotos and switches in the block.
+  if (getCurFunction()->NeedsScopeChecking() &&
+      !hasAnyUnrecoverableErrorsInThisFunction())
+    DiagnoseInvalidJumps(cast<CompoundStmt>(Body));
+
+  BSI->TheDecl->setBody(cast<CompoundStmt>(Body));
+
+  computeNRVO(Body, getCurBlock());
+  
+  BlockExpr *Result = new (Context) BlockExpr(BSI->TheDecl, BlockTy);
+  const AnalysisBasedWarnings::Policy &WP = AnalysisWarnings.getDefaultPolicy();
+  PopFunctionScopeInfo(&WP, Result->getBlockDecl(), Result);
+
+  // If the block isn't obviously global, i.e. it captures anything at
+  // all, then we need to do a few things in the surrounding context:
+  if (Result->getBlockDecl()->hasCaptures()) {
+    // First, this expression has a new cleanup object.
+    ExprCleanupObjects.push_back(Result->getBlockDecl());
+    ExprNeedsCleanups = true;
+
+    // It also gets a branch-protected scope if any of the captured
+    // variables needs destruction.
+    for (BlockDecl::capture_const_iterator
+           ci = Result->getBlockDecl()->capture_begin(),
+           ce = Result->getBlockDecl()->capture_end(); ci != ce; ++ci) {
+      const VarDecl *var = ci->getVariable();
+      if (var->getType().isDestructedType() != QualType::DK_none) {
+        getCurFunction()->setHasBranchProtectedScope();
+        break;
+      }
+    }
+  }
+
+  return Owned(Result);
+}
+
+ExprResult Sema::ActOnVAArg(SourceLocation BuiltinLoc,
+                                        Expr *E, ParsedType Ty,
+                                        SourceLocation RPLoc) {
+  TypeSourceInfo *TInfo;
+  GetTypeFromParser(Ty, &TInfo);
+  return BuildVAArgExpr(BuiltinLoc, E, TInfo, RPLoc);
+}
+
+ExprResult Sema::BuildVAArgExpr(SourceLocation BuiltinLoc,
+                                Expr *E, TypeSourceInfo *TInfo,
+                                SourceLocation RPLoc) {
+  Expr *OrigExpr = E;
+
+  // Get the va_list type
+  QualType VaListType = Context.getBuiltinVaListType();
+  if (VaListType->isArrayType()) {
+    // Deal with implicit array decay; for example, on x86-64,
+    // va_list is an array, but it's supposed to decay to
+    // a pointer for va_arg.
+    VaListType = Context.getArrayDecayedType(VaListType);
+    // Make sure the input expression also decays appropriately.
+    ExprResult Result = UsualUnaryConversions(E);
+    if (Result.isInvalid())
+      return ExprError();
+    E = Result.take();
+  } else {
+    // Otherwise, the va_list argument must be an l-value because
+    // it is modified by va_arg.
+    if (!E->isTypeDependent() &&
+        CheckForModifiableLvalue(E, BuiltinLoc, *this))
+      return ExprError();
+  }
+
+  if (!E->isTypeDependent() &&
+      !Context.hasSameType(VaListType, E->getType())) {
+    return ExprError(Diag(E->getLocStart(),
+                         diag::err_first_argument_to_va_arg_not_of_type_va_list)
+      << OrigExpr->getType() << E->getSourceRange());
+  }
+
+  if (!TInfo->getType()->isDependentType()) {
+    if (RequireCompleteType(TInfo->getTypeLoc().getBeginLoc(), TInfo->getType(),
+          PDiag(diag::err_second_parameter_to_va_arg_incomplete)
+          << TInfo->getTypeLoc().getSourceRange()))
+      return ExprError();
+
+    if (RequireNonAbstractType(TInfo->getTypeLoc().getBeginLoc(),
+          TInfo->getType(),
+          PDiag(diag::err_second_parameter_to_va_arg_abstract)
+          << TInfo->getTypeLoc().getSourceRange()))
+      return ExprError();
+
+    if (!TInfo->getType().isPODType(Context)) {
+      Diag(TInfo->getTypeLoc().getBeginLoc(),
+           TInfo->getType()->isObjCLifetimeType()
+             ? diag::warn_second_parameter_to_va_arg_ownership_qualified
+             : diag::warn_second_parameter_to_va_arg_not_pod)
+        << TInfo->getType()
+        << TInfo->getTypeLoc().getSourceRange();
+    }
+
+    // Check for va_arg where arguments of the given type will be promoted
+    // (i.e. this va_arg is guaranteed to have undefined behavior).
+    QualType PromoteType;
+    if (TInfo->getType()->isPromotableIntegerType()) {
+      PromoteType = Context.getPromotedIntegerType(TInfo->getType());
+      if (Context.typesAreCompatible(PromoteType, TInfo->getType()))
+        PromoteType = QualType();
+    }
+    if (TInfo->getType()->isSpecificBuiltinType(BuiltinType::Float))
+      PromoteType = Context.DoubleTy;
+    if (!PromoteType.isNull())
+      Diag(TInfo->getTypeLoc().getBeginLoc(),
+          diag::warn_second_parameter_to_va_arg_never_compatible)
+        << TInfo->getType()
+        << PromoteType
+        << TInfo->getTypeLoc().getSourceRange();
+  }
+
+  QualType T = TInfo->getType().getNonLValueExprType(Context);
+  return Owned(new (Context) VAArgExpr(BuiltinLoc, E, TInfo, RPLoc, T));
+}
+
+ExprResult Sema::ActOnGNUNullExpr(SourceLocation TokenLoc) {
+  // The type of __null will be int or long, depending on the size of
+  // pointers on the target.
+  QualType Ty;
+  unsigned pw = Context.getTargetInfo().getPointerWidth(0);
+  if (pw == Context.getTargetInfo().getIntWidth())
+    Ty = Context.IntTy;
+  else if (pw == Context.getTargetInfo().getLongWidth())
+    Ty = Context.LongTy;
+  else if (pw == Context.getTargetInfo().getLongLongWidth())
+    Ty = Context.LongLongTy;
+  else {
+    llvm_unreachable("I don't know size of pointer!");
+  }
+
+  return Owned(new (Context) GNUNullExpr(Ty, TokenLoc));
+}
+
+static void MakeObjCStringLiteralFixItHint(Sema& SemaRef, QualType DstType,
+                                           Expr *SrcExpr, FixItHint &Hint) {
+  if (!SemaRef.getLangOpts().ObjC1)
+    return;
+
+  const ObjCObjectPointerType *PT = DstType->getAs<ObjCObjectPointerType>();
+  if (!PT)
+    return;
+
+  // Check if the destination is of type 'id'.
+  if (!PT->isObjCIdType()) {
+    // Check if the destination is the 'NSString' interface.
+    const ObjCInterfaceDecl *ID = PT->getInterfaceDecl();
+    if (!ID || !ID->getIdentifier()->isStr("NSString"))
+      return;
+  }
+
+  // Ignore any parens, implicit casts (should only be
+  // array-to-pointer decays), and not-so-opaque values.  The last is
+  // important for making this trigger for property assignments.
+  SrcExpr = SrcExpr->IgnoreParenImpCasts();
+  if (OpaqueValueExpr *OV = dyn_cast<OpaqueValueExpr>(SrcExpr))
+    if (OV->getSourceExpr())
+      SrcExpr = OV->getSourceExpr()->IgnoreParenImpCasts();
+
+  StringLiteral *SL = dyn_cast<StringLiteral>(SrcExpr);
+  if (!SL || !SL->isAscii())
+    return;
+
+  Hint = FixItHint::CreateInsertion(SL->getLocStart(), "@");
+}
+
+bool Sema::DiagnoseAssignmentResult(AssignConvertType ConvTy,
+                                    SourceLocation Loc,
+                                    QualType DstType, QualType SrcType,
+                                    Expr *SrcExpr, AssignmentAction Action,
+                                    bool *Complained) {
+  if (Complained)
+    *Complained = false;
+
+  // Decode the result (notice that AST's are still created for extensions).
+  bool CheckInferredResultType = false;
+  bool isInvalid = false;
+  unsigned DiagKind = 0;
+  FixItHint Hint;
+  ConversionFixItGenerator ConvHints;
+  bool MayHaveConvFixit = false;
+  bool MayHaveFunctionDiff = false;
+
+  switch (ConvTy) {
+  case Compatible: return false;
+  case PointerToInt:
+    DiagKind = diag::ext_typecheck_convert_pointer_int;
+    ConvHints.tryToFixConversion(SrcExpr, SrcType, DstType, *this);
+    MayHaveConvFixit = true;
+    break;
+  case IntToPointer:
+    DiagKind = diag::ext_typecheck_convert_int_pointer;
+    ConvHints.tryToFixConversion(SrcExpr, SrcType, DstType, *this);
+    MayHaveConvFixit = true;
+    break;
+  case IncompatiblePointer:
+    MakeObjCStringLiteralFixItHint(*this, DstType, SrcExpr, Hint);
+    DiagKind = diag::ext_typecheck_convert_incompatible_pointer;
+    CheckInferredResultType = DstType->isObjCObjectPointerType() &&
+      SrcType->isObjCObjectPointerType();
+    if (Hint.isNull() && !CheckInferredResultType) {
+      ConvHints.tryToFixConversion(SrcExpr, SrcType, DstType, *this);
+    }
+    MayHaveConvFixit = true;
+    break;
+  case IncompatiblePointerSign:
+    DiagKind = diag::ext_typecheck_convert_incompatible_pointer_sign;
+    break;
+  case FunctionVoidPointer:
+    DiagKind = diag::ext_typecheck_convert_pointer_void_func;
+    break;
+  case IncompatiblePointerDiscardsQualifiers: {
+    // Perform array-to-pointer decay if necessary.
+    if (SrcType->isArrayType()) SrcType = Context.getArrayDecayedType(SrcType);
+
+    Qualifiers lhq = SrcType->getPointeeType().getQualifiers();
+    Qualifiers rhq = DstType->getPointeeType().getQualifiers();
+    if (lhq.getAddressSpace() != rhq.getAddressSpace()) {
+      DiagKind = diag::err_typecheck_incompatible_address_space;
+      break;
+
+
+    } else if (lhq.getObjCLifetime() != rhq.getObjCLifetime()) {
+      DiagKind = diag::err_typecheck_incompatible_ownership;
+      break;
+    }
+
+    llvm_unreachable("unknown error case for discarding qualifiers!");
+    // fallthrough
+  }
+  case CompatiblePointerDiscardsQualifiers:
+    // If the qualifiers lost were because we were applying the
+    // (deprecated) C++ conversion from a string literal to a char*
+    // (or wchar_t*), then there was no error (C++ 4.2p2).  FIXME:
+    // Ideally, this check would be performed in
+    // checkPointerTypesForAssignment. However, that would require a
+    // bit of refactoring (so that the second argument is an
+    // expression, rather than a type), which should be done as part
+    // of a larger effort to fix checkPointerTypesForAssignment for
+    // C++ semantics.
+    if (getLangOpts().CPlusPlus &&
+        IsStringLiteralToNonConstPointerConversion(SrcExpr, DstType))
+      return false;
+    DiagKind = diag::ext_typecheck_convert_discards_qualifiers;
+    break;
+  case IncompatibleNestedPointerQualifiers:
+    DiagKind = diag::ext_nested_pointer_qualifier_mismatch;
+    break;
+  case IntToBlockPointer:
+    DiagKind = diag::err_int_to_block_pointer;
+    break;
+  case IncompatibleBlockPointer:
+    DiagKind = diag::err_typecheck_convert_incompatible_block_pointer;
+    break;
+  case IncompatibleObjCQualifiedId:
+    // FIXME: Diagnose the problem in ObjCQualifiedIdTypesAreCompatible, since
+    // it can give a more specific diagnostic.
+    DiagKind = diag::warn_incompatible_qualified_id;
+    break;
+  case IncompatibleVectors:
+    DiagKind = diag::warn_incompatible_vectors;
+    break;
+  case IncompatibleObjCWeakRef:
+    DiagKind = diag::err_arc_weak_unavailable_assign;
+    break;
+  case Incompatible:
+    DiagKind = diag::err_typecheck_convert_incompatible;
+    ConvHints.tryToFixConversion(SrcExpr, SrcType, DstType, *this);
+    MayHaveConvFixit = true;
+    isInvalid = true;
+    MayHaveFunctionDiff = true;
+    break;
+  }
+
+  QualType FirstType, SecondType;
+  switch (Action) {
+  case AA_Assigning:
+  case AA_Initializing:
+    // The destination type comes first.
+    FirstType = DstType;
+    SecondType = SrcType;
+    break;
+
+  case AA_Returning:
+  case AA_Passing:
+  case AA_Converting:
+  case AA_Sending:
+  case AA_Casting:
+    // The source type comes first.
+    FirstType = SrcType;
+    SecondType = DstType;
+    break;
+  }
+
+  PartialDiagnostic FDiag = PDiag(DiagKind);
+  FDiag << FirstType << SecondType << Action << SrcExpr->getSourceRange();
+
+  // If we can fix the conversion, suggest the FixIts.
+  assert(ConvHints.isNull() || Hint.isNull());
+  if (!ConvHints.isNull()) {
+    for (std::vector<FixItHint>::iterator HI = ConvHints.Hints.begin(),
+         HE = ConvHints.Hints.end(); HI != HE; ++HI)
+      FDiag << *HI;
+  } else {
+    FDiag << Hint;
+  }
+  if (MayHaveConvFixit) { FDiag << (unsigned) (ConvHints.Kind); }
+
+  if (MayHaveFunctionDiff)
+    HandleFunctionTypeMismatch(FDiag, SecondType, FirstType);
+
+  Diag(Loc, FDiag);
+
+  if (SecondType == Context.OverloadTy)
+    NoteAllOverloadCandidates(OverloadExpr::find(SrcExpr).Expression,
+                              FirstType);
+
+  if (CheckInferredResultType)
+    EmitRelatedResultTypeNote(SrcExpr);
+  
+  if (Complained)
+    *Complained = true;
+  return isInvalid;
+}
+
+ExprResult Sema::VerifyIntegerConstantExpression(Expr *E,
+                                                 llvm::APSInt *Result) {
+  return VerifyIntegerConstantExpression(E, Result,
+      PDiag(diag::err_expr_not_ice) << LangOpts.CPlusPlus);
+}
+
+ExprResult
+Sema::VerifyIntegerConstantExpression(Expr *E, llvm::APSInt *Result,
+                                      const PartialDiagnostic &NotIceDiag,
+                                      bool AllowFold,
+                                      const PartialDiagnostic &FoldDiag) {
+  SourceLocation DiagLoc = E->getLocStart();
+
+  if (getLangOpts().CPlusPlus0x) {
+    // C++11 [expr.const]p5:
+    //   If an expression of literal class type is used in a context where an
+    //   integral constant expression is required, then that class type shall
+    //   have a single non-explicit conversion function to an integral or
+    //   unscoped enumeration type
+    ExprResult Converted;
+    if (NotIceDiag.getDiagID()) {
+      Converted = ConvertToIntegralOrEnumerationType(
+        DiagLoc, E,
+        PDiag(diag::err_ice_not_integral),
+        PDiag(diag::err_ice_incomplete_type),
+        PDiag(diag::err_ice_explicit_conversion),
+        PDiag(diag::note_ice_conversion_here),
+        PDiag(diag::err_ice_ambiguous_conversion),
+        PDiag(diag::note_ice_conversion_here),
+        PDiag(0),
+        /*AllowScopedEnumerations*/ false);
+    } else {
+      // The caller wants to silently enquire whether this is an ICE. Don't
+      // produce any diagnostics if it isn't.
+      Converted = ConvertToIntegralOrEnumerationType(
+        DiagLoc, E, PDiag(), PDiag(), PDiag(), PDiag(),
+        PDiag(), PDiag(), PDiag(), false);
+    }
+    if (Converted.isInvalid())
+      return Converted;
+    E = Converted.take();
+    if (!E->getType()->isIntegralOrUnscopedEnumerationType())
+      return ExprError();
+  } else if (!E->getType()->isIntegralOrUnscopedEnumerationType()) {
+    // An ICE must be of integral or unscoped enumeration type.
+    if (NotIceDiag.getDiagID())
+      Diag(DiagLoc, NotIceDiag) << E->getSourceRange();
+    return ExprError();
+  }
+
+  // Circumvent ICE checking in C++11 to avoid evaluating the expression twice
+  // in the non-ICE case.
+  if (!getLangOpts().CPlusPlus0x && E->isIntegerConstantExpr(Context)) {
+    if (Result)
+      *Result = E->EvaluateKnownConstInt(Context);
+    return Owned(E);
+  }
+
+  Expr::EvalResult EvalResult;
+  llvm::SmallVector<PartialDiagnosticAt, 8> Notes;
+  EvalResult.Diag = &Notes;
+
+  // Try to evaluate the expression, and produce diagnostics explaining why it's
+  // not a constant expression as a side-effect.
+  bool Folded = E->EvaluateAsRValue(EvalResult, Context) &&
+                EvalResult.Val.isInt() && !EvalResult.HasSideEffects;
+
+  // In C++11, we can rely on diagnostics being produced for any expression
+  // which is not a constant expression. If no diagnostics were produced, then
+  // this is a constant expression.
+  if (Folded && getLangOpts().CPlusPlus0x && Notes.empty()) {
+    if (Result)
+      *Result = EvalResult.Val.getInt();
+    return Owned(E);
+  }
+
+  // If our only note is the usual "invalid subexpression" note, just point
+  // the caret at its location rather than producing an essentially
+  // redundant note.
+  if (Notes.size() == 1 && Notes[0].second.getDiagID() ==
+        diag::note_invalid_subexpr_in_const_expr) {
+    DiagLoc = Notes[0].first;
+    Notes.clear();
+  }
+
+  if (!Folded || !AllowFold) {
+    if (NotIceDiag.getDiagID()) {
+      Diag(DiagLoc, NotIceDiag) << E->getSourceRange();
+      for (unsigned I = 0, N = Notes.size(); I != N; ++I)
+        Diag(Notes[I].first, Notes[I].second);
+    }
+
+    return ExprError();
+  }
+
+  if (FoldDiag.getDiagID())
+    Diag(DiagLoc, FoldDiag) << E->getSourceRange();
+  else
+    Diag(DiagLoc, diag::ext_expr_not_ice)
+      << E->getSourceRange() << LangOpts.CPlusPlus;
+  for (unsigned I = 0, N = Notes.size(); I != N; ++I)
+    Diag(Notes[I].first, Notes[I].second);
+
+  if (Result)
+    *Result = EvalResult.Val.getInt();
+  return Owned(E);
+}
+
+namespace {
+  // Handle the case where we conclude a expression which we speculatively
+  // considered to be unevaluated is actually evaluated.
+  class TransformToPE : public TreeTransform<TransformToPE> {
+    typedef TreeTransform<TransformToPE> BaseTransform;
+
+  public:
+    TransformToPE(Sema &SemaRef) : BaseTransform(SemaRef) { }
+
+    // Make sure we redo semantic analysis
+    bool AlwaysRebuild() { return true; }
+
+    // Make sure we handle LabelStmts correctly.
+    // FIXME: This does the right thing, but maybe we need a more general
+    // fix to TreeTransform?
+    StmtResult TransformLabelStmt(LabelStmt *S) {
+      S->getDecl()->setStmt(0);
+      return BaseTransform::TransformLabelStmt(S);
+    }
+
+    // We need to special-case DeclRefExprs referring to FieldDecls which
+    // are not part of a member pointer formation; normal TreeTransforming
+    // doesn't catch this case because of the way we represent them in the AST.
+    // FIXME: This is a bit ugly; is it really the best way to handle this
+    // case?
+    //
+    // Error on DeclRefExprs referring to FieldDecls.
+    ExprResult TransformDeclRefExpr(DeclRefExpr *E) {
+      if (isa<FieldDecl>(E->getDecl()) &&
+          SemaRef.ExprEvalContexts.back().Context != Sema::Unevaluated)
+        return SemaRef.Diag(E->getLocation(),
+                            diag::err_invalid_non_static_member_use)
+            << E->getDecl() << E->getSourceRange();
+
+      return BaseTransform::TransformDeclRefExpr(E);
+    }
+
+    // Exception: filter out member pointer formation
+    ExprResult TransformUnaryOperator(UnaryOperator *E) {
+      if (E->getOpcode() == UO_AddrOf && E->getType()->isMemberPointerType())
+        return E;
+
+      return BaseTransform::TransformUnaryOperator(E);
+    }
+
+    ExprResult TransformLambdaExpr(LambdaExpr *E) {
+      // Lambdas never need to be transformed.
+      return E;
+    }
+  };
+}
+
+ExprResult Sema::TranformToPotentiallyEvaluated(Expr *E) {
+  assert(ExprEvalContexts.back().Context == Unevaluated &&
+         "Should only transform unevaluated expressions");
+  ExprEvalContexts.back().Context =
+      ExprEvalContexts[ExprEvalContexts.size()-2].Context;
+  if (ExprEvalContexts.back().Context == Unevaluated)
+    return E;
+  return TransformToPE(*this).TransformExpr(E);
+}
+
+void
+Sema::PushExpressionEvaluationContext(ExpressionEvaluationContext NewContext,
+                                      Decl *LambdaContextDecl,
+                                      bool IsDecltype) {
+  ExprEvalContexts.push_back(
+             ExpressionEvaluationContextRecord(NewContext,
+                                               ExprCleanupObjects.size(),
+                                               ExprNeedsCleanups,
+                                               LambdaContextDecl,
+                                               IsDecltype));
+  ExprNeedsCleanups = false;
+  if (!MaybeODRUseExprs.empty())
+    std::swap(MaybeODRUseExprs, ExprEvalContexts.back().SavedMaybeODRUseExprs);
+}
+
+void Sema::PopExpressionEvaluationContext() {
+  ExpressionEvaluationContextRecord& Rec = ExprEvalContexts.back();
+
+  if (!Rec.Lambdas.empty()) {
+    if (Rec.Context == Unevaluated) {
+      // C++11 [expr.prim.lambda]p2:
+      //   A lambda-expression shall not appear in an unevaluated operand
+      //   (Clause 5).
+      for (unsigned I = 0, N = Rec.Lambdas.size(); I != N; ++I)
+        Diag(Rec.Lambdas[I]->getLocStart(), 
+             diag::err_lambda_unevaluated_operand);
+    } else {
+      // Mark the capture expressions odr-used. This was deferred
+      // during lambda expression creation.
+      for (unsigned I = 0, N = Rec.Lambdas.size(); I != N; ++I) {
+        LambdaExpr *Lambda = Rec.Lambdas[I];
+        for (LambdaExpr::capture_init_iterator 
+                  C = Lambda->capture_init_begin(),
+               CEnd = Lambda->capture_init_end();
+             C != CEnd; ++C) {
+          MarkDeclarationsReferencedInExpr(*C);
+        }
+      }
+    }
+  }
+
+  // When are coming out of an unevaluated context, clear out any
+  // temporaries that we may have created as part of the evaluation of
+  // the expression in that context: they aren't relevant because they
+  // will never be constructed.
+  if (Rec.Context == Unevaluated || Rec.Context == ConstantEvaluated) {
+    ExprCleanupObjects.erase(ExprCleanupObjects.begin() + Rec.NumCleanupObjects,
+                             ExprCleanupObjects.end());
+    ExprNeedsCleanups = Rec.ParentNeedsCleanups;
+    CleanupVarDeclMarking();
+    std::swap(MaybeODRUseExprs, Rec.SavedMaybeODRUseExprs);
+  // Otherwise, merge the contexts together.
+  } else {
+    ExprNeedsCleanups |= Rec.ParentNeedsCleanups;
+    MaybeODRUseExprs.insert(Rec.SavedMaybeODRUseExprs.begin(),
+                            Rec.SavedMaybeODRUseExprs.end());
+  }
+
+  // Pop the current expression evaluation context off the stack.
+  ExprEvalContexts.pop_back();
+}
+
+void Sema::DiscardCleanupsInEvaluationContext() {
+  ExprCleanupObjects.erase(
+         ExprCleanupObjects.begin() + ExprEvalContexts.back().NumCleanupObjects,
+         ExprCleanupObjects.end());
+  ExprNeedsCleanups = false;
+  MaybeODRUseExprs.clear();
+}
+
+ExprResult Sema::HandleExprEvaluationContextForTypeof(Expr *E) {
+  if (!E->getType()->isVariablyModifiedType())
+    return E;
+  return TranformToPotentiallyEvaluated(E);
+}
+
+static bool IsPotentiallyEvaluatedContext(Sema &SemaRef) {
+  // Do not mark anything as "used" within a dependent context; wait for
+  // an instantiation.
+  if (SemaRef.CurContext->isDependentContext())
+    return false;
+
+  switch (SemaRef.ExprEvalContexts.back().Context) {
+    case Sema::Unevaluated:
+      // We are in an expression that is not potentially evaluated; do nothing.
+      // (Depending on how you read the standard, we actually do need to do
+      // something here for null pointer constants, but the standard's
+      // definition of a null pointer constant is completely crazy.)
+      return false;
+
+    case Sema::ConstantEvaluated:
+    case Sema::PotentiallyEvaluated:
+      // We are in a potentially evaluated expression (or a constant-expression
+      // in C++03); we need to do implicit template instantiation, implicitly
+      // define class members, and mark most declarations as used.
+      return true;
+
+    case Sema::PotentiallyEvaluatedIfUsed:
+      // Referenced declarations will only be used if the construct in the
+      // containing expression is used.
+      return false;
+  }
+  llvm_unreachable("Invalid context");
+}
+
+/// \brief Mark a function referenced, and check whether it is odr-used
+/// (C++ [basic.def.odr]p2, C99 6.9p3)
+void Sema::MarkFunctionReferenced(SourceLocation Loc, FunctionDecl *Func) {
+  assert(Func && "No function?");
+
+  Func->setReferenced();
+
+  // Don't mark this function as used multiple times, unless it's a constexpr
+  // function which we need to instantiate.
+  if (Func->isUsed(false) &&
+      !(Func->isConstexpr() && !Func->getBody() &&
+        Func->isImplicitlyInstantiable()))
+    return;
+
+  if (!IsPotentiallyEvaluatedContext(*this))
+    return;
+
+  // Note that this declaration has been used.
+  if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(Func)) {
+    if (Constructor->isDefaulted() && !Constructor->isDeleted()) {
+      if (Constructor->isDefaultConstructor()) {
+        if (Constructor->isTrivial())
+          return;
+        if (!Constructor->isUsed(false))
+          DefineImplicitDefaultConstructor(Loc, Constructor);
+      } else if (Constructor->isCopyConstructor()) {
+        if (!Constructor->isUsed(false))
+          DefineImplicitCopyConstructor(Loc, Constructor);
+      } else if (Constructor->isMoveConstructor()) {
+        if (!Constructor->isUsed(false))
+          DefineImplicitMoveConstructor(Loc, Constructor);
+      }
+    }
+
+    MarkVTableUsed(Loc, Constructor->getParent());
+  } else if (CXXDestructorDecl *Destructor =
+                 dyn_cast<CXXDestructorDecl>(Func)) {
+    if (Destructor->isDefaulted() && !Destructor->isDeleted() &&
+        !Destructor->isUsed(false))
+      DefineImplicitDestructor(Loc, Destructor);
+    if (Destructor->isVirtual())
+      MarkVTableUsed(Loc, Destructor->getParent());
+  } else if (CXXMethodDecl *MethodDecl = dyn_cast<CXXMethodDecl>(Func)) {
+    if (MethodDecl->isDefaulted() && !MethodDecl->isDeleted() &&
+        MethodDecl->isOverloadedOperator() &&
+        MethodDecl->getOverloadedOperator() == OO_Equal) {
+      if (!MethodDecl->isUsed(false)) {
+        if (MethodDecl->isCopyAssignmentOperator())
+          DefineImplicitCopyAssignment(Loc, MethodDecl);
+        else
+          DefineImplicitMoveAssignment(Loc, MethodDecl);
+      }
+    } else if (isa<CXXConversionDecl>(MethodDecl) &&
+               MethodDecl->getParent()->isLambda()) {
+      CXXConversionDecl *Conversion = cast<CXXConversionDecl>(MethodDecl);
+      if (Conversion->isLambdaToBlockPointerConversion())
+        DefineImplicitLambdaToBlockPointerConversion(Loc, Conversion);
+      else
+        DefineImplicitLambdaToFunctionPointerConversion(Loc, Conversion);
+    } else if (MethodDecl->isVirtual())
+      MarkVTableUsed(Loc, MethodDecl->getParent());
+  }
+
+  // Recursive functions should be marked when used from another function.
+  // FIXME: Is this really right?
+  if (CurContext == Func) return;
+
+  // Instantiate the exception specification for any function which is
+  // used: CodeGen will need it.
+  const FunctionProtoType *FPT = Func->getType()->getAs<FunctionProtoType>();
+  if (FPT && FPT->getExceptionSpecType() == EST_Uninstantiated)
+    InstantiateExceptionSpec(Loc, Func);
+
+  // Implicit instantiation of function templates and member functions of
+  // class templates.
+  if (Func->isImplicitlyInstantiable()) {
+    bool AlreadyInstantiated = false;
+    SourceLocation PointOfInstantiation = Loc;
+    if (FunctionTemplateSpecializationInfo *SpecInfo
+                              = Func->getTemplateSpecializationInfo()) {
+      if (SpecInfo->getPointOfInstantiation().isInvalid())
+        SpecInfo->setPointOfInstantiation(Loc);
+      else if (SpecInfo->getTemplateSpecializationKind()
+                 == TSK_ImplicitInstantiation) {
+        AlreadyInstantiated = true;
+        PointOfInstantiation = SpecInfo->getPointOfInstantiation();
+      }
+    } else if (MemberSpecializationInfo *MSInfo
+                                = Func->getMemberSpecializationInfo()) {
+      if (MSInfo->getPointOfInstantiation().isInvalid())
+        MSInfo->setPointOfInstantiation(Loc);
+      else if (MSInfo->getTemplateSpecializationKind()
+                 == TSK_ImplicitInstantiation) {
+        AlreadyInstantiated = true;
+        PointOfInstantiation = MSInfo->getPointOfInstantiation();
+      }
+    }
+
+    if (!AlreadyInstantiated || Func->isConstexpr()) {
+      if (isa<CXXRecordDecl>(Func->getDeclContext()) &&
+          cast<CXXRecordDecl>(Func->getDeclContext())->isLocalClass())
+        PendingLocalImplicitInstantiations.push_back(
+            std::make_pair(Func, PointOfInstantiation));
+      else if (Func->isConstexpr())
+        // Do not defer instantiations of constexpr functions, to avoid the
+        // expression evaluator needing to call back into Sema if it sees a
+        // call to such a function.
+        InstantiateFunctionDefinition(PointOfInstantiation, Func);
+      else {
+        PendingInstantiations.push_back(std::make_pair(Func,
+                                                       PointOfInstantiation));
+        // Notify the consumer that a function was implicitly instantiated.
+        Consumer.HandleCXXImplicitFunctionInstantiation(Func);
+      }
+    }
+  } else {
+    // Walk redefinitions, as some of them may be instantiable.
+    for (FunctionDecl::redecl_iterator i(Func->redecls_begin()),
+         e(Func->redecls_end()); i != e; ++i) {
+      if (!i->isUsed(false) && i->isImplicitlyInstantiable())
+        MarkFunctionReferenced(Loc, *i);
+    }
+  }
+
+  // Keep track of used but undefined functions.
+  if (!Func->isPure() && !Func->hasBody() &&
+      Func->getLinkage() != ExternalLinkage) {
+    SourceLocation &old = UndefinedInternals[Func->getCanonicalDecl()];
+    if (old.isInvalid()) old = Loc;
+  }
+
+  Func->setUsed(true);
+}
+
+static void
+diagnoseUncapturableValueReference(Sema &S, SourceLocation loc,
+                                   VarDecl *var, DeclContext *DC) {
+  DeclContext *VarDC = var->getDeclContext();
+
+  //  If the parameter still belongs to the translation unit, then
+  //  we're actually just using one parameter in the declaration of
+  //  the next.
+  if (isa<ParmVarDecl>(var) &&
+      isa<TranslationUnitDecl>(VarDC))
+    return;
+
+  // For C code, don't diagnose about capture if we're not actually in code
+  // right now; it's impossible to write a non-constant expression outside of
+  // function context, so we'll get other (more useful) diagnostics later.
+  //
+  // For C++, things get a bit more nasty... it would be nice to suppress this
+  // diagnostic for certain cases like using a local variable in an array bound
+  // for a member of a local class, but the correct predicate is not obvious.
+  if (!S.getLangOpts().CPlusPlus && !S.CurContext->isFunctionOrMethod())
+    return;
+
+  if (isa<CXXMethodDecl>(VarDC) &&
+      cast<CXXRecordDecl>(VarDC->getParent())->isLambda()) {
+    S.Diag(loc, diag::err_reference_to_local_var_in_enclosing_lambda)
+      << var->getIdentifier();
+  } else if (FunctionDecl *fn = dyn_cast<FunctionDecl>(VarDC)) {
+    S.Diag(loc, diag::err_reference_to_local_var_in_enclosing_function)
+      << var->getIdentifier() << fn->getDeclName();
+  } else if (isa<BlockDecl>(VarDC)) {
+    S.Diag(loc, diag::err_reference_to_local_var_in_enclosing_block)
+      << var->getIdentifier();
+  } else {
+    // FIXME: Is there any other context where a local variable can be
+    // declared?
+    S.Diag(loc, diag::err_reference_to_local_var_in_enclosing_context)
+      << var->getIdentifier();
+  }
+
+  S.Diag(var->getLocation(), diag::note_local_variable_declared_here)
+    << var->getIdentifier();
+
+  // FIXME: Add additional diagnostic info about class etc. which prevents
+  // capture.
+}
+
+/// \brief Capture the given variable in the given lambda expression.
+static ExprResult captureInLambda(Sema &S, LambdaScopeInfo *LSI,
+                                  VarDecl *Var, QualType FieldType, 
+                                  QualType DeclRefType,
+                                  SourceLocation Loc) {
+  CXXRecordDecl *Lambda = LSI->Lambda;
+
+  // Build the non-static data member.
+  FieldDecl *Field
+    = FieldDecl::Create(S.Context, Lambda, Loc, Loc, 0, FieldType,
+                        S.Context.getTrivialTypeSourceInfo(FieldType, Loc),
+                        0, false, false);
+  Field->setImplicit(true);
+  Field->setAccess(AS_private);
+  Lambda->addDecl(Field);
+
+  // C++11 [expr.prim.lambda]p21:
+  //   When the lambda-expression is evaluated, the entities that
+  //   are captured by copy are used to direct-initialize each
+  //   corresponding non-static data member of the resulting closure
+  //   object. (For array members, the array elements are
+  //   direct-initialized in increasing subscript order.) These
+  //   initializations are performed in the (unspecified) order in
+  //   which the non-static data members are declared.
+      
+  // Introduce a new evaluation context for the initialization, so
+  // that temporaries introduced as part of the capture are retained
+  // to be re-"exported" from the lambda expression itself.
+  S.PushExpressionEvaluationContext(Sema::PotentiallyEvaluated);
+
+  // C++ [expr.prim.labda]p12:
+  //   An entity captured by a lambda-expression is odr-used (3.2) in
+  //   the scope containing the lambda-expression.
+  Expr *Ref = new (S.Context) DeclRefExpr(Var, false, DeclRefType,
+                                          VK_LValue, Loc);
+  Var->setReferenced(true);
+  Var->setUsed(true);
+
+  // When the field has array type, create index variables for each
+  // dimension of the array. We use these index variables to subscript
+  // the source array, and other clients (e.g., CodeGen) will perform
+  // the necessary iteration with these index variables.
+  SmallVector<VarDecl *, 4> IndexVariables;
+  QualType BaseType = FieldType;
+  QualType SizeType = S.Context.getSizeType();
+  LSI->ArrayIndexStarts.push_back(LSI->ArrayIndexVars.size());
+  while (const ConstantArrayType *Array
+                        = S.Context.getAsConstantArrayType(BaseType)) {
+    // Create the iteration variable for this array index.
+    IdentifierInfo *IterationVarName = 0;
+    {
+      SmallString<8> Str;
+      llvm::raw_svector_ostream OS(Str);
+      OS << "__i" << IndexVariables.size();
+      IterationVarName = &S.Context.Idents.get(OS.str());
+    }
+    VarDecl *IterationVar
+      = VarDecl::Create(S.Context, S.CurContext, Loc, Loc,
+                        IterationVarName, SizeType,
+                        S.Context.getTrivialTypeSourceInfo(SizeType, Loc),
+                        SC_None, SC_None);
+    IndexVariables.push_back(IterationVar);
+    LSI->ArrayIndexVars.push_back(IterationVar);
+    
+    // Create a reference to the iteration variable.
+    ExprResult IterationVarRef
+      = S.BuildDeclRefExpr(IterationVar, SizeType, VK_LValue, Loc);
+    assert(!IterationVarRef.isInvalid() &&
+           "Reference to invented variable cannot fail!");
+    IterationVarRef = S.DefaultLvalueConversion(IterationVarRef.take());
+    assert(!IterationVarRef.isInvalid() &&
+           "Conversion of invented variable cannot fail!");
+    
+    // Subscript the array with this iteration variable.
+    ExprResult Subscript = S.CreateBuiltinArraySubscriptExpr(
+                             Ref, Loc, IterationVarRef.take(), Loc);
+    if (Subscript.isInvalid()) {
+      S.CleanupVarDeclMarking();
+      S.DiscardCleanupsInEvaluationContext();
+      S.PopExpressionEvaluationContext();
+      return ExprError();
+    }
+
+    Ref = Subscript.take();
+    BaseType = Array->getElementType();
+  }
+
+  // Construct the entity that we will be initializing. For an array, this
+  // will be first element in the array, which may require several levels
+  // of array-subscript entities. 
+  SmallVector<InitializedEntity, 4> Entities;
+  Entities.reserve(1 + IndexVariables.size());
+  Entities.push_back(
+    InitializedEntity::InitializeLambdaCapture(Var, Field, Loc));
+  for (unsigned I = 0, N = IndexVariables.size(); I != N; ++I)
+    Entities.push_back(InitializedEntity::InitializeElement(S.Context,
+                                                            0,
+                                                            Entities.back()));
+
+  InitializationKind InitKind
+    = InitializationKind::CreateDirect(Loc, Loc, Loc);
+  InitializationSequence Init(S, Entities.back(), InitKind, &Ref, 1);
+  ExprResult Result(true);
+  if (!Init.Diagnose(S, Entities.back(), InitKind, &Ref, 1))
+    Result = Init.Perform(S, Entities.back(), InitKind, 
+                          MultiExprArg(S, &Ref, 1));
+
+  // If this initialization requires any cleanups (e.g., due to a
+  // default argument to a copy constructor), note that for the
+  // lambda.
+  if (S.ExprNeedsCleanups)
+    LSI->ExprNeedsCleanups = true;
+
+  // Exit the expression evaluation context used for the capture.
+  S.CleanupVarDeclMarking();
+  S.DiscardCleanupsInEvaluationContext();
+  S.PopExpressionEvaluationContext();
+  return Result;
+}
+
+bool Sema::tryCaptureVariable(VarDecl *Var, SourceLocation Loc, 
+                              TryCaptureKind Kind, SourceLocation EllipsisLoc,
+                              bool BuildAndDiagnose, 
+                              QualType &CaptureType,
+                              QualType &DeclRefType) {
+  bool Nested = false;
+  
+  DeclContext *DC = CurContext;
+  if (Var->getDeclContext() == DC) return true;
+  if (!Var->hasLocalStorage()) return true;
+
+  bool HasBlocksAttr = Var->hasAttr<BlocksAttr>();
+
+  // Walk up the stack to determine whether we can capture the variable,
+  // performing the "simple" checks that don't depend on type. We stop when
+  // we've either hit the declared scope of the variable or find an existing
+  // capture of that variable.
+  CaptureType = Var->getType();
+  DeclRefType = CaptureType.getNonReferenceType();
+  bool Explicit = (Kind != TryCapture_Implicit);
+  unsigned FunctionScopesIndex = FunctionScopes.size() - 1;
+  do {
+    // Only block literals and lambda expressions can capture; other
+    // scopes don't work.
+    DeclContext *ParentDC;
+    if (isa<BlockDecl>(DC))
+      ParentDC = DC->getParent();
+    else if (isa<CXXMethodDecl>(DC) &&
+             cast<CXXMethodDecl>(DC)->getOverloadedOperator() == OO_Call &&
+             cast<CXXRecordDecl>(DC->getParent())->isLambda())
+      ParentDC = DC->getParent()->getParent();
+    else {
+      if (BuildAndDiagnose)
+        diagnoseUncapturableValueReference(*this, Loc, Var, DC);
+      return true;
+    }
+
+    CapturingScopeInfo *CSI =
+      cast<CapturingScopeInfo>(FunctionScopes[FunctionScopesIndex]);
+
+    // Check whether we've already captured it.
+    if (CSI->CaptureMap.count(Var)) {
+      // If we found a capture, any subcaptures are nested.
+      Nested = true;
+      
+      // Retrieve the capture type for this variable.
+      CaptureType = CSI->getCapture(Var).getCaptureType();
+      
+      // Compute the type of an expression that refers to this variable.
+      DeclRefType = CaptureType.getNonReferenceType();
+      
+      const CapturingScopeInfo::Capture &Cap = CSI->getCapture(Var);
+      if (Cap.isCopyCapture() &&
+          !(isa<LambdaScopeInfo>(CSI) && cast<LambdaScopeInfo>(CSI)->Mutable))
+        DeclRefType.addConst();
+      break;
+    }
+
+    bool IsBlock = isa<BlockScopeInfo>(CSI);
+    bool IsLambda = !IsBlock;
+
+    // Lambdas are not allowed to capture unnamed variables
+    // (e.g. anonymous unions).
+    // FIXME: The C++11 rule don't actually state this explicitly, but I'm
+    // assuming that's the intent.
+    if (IsLambda && !Var->getDeclName()) {
+      if (BuildAndDiagnose) {
+        Diag(Loc, diag::err_lambda_capture_anonymous_var);
+        Diag(Var->getLocation(), diag::note_declared_at);
+      }
+      return true;
+    }
+
+    // Prohibit variably-modified types; they're difficult to deal with.
+    if (Var->getType()->isVariablyModifiedType()) {
+      if (BuildAndDiagnose) {
+        if (IsBlock)
+          Diag(Loc, diag::err_ref_vm_type);
+        else
+          Diag(Loc, diag::err_lambda_capture_vm_type) << Var->getDeclName();
+        Diag(Var->getLocation(), diag::note_previous_decl) 
+          << Var->getDeclName();
+      }
+      return true;
+    }
+
+    // Lambdas are not allowed to capture __block variables; they don't
+    // support the expected semantics.
+    if (IsLambda && HasBlocksAttr) {
+      if (BuildAndDiagnose) {
+        Diag(Loc, diag::err_lambda_capture_block) 
+          << Var->getDeclName();
+        Diag(Var->getLocation(), diag::note_previous_decl) 
+          << Var->getDeclName();
+      }
+      return true;
+    }
+
+    if (CSI->ImpCaptureStyle == CapturingScopeInfo::ImpCap_None && !Explicit) {
+      // No capture-default
+      if (BuildAndDiagnose) {
+        Diag(Loc, diag::err_lambda_impcap) << Var->getDeclName();
+        Diag(Var->getLocation(), diag::note_previous_decl) 
+          << Var->getDeclName();
+        Diag(cast<LambdaScopeInfo>(CSI)->Lambda->getLocStart(),
+             diag::note_lambda_decl);
+      }
+      return true;
+    }
+
+    FunctionScopesIndex--;
+    DC = ParentDC;
+    Explicit = false;
+  } while (!Var->getDeclContext()->Equals(DC));
+
+  // Walk back down the scope stack, computing the type of the capture at
+  // each step, checking type-specific requirements, and adding captures if
+  // requested.
+  for (unsigned I = ++FunctionScopesIndex, N = FunctionScopes.size(); I != N; 
+       ++I) {
+    CapturingScopeInfo *CSI = cast<CapturingScopeInfo>(FunctionScopes[I]);
+    
+    // Compute the type of the capture and of a reference to the capture within
+    // this scope.
+    if (isa<BlockScopeInfo>(CSI)) {
+      Expr *CopyExpr = 0;
+      bool ByRef = false;
+      
+      // Blocks are not allowed to capture arrays.
+      if (CaptureType->isArrayType()) {
+        if (BuildAndDiagnose) {
+          Diag(Loc, diag::err_ref_array_type);
+          Diag(Var->getLocation(), diag::note_previous_decl) 
+          << Var->getDeclName();
+        }
+        return true;
+      }
+
+      // Forbid the block-capture of autoreleasing variables.
+      if (CaptureType.getObjCLifetime() == Qualifiers::OCL_Autoreleasing) {
+        if (BuildAndDiagnose) {
+          Diag(Loc, diag::err_arc_autoreleasing_capture)
+            << /*block*/ 0;
+          Diag(Var->getLocation(), diag::note_previous_decl)
+            << Var->getDeclName();
+        }
+        return true;
+      }
+
+      if (HasBlocksAttr || CaptureType->isReferenceType()) {
+        // Block capture by reference does not change the capture or
+        // declaration reference types.
+        ByRef = true;
+      } else {
+        // Block capture by copy introduces 'const'.
+        CaptureType = CaptureType.getNonReferenceType().withConst();
+        DeclRefType = CaptureType;
+                
+        if (getLangOpts().CPlusPlus && BuildAndDiagnose) {
+          if (const RecordType *Record = DeclRefType->getAs<RecordType>()) {
+            // The capture logic needs the destructor, so make sure we mark it.
+            // Usually this is unnecessary because most local variables have
+            // their destructors marked at declaration time, but parameters are
+            // an exception because it's technically only the call site that
+            // actually requires the destructor.
+            if (isa<ParmVarDecl>(Var))
+              FinalizeVarWithDestructor(Var, Record);
+            
+            // According to the blocks spec, the capture of a variable from
+            // the stack requires a const copy constructor.  This is not true
+            // of the copy/move done to move a __block variable to the heap.
+            Expr *DeclRef = new (Context) DeclRefExpr(Var, false,
+                                                      DeclRefType.withConst(), 
+                                                      VK_LValue, Loc);
+            ExprResult Result
+              = PerformCopyInitialization(
+                  InitializedEntity::InitializeBlock(Var->getLocation(),
+                                                     CaptureType, false),
+                  Loc, Owned(DeclRef));
+            
+            // Build a full-expression copy expression if initialization
+            // succeeded and used a non-trivial constructor.  Recover from
+            // errors by pretending that the copy isn't necessary.
+            if (!Result.isInvalid() &&
+                !cast<CXXConstructExpr>(Result.get())->getConstructor()
+                   ->isTrivial()) {
+              Result = MaybeCreateExprWithCleanups(Result);
+              CopyExpr = Result.take();
+            }
+          }
+        }
+      }
+
+      // Actually capture the variable.
+      if (BuildAndDiagnose)
+        CSI->addCapture(Var, HasBlocksAttr, ByRef, Nested, Loc, 
+                        SourceLocation(), CaptureType, CopyExpr);
+      Nested = true;
+      continue;
+    } 
+    
+    LambdaScopeInfo *LSI = cast<LambdaScopeInfo>(CSI);
+    
+    // Determine whether we are capturing by reference or by value.
+    bool ByRef = false;
+    if (I == N - 1 && Kind != TryCapture_Implicit) {
+      ByRef = (Kind == TryCapture_ExplicitByRef);
+    } else {
+      ByRef = (LSI->ImpCaptureStyle == LambdaScopeInfo::ImpCap_LambdaByref);
+    }
+    
+    // Compute the type of the field that will capture this variable.
+    if (ByRef) {
+      // C++11 [expr.prim.lambda]p15:
+      //   An entity is captured by reference if it is implicitly or
+      //   explicitly captured but not captured by copy. It is
+      //   unspecified whether additional unnamed non-static data
+      //   members are declared in the closure type for entities
+      //   captured by reference.
+      //
+      // FIXME: It is not clear whether we want to build an lvalue reference
+      // to the DeclRefType or to CaptureType.getNonReferenceType(). GCC appears
+      // to do the former, while EDG does the latter. Core issue 1249 will 
+      // clarify, but for now we follow GCC because it's a more permissive and
+      // easily defensible position.
+      CaptureType = Context.getLValueReferenceType(DeclRefType);
+    } else {
+      // C++11 [expr.prim.lambda]p14:
+      //   For each entity captured by copy, an unnamed non-static
+      //   data member is declared in the closure type. The
+      //   declaration order of these members is unspecified. The type
+      //   of such a data member is the type of the corresponding
+      //   captured entity if the entity is not a reference to an
+      //   object, or the referenced type otherwise. [Note: If the
+      //   captured entity is a reference to a function, the
+      //   corresponding data member is also a reference to a
+      //   function. - end note ]
+      if (const ReferenceType *RefType = CaptureType->getAs<ReferenceType>()){
+        if (!RefType->getPointeeType()->isFunctionType())
+          CaptureType = RefType->getPointeeType();
+      }
+
+      // Forbid the lambda copy-capture of autoreleasing variables.
+      if (CaptureType.getObjCLifetime() == Qualifiers::OCL_Autoreleasing) {
+        if (BuildAndDiagnose) {
+          Diag(Loc, diag::err_arc_autoreleasing_capture) << /*lambda*/ 1;
+          Diag(Var->getLocation(), diag::note_previous_decl)
+            << Var->getDeclName();
+        }
+        return true;
+      }
+    }
+
+    // Capture this variable in the lambda.
+    Expr *CopyExpr = 0;
+    if (BuildAndDiagnose) {
+      ExprResult Result = captureInLambda(*this, LSI, Var, CaptureType,
+                                          DeclRefType, Loc);
+      if (!Result.isInvalid())
+        CopyExpr = Result.take();
+    }
+    
+    // Compute the type of a reference to this captured variable.
+    if (ByRef)
+      DeclRefType = CaptureType.getNonReferenceType();
+    else {
+      // C++ [expr.prim.lambda]p5:
+      //   The closure type for a lambda-expression has a public inline 
+      //   function call operator [...]. This function call operator is 
+      //   declared const (9.3.1) if and only if the lambda-expression’s 
+      //   parameter-declaration-clause is not followed by mutable.
+      DeclRefType = CaptureType.getNonReferenceType();
+      if (!LSI->Mutable && !CaptureType->isReferenceType())
+        DeclRefType.addConst();      
+    }
+    
+    // Add the capture.
+    if (BuildAndDiagnose)
+      CSI->addCapture(Var, /*IsBlock=*/false, ByRef, Nested, Loc,
+                      EllipsisLoc, CaptureType, CopyExpr);
+    Nested = true;
+  }
+
+  return false;
+}
+
+bool Sema::tryCaptureVariable(VarDecl *Var, SourceLocation Loc,
+                              TryCaptureKind Kind, SourceLocation EllipsisLoc) {  
+  QualType CaptureType;
+  QualType DeclRefType;
+  return tryCaptureVariable(Var, Loc, Kind, EllipsisLoc,
+                            /*BuildAndDiagnose=*/true, CaptureType,
+                            DeclRefType);
+}
+
+QualType Sema::getCapturedDeclRefType(VarDecl *Var, SourceLocation Loc) {
+  QualType CaptureType;
+  QualType DeclRefType;
+  
+  // Determine whether we can capture this variable.
+  if (tryCaptureVariable(Var, Loc, TryCapture_Implicit, SourceLocation(),
+                         /*BuildAndDiagnose=*/false, CaptureType, DeclRefType))
+    return QualType();
+
+  return DeclRefType;
+}
+
+static void MarkVarDeclODRUsed(Sema &SemaRef, VarDecl *Var,
+                               SourceLocation Loc) {
+  // Keep track of used but undefined variables.
+  // FIXME: We shouldn't suppress this warning for static data members.
+  if (Var->hasDefinition(SemaRef.Context) == VarDecl::DeclarationOnly &&
+      Var->getLinkage() != ExternalLinkage &&
+      !(Var->isStaticDataMember() && Var->hasInit())) {
+    SourceLocation &old = SemaRef.UndefinedInternals[Var->getCanonicalDecl()];
+    if (old.isInvalid()) old = Loc;
+  }
+
+  SemaRef.tryCaptureVariable(Var, Loc);
+
+  Var->setUsed(true);
+}
+
+void Sema::UpdateMarkingForLValueToRValue(Expr *E) {
+  // Per C++11 [basic.def.odr], a variable is odr-used "unless it is 
+  // an object that satisfies the requirements for appearing in a
+  // constant expression (5.19) and the lvalue-to-rvalue conversion (4.1)
+  // is immediately applied."  This function handles the lvalue-to-rvalue
+  // conversion part.
+  MaybeODRUseExprs.erase(E->IgnoreParens());
+}
+
+ExprResult Sema::ActOnConstantExpression(ExprResult Res) {
+  if (!Res.isUsable())
+    return Res;
+
+  // If a constant-expression is a reference to a variable where we delay
+  // deciding whether it is an odr-use, just assume we will apply the
+  // lvalue-to-rvalue conversion.  In the one case where this doesn't happen
+  // (a non-type template argument), we have special handling anyway.
+  UpdateMarkingForLValueToRValue(Res.get());
+  return Res;
+}
+
+void Sema::CleanupVarDeclMarking() {
+  for (llvm::SmallPtrSetIterator<Expr*> i = MaybeODRUseExprs.begin(),
+                                        e = MaybeODRUseExprs.end();
+       i != e; ++i) {
+    VarDecl *Var;
+    SourceLocation Loc;
+    if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(*i)) {
+      Var = cast<VarDecl>(DRE->getDecl());
+      Loc = DRE->getLocation();
+    } else if (MemberExpr *ME = dyn_cast<MemberExpr>(*i)) {
+      Var = cast<VarDecl>(ME->getMemberDecl());
+      Loc = ME->getMemberLoc();
+    } else {
+      llvm_unreachable("Unexpcted expression");
+    }
+
+    MarkVarDeclODRUsed(*this, Var, Loc);
+  }
+
+  MaybeODRUseExprs.clear();
+}
+
+// Mark a VarDecl referenced, and perform the necessary handling to compute
+// odr-uses.
+static void DoMarkVarDeclReferenced(Sema &SemaRef, SourceLocation Loc,
+                                    VarDecl *Var, Expr *E) {
+  Var->setReferenced();
+
+  if (!IsPotentiallyEvaluatedContext(SemaRef))
+    return;
+
+  // Implicit instantiation of static data members of class templates.
+  if (Var->isStaticDataMember() && Var->getInstantiatedFromStaticDataMember()) {
+    MemberSpecializationInfo *MSInfo = Var->getMemberSpecializationInfo();
+    assert(MSInfo && "Missing member specialization information?");
+    bool AlreadyInstantiated = !MSInfo->getPointOfInstantiation().isInvalid();
+    if (MSInfo->getTemplateSpecializationKind() == TSK_ImplicitInstantiation &&
+        (!AlreadyInstantiated ||
+         Var->isUsableInConstantExpressions(SemaRef.Context))) {
+      if (!AlreadyInstantiated) {
+        // This is a modification of an existing AST node. Notify listeners.
+        if (ASTMutationListener *L = SemaRef.getASTMutationListener())
+          L->StaticDataMemberInstantiated(Var);
+        MSInfo->setPointOfInstantiation(Loc);
+      }
+      SourceLocation PointOfInstantiation = MSInfo->getPointOfInstantiation();
+      if (Var->isUsableInConstantExpressions(SemaRef.Context))
+        // Do not defer instantiations of variables which could be used in a
+        // constant expression.
+        SemaRef.InstantiateStaticDataMemberDefinition(PointOfInstantiation,Var);
+      else
+        SemaRef.PendingInstantiations.push_back(
+            std::make_pair(Var, PointOfInstantiation));
+    }
+  }
+
+  // Per C++11 [basic.def.odr], a variable is odr-used "unless it is 
+  // an object that satisfies the requirements for appearing in a
+  // constant expression (5.19) and the lvalue-to-rvalue conversion (4.1)
+  // is immediately applied."  We check the first part here, and
+  // Sema::UpdateMarkingForLValueToRValue deals with the second part.
+  // Note that we use the C++11 definition everywhere because nothing in
+  // C++03 depends on whether we get the C++03 version correct. This does not
+  // apply to references, since they are not objects.
+  const VarDecl *DefVD;
+  if (E && !isa<ParmVarDecl>(Var) && !Var->getType()->isReferenceType() &&
+      Var->isUsableInConstantExpressions(SemaRef.Context) &&
+      Var->getAnyInitializer(DefVD) && DefVD->checkInitIsICE())
+    SemaRef.MaybeODRUseExprs.insert(E);
+  else
+    MarkVarDeclODRUsed(SemaRef, Var, Loc);
+}
+
+/// \brief Mark a variable referenced, and check whether it is odr-used
+/// (C++ [basic.def.odr]p2, C99 6.9p3).  Note that this should not be
+/// used directly for normal expressions referring to VarDecl.
+void Sema::MarkVariableReferenced(SourceLocation Loc, VarDecl *Var) {
+  DoMarkVarDeclReferenced(*this, Loc, Var, 0);
+}
+
+static void MarkExprReferenced(Sema &SemaRef, SourceLocation Loc,
+                               Decl *D, Expr *E) {
+  if (VarDecl *Var = dyn_cast<VarDecl>(D)) {
+    DoMarkVarDeclReferenced(SemaRef, Loc, Var, E);
+    return;
+  }
+
+  SemaRef.MarkAnyDeclReferenced(Loc, D);
+} 
+
+/// \brief Perform reference-marking and odr-use handling for a DeclRefExpr.
+void Sema::MarkDeclRefReferenced(DeclRefExpr *E) {
+  MarkExprReferenced(*this, E->getLocation(), E->getDecl(), E);
+}
+
+/// \brief Perform reference-marking and odr-use handling for a MemberExpr.
+void Sema::MarkMemberReferenced(MemberExpr *E) {
+  MarkExprReferenced(*this, E->getMemberLoc(), E->getMemberDecl(), E);
+}
+
+/// \brief Perform marking for a reference to an arbitrary declaration.  It
+/// marks the declaration referenced, and performs odr-use checking for functions
+/// and variables. This method should not be used when building an normal
+/// expression which refers to a variable.
+void Sema::MarkAnyDeclReferenced(SourceLocation Loc, Decl *D) {
+  if (VarDecl *VD = dyn_cast<VarDecl>(D))
+    MarkVariableReferenced(Loc, VD);
+  else if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
+    MarkFunctionReferenced(Loc, FD);
+  else
+    D->setReferenced();
+}
+
+namespace {
+  // Mark all of the declarations referenced
+  // FIXME: Not fully implemented yet! We need to have a better understanding
+  // of when we're entering
+  class MarkReferencedDecls : public RecursiveASTVisitor<MarkReferencedDecls> {
+    Sema &S;
+    SourceLocation Loc;
+
+  public:
+    typedef RecursiveASTVisitor<MarkReferencedDecls> Inherited;
+
+    MarkReferencedDecls(Sema &S, SourceLocation Loc) : S(S), Loc(Loc) { }
+
+    bool TraverseTemplateArgument(const TemplateArgument &Arg);
+    bool TraverseRecordType(RecordType *T);
+  };
+}
+
+bool MarkReferencedDecls::TraverseTemplateArgument(
+  const TemplateArgument &Arg) {
+  if (Arg.getKind() == TemplateArgument::Declaration) {
+    if (Decl *D = Arg.getAsDecl())
+      S.MarkAnyDeclReferenced(Loc, D);
+  }
+
+  return Inherited::TraverseTemplateArgument(Arg);
+}
+
+bool MarkReferencedDecls::TraverseRecordType(RecordType *T) {
+  if (ClassTemplateSpecializationDecl *Spec
+                  = dyn_cast<ClassTemplateSpecializationDecl>(T->getDecl())) {
+    const TemplateArgumentList &Args = Spec->getTemplateArgs();
+    return TraverseTemplateArguments(Args.data(), Args.size());
+  }
+
+  return true;
+}
+
+void Sema::MarkDeclarationsReferencedInType(SourceLocation Loc, QualType T) {
+  MarkReferencedDecls Marker(*this, Loc);
+  Marker.TraverseType(Context.getCanonicalType(T));
+}
+
+namespace {
+  /// \brief Helper class that marks all of the declarations referenced by
+  /// potentially-evaluated subexpressions as "referenced".
+  class EvaluatedExprMarker : public EvaluatedExprVisitor<EvaluatedExprMarker> {
+    Sema &S;
+    bool SkipLocalVariables;
+    
+  public:
+    typedef EvaluatedExprVisitor<EvaluatedExprMarker> Inherited;
+    
+    EvaluatedExprMarker(Sema &S, bool SkipLocalVariables) 
+      : Inherited(S.Context), S(S), SkipLocalVariables(SkipLocalVariables) { }
+    
+    void VisitDeclRefExpr(DeclRefExpr *E) {
+      // If we were asked not to visit local variables, don't.
+      if (SkipLocalVariables) {
+        if (VarDecl *VD = dyn_cast<VarDecl>(E->getDecl()))
+          if (VD->hasLocalStorage())
+            return;
+      }
+      
+      S.MarkDeclRefReferenced(E);
+    }
+    
+    void VisitMemberExpr(MemberExpr *E) {
+      S.MarkMemberReferenced(E);
+      Inherited::VisitMemberExpr(E);
+    }
+    
+    void VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *E) {
+      S.MarkFunctionReferenced(E->getLocStart(),
+            const_cast<CXXDestructorDecl*>(E->getTemporary()->getDestructor()));
+      Visit(E->getSubExpr());
+    }
+    
+    void VisitCXXNewExpr(CXXNewExpr *E) {
+      if (E->getOperatorNew())
+        S.MarkFunctionReferenced(E->getLocStart(), E->getOperatorNew());
+      if (E->getOperatorDelete())
+        S.MarkFunctionReferenced(E->getLocStart(), E->getOperatorDelete());
+      Inherited::VisitCXXNewExpr(E);
+    }
+
+    void VisitCXXDeleteExpr(CXXDeleteExpr *E) {
+      if (E->getOperatorDelete())
+        S.MarkFunctionReferenced(E->getLocStart(), E->getOperatorDelete());
+      QualType Destroyed = S.Context.getBaseElementType(E->getDestroyedType());
+      if (const RecordType *DestroyedRec = Destroyed->getAs<RecordType>()) {
+        CXXRecordDecl *Record = cast<CXXRecordDecl>(DestroyedRec->getDecl());
+        S.MarkFunctionReferenced(E->getLocStart(), 
+                                    S.LookupDestructor(Record));
+      }
+      
+      Inherited::VisitCXXDeleteExpr(E);
+    }
+    
+    void VisitCXXConstructExpr(CXXConstructExpr *E) {
+      S.MarkFunctionReferenced(E->getLocStart(), E->getConstructor());
+      Inherited::VisitCXXConstructExpr(E);
+    }
+    
+    void VisitCXXDefaultArgExpr(CXXDefaultArgExpr *E) {
+      Visit(E->getExpr());
+    }
+
+    void VisitImplicitCastExpr(ImplicitCastExpr *E) {
+      Inherited::VisitImplicitCastExpr(E);
+
+      if (E->getCastKind() == CK_LValueToRValue)
+        S.UpdateMarkingForLValueToRValue(E->getSubExpr());
+    }
+  };
+}
+
+/// \brief Mark any declarations that appear within this expression or any
+/// potentially-evaluated subexpressions as "referenced".
+///
+/// \param SkipLocalVariables If true, don't mark local variables as 
+/// 'referenced'.
+void Sema::MarkDeclarationsReferencedInExpr(Expr *E, 
+                                            bool SkipLocalVariables) {
+  EvaluatedExprMarker(*this, SkipLocalVariables).Visit(E);
+}
+
+/// \brief Emit a diagnostic that describes an effect on the run-time behavior
+/// of the program being compiled.
+///
+/// This routine emits the given diagnostic when the code currently being
+/// type-checked is "potentially evaluated", meaning that there is a
+/// possibility that the code will actually be executable. Code in sizeof()
+/// expressions, code used only during overload resolution, etc., are not
+/// potentially evaluated. This routine will suppress such diagnostics or,
+/// in the absolutely nutty case of potentially potentially evaluated
+/// expressions (C++ typeid), queue the diagnostic to potentially emit it
+/// later.
+///
+/// This routine should be used for all diagnostics that describe the run-time
+/// behavior of a program, such as passing a non-POD value through an ellipsis.
+/// Failure to do so will likely result in spurious diagnostics or failures
+/// during overload resolution or within sizeof/alignof/typeof/typeid.
+bool Sema::DiagRuntimeBehavior(SourceLocation Loc, const Stmt *Statement,
+                               const PartialDiagnostic &PD) {
+  switch (ExprEvalContexts.back().Context) {
+  case Unevaluated:
+    // The argument will never be evaluated, so don't complain.
+    break;
+
+  case ConstantEvaluated:
+    // Relevant diagnostics should be produced by constant evaluation.
+    break;
+
+  case PotentiallyEvaluated:
+  case PotentiallyEvaluatedIfUsed:
+    if (Statement && getCurFunctionOrMethodDecl()) {
+      FunctionScopes.back()->PossiblyUnreachableDiags.
+        push_back(sema::PossiblyUnreachableDiag(PD, Loc, Statement));
+    }
+    else
+      Diag(Loc, PD);
+      
+    return true;
+  }
+
+  return false;
+}
+
+bool Sema::CheckCallReturnType(QualType ReturnType, SourceLocation Loc,
+                               CallExpr *CE, FunctionDecl *FD) {
+  if (ReturnType->isVoidType() || !ReturnType->isIncompleteType())
+    return false;
+
+  // If we're inside a decltype's expression, don't check for a valid return
+  // type or construct temporaries until we know whether this is the last call.
+  if (ExprEvalContexts.back().IsDecltype) {
+    ExprEvalContexts.back().DelayedDecltypeCalls.push_back(CE);
+    return false;
+  }
+
+  PartialDiagnostic Note =
+    FD ? PDiag(diag::note_function_with_incomplete_return_type_declared_here)
+    << FD->getDeclName() : PDiag();
+  SourceLocation NoteLoc = FD ? FD->getLocation() : SourceLocation();
+
+  if (RequireCompleteType(Loc, ReturnType,
+                          FD ?
+                          PDiag(diag::err_call_function_incomplete_return)
+                            << CE->getSourceRange() << FD->getDeclName() :
+                          PDiag(diag::err_call_incomplete_return)
+                            << CE->getSourceRange(),
+                          std::make_pair(NoteLoc, Note)))
+    return true;
+
+  return false;
+}
+
+// Diagnose the s/=/==/ and s/\|=/!=/ typos. Note that adding parentheses
+// will prevent this condition from triggering, which is what we want.
+void Sema::DiagnoseAssignmentAsCondition(Expr *E) {
+  SourceLocation Loc;
+
+  unsigned diagnostic = diag::warn_condition_is_assignment;
+  bool IsOrAssign = false;
+
+  if (BinaryOperator *Op = dyn_cast<BinaryOperator>(E)) {
+    if (Op->getOpcode() != BO_Assign && Op->getOpcode() != BO_OrAssign)
+      return;
+
+    IsOrAssign = Op->getOpcode() == BO_OrAssign;
+
+    // Greylist some idioms by putting them into a warning subcategory.
+    if (ObjCMessageExpr *ME
+          = dyn_cast<ObjCMessageExpr>(Op->getRHS()->IgnoreParenCasts())) {
+      Selector Sel = ME->getSelector();
+
+      // self = [<foo> init...]
+      if (isSelfExpr(Op->getLHS()) && Sel.getNameForSlot(0).startswith("init"))
+        diagnostic = diag::warn_condition_is_idiomatic_assignment;
+
+      // <foo> = [<bar> nextObject]
+      else if (Sel.isUnarySelector() && Sel.getNameForSlot(0) == "nextObject")
+        diagnostic = diag::warn_condition_is_idiomatic_assignment;
+    }
+
+    Loc = Op->getOperatorLoc();
+  } else if (CXXOperatorCallExpr *Op = dyn_cast<CXXOperatorCallExpr>(E)) {
+    if (Op->getOperator() != OO_Equal && Op->getOperator() != OO_PipeEqual)
+      return;
+
+    IsOrAssign = Op->getOperator() == OO_PipeEqual;
+    Loc = Op->getOperatorLoc();
+  } else {
+    // Not an assignment.
+    return;
+  }
+
+  Diag(Loc, diagnostic) << E->getSourceRange();
+
+  SourceLocation Open = E->getLocStart();
+  SourceLocation Close = PP.getLocForEndOfToken(E->getSourceRange().getEnd());
+  Diag(Loc, diag::note_condition_assign_silence)
+        << FixItHint::CreateInsertion(Open, "(")
+        << FixItHint::CreateInsertion(Close, ")");
+
+  if (IsOrAssign)
+    Diag(Loc, diag::note_condition_or_assign_to_comparison)
+      << FixItHint::CreateReplacement(Loc, "!=");
+  else
+    Diag(Loc, diag::note_condition_assign_to_comparison)
+      << FixItHint::CreateReplacement(Loc, "==");
+}
+
+/// \brief Redundant parentheses over an equality comparison can indicate
+/// that the user intended an assignment used as condition.
+void Sema::DiagnoseEqualityWithExtraParens(ParenExpr *ParenE) {
+  // Don't warn if the parens came from a macro.
+  SourceLocation parenLoc = ParenE->getLocStart();
+  if (parenLoc.isInvalid() || parenLoc.isMacroID())
+    return;
+  // Don't warn for dependent expressions.
+  if (ParenE->isTypeDependent())
+    return;
+
+  Expr *E = ParenE->IgnoreParens();
+
+  if (BinaryOperator *opE = dyn_cast<BinaryOperator>(E))
+    if (opE->getOpcode() == BO_EQ &&
+        opE->getLHS()->IgnoreParenImpCasts()->isModifiableLvalue(Context)
+                                                           == Expr::MLV_Valid) {
+      SourceLocation Loc = opE->getOperatorLoc();
+      
+      Diag(Loc, diag::warn_equality_with_extra_parens) << E->getSourceRange();
+      SourceRange ParenERange = ParenE->getSourceRange();
+      Diag(Loc, diag::note_equality_comparison_silence)
+        << FixItHint::CreateRemoval(ParenERange.getBegin())
+        << FixItHint::CreateRemoval(ParenERange.getEnd());
+      Diag(Loc, diag::note_equality_comparison_to_assign)
+        << FixItHint::CreateReplacement(Loc, "=");
+    }
+}
+
+ExprResult Sema::CheckBooleanCondition(Expr *E, SourceLocation Loc) {
+  DiagnoseAssignmentAsCondition(E);
+  if (ParenExpr *parenE = dyn_cast<ParenExpr>(E))
+    DiagnoseEqualityWithExtraParens(parenE);
+
+  ExprResult result = CheckPlaceholderExpr(E);
+  if (result.isInvalid()) return ExprError();
+  E = result.take();
+
+  if (!E->isTypeDependent()) {
+    if (getLangOpts().CPlusPlus)
+      return CheckCXXBooleanCondition(E); // C++ 6.4p4
+
+    ExprResult ERes = DefaultFunctionArrayLvalueConversion(E);
+    if (ERes.isInvalid())
+      return ExprError();
+    E = ERes.take();
+
+    QualType T = E->getType();
+    if (!T->isScalarType()) { // C99 6.8.4.1p1
+      Diag(Loc, diag::err_typecheck_statement_requires_scalar)
+        << T << E->getSourceRange();
+      return ExprError();
+    }
+  }
+
+  return Owned(E);
+}
+
+ExprResult Sema::ActOnBooleanCondition(Scope *S, SourceLocation Loc,
+                                       Expr *SubExpr) {
+  if (!SubExpr)
+    return ExprError();
+
+  return CheckBooleanCondition(SubExpr, Loc);
+}
+
+namespace {
+  /// A visitor for rebuilding a call to an __unknown_any expression
+  /// to have an appropriate type.
+  struct RebuildUnknownAnyFunction
+    : StmtVisitor<RebuildUnknownAnyFunction, ExprResult> {
+
+    Sema &S;
+
+    RebuildUnknownAnyFunction(Sema &S) : S(S) {}
+
+    ExprResult VisitStmt(Stmt *S) {
+      llvm_unreachable("unexpected statement!");
+    }
+
+    ExprResult VisitExpr(Expr *E) {
+      S.Diag(E->getExprLoc(), diag::err_unsupported_unknown_any_call)
+        << E->getSourceRange();
+      return ExprError();
+    }
+
+    /// Rebuild an expression which simply semantically wraps another
+    /// expression which it shares the type and value kind of.
+    template <class T> ExprResult rebuildSugarExpr(T *E) {
+      ExprResult SubResult = Visit(E->getSubExpr());
+      if (SubResult.isInvalid()) return ExprError();
+
+      Expr *SubExpr = SubResult.take();
+      E->setSubExpr(SubExpr);
+      E->setType(SubExpr->getType());
+      E->setValueKind(SubExpr->getValueKind());
+      assert(E->getObjectKind() == OK_Ordinary);
+      return E;
+    }
+
+    ExprResult VisitParenExpr(ParenExpr *E) {
+      return rebuildSugarExpr(E);
+    }
+
+    ExprResult VisitUnaryExtension(UnaryOperator *E) {
+      return rebuildSugarExpr(E);
+    }
+
+    ExprResult VisitUnaryAddrOf(UnaryOperator *E) {
+      ExprResult SubResult = Visit(E->getSubExpr());
+      if (SubResult.isInvalid()) return ExprError();
+
+      Expr *SubExpr = SubResult.take();
+      E->setSubExpr(SubExpr);
+      E->setType(S.Context.getPointerType(SubExpr->getType()));
+      assert(E->getValueKind() == VK_RValue);
+      assert(E->getObjectKind() == OK_Ordinary);
+      return E;
+    }
+
+    ExprResult resolveDecl(Expr *E, ValueDecl *VD) {
+      if (!isa<FunctionDecl>(VD)) return VisitExpr(E);
+
+      E->setType(VD->getType());
+
+      assert(E->getValueKind() == VK_RValue);
+      if (S.getLangOpts().CPlusPlus &&
+          !(isa<CXXMethodDecl>(VD) &&
+            cast<CXXMethodDecl>(VD)->isInstance()))
+        E->setValueKind(VK_LValue);
+
+      return E;
+    }
+
+    ExprResult VisitMemberExpr(MemberExpr *E) {
+      return resolveDecl(E, E->getMemberDecl());
+    }
+
+    ExprResult VisitDeclRefExpr(DeclRefExpr *E) {
+      return resolveDecl(E, E->getDecl());
+    }
+  };
+}
+
+/// Given a function expression of unknown-any type, try to rebuild it
+/// to have a function type.
+static ExprResult rebuildUnknownAnyFunction(Sema &S, Expr *FunctionExpr) {
+  ExprResult Result = RebuildUnknownAnyFunction(S).Visit(FunctionExpr);
+  if (Result.isInvalid()) return ExprError();
+  return S.DefaultFunctionArrayConversion(Result.take());
+}
+
+namespace {
+  /// A visitor for rebuilding an expression of type __unknown_anytype
+  /// into one which resolves the type directly on the referring
+  /// expression.  Strict preservation of the original source
+  /// structure is not a goal.
+  struct RebuildUnknownAnyExpr
+    : StmtVisitor<RebuildUnknownAnyExpr, ExprResult> {
+
+    Sema &S;
+
+    /// The current destination type.
+    QualType DestType;
+
+    RebuildUnknownAnyExpr(Sema &S, QualType CastType)
+      : S(S), DestType(CastType) {}
+
+    ExprResult VisitStmt(Stmt *S) {
+      llvm_unreachable("unexpected statement!");
+    }
+
+    ExprResult VisitExpr(Expr *E) {
+      S.Diag(E->getExprLoc(), diag::err_unsupported_unknown_any_expr)
+        << E->getSourceRange();
+      return ExprError();
+    }
+
+    ExprResult VisitCallExpr(CallExpr *E);
+    ExprResult VisitObjCMessageExpr(ObjCMessageExpr *E);
+
+    /// Rebuild an expression which simply semantically wraps another
+    /// expression which it shares the type and value kind of.
+    template <class T> ExprResult rebuildSugarExpr(T *E) {
+      ExprResult SubResult = Visit(E->getSubExpr());
+      if (SubResult.isInvalid()) return ExprError();
+      Expr *SubExpr = SubResult.take();
+      E->setSubExpr(SubExpr);
+      E->setType(SubExpr->getType());
+      E->setValueKind(SubExpr->getValueKind());
+      assert(E->getObjectKind() == OK_Ordinary);
+      return E;
+    }
+
+    ExprResult VisitParenExpr(ParenExpr *E) {
+      return rebuildSugarExpr(E);
+    }
+
+    ExprResult VisitUnaryExtension(UnaryOperator *E) {
+      return rebuildSugarExpr(E);
+    }
+
+    ExprResult VisitUnaryAddrOf(UnaryOperator *E) {
+      const PointerType *Ptr = DestType->getAs<PointerType>();
+      if (!Ptr) {
+        S.Diag(E->getOperatorLoc(), diag::err_unknown_any_addrof)
+          << E->getSourceRange();
+        return ExprError();
+      }
+      assert(E->getValueKind() == VK_RValue);
+      assert(E->getObjectKind() == OK_Ordinary);
+      E->setType(DestType);
+
+      // Build the sub-expression as if it were an object of the pointee type.
+      DestType = Ptr->getPointeeType();
+      ExprResult SubResult = Visit(E->getSubExpr());
+      if (SubResult.isInvalid()) return ExprError();
+      E->setSubExpr(SubResult.take());
+      return E;
+    }
+
+    ExprResult VisitImplicitCastExpr(ImplicitCastExpr *E);
+
+    ExprResult resolveDecl(Expr *E, ValueDecl *VD);
+
+    ExprResult VisitMemberExpr(MemberExpr *E) {
+      return resolveDecl(E, E->getMemberDecl());
+    }
+
+    ExprResult VisitDeclRefExpr(DeclRefExpr *E) {
+      return resolveDecl(E, E->getDecl());
+    }
+  };
+}
+
+/// Rebuilds a call expression which yielded __unknown_anytype.
+ExprResult RebuildUnknownAnyExpr::VisitCallExpr(CallExpr *E) {
+  Expr *CalleeExpr = E->getCallee();
+
+  enum FnKind {
+    FK_MemberFunction,
+    FK_FunctionPointer,
+    FK_BlockPointer
+  };
+
+  FnKind Kind;
+  QualType CalleeType = CalleeExpr->getType();
+  if (CalleeType == S.Context.BoundMemberTy) {
+    assert(isa<CXXMemberCallExpr>(E) || isa<CXXOperatorCallExpr>(E));
+    Kind = FK_MemberFunction;
+    CalleeType = Expr::findBoundMemberType(CalleeExpr);
+  } else if (const PointerType *Ptr = CalleeType->getAs<PointerType>()) {
+    CalleeType = Ptr->getPointeeType();
+    Kind = FK_FunctionPointer;
+  } else {
+    CalleeType = CalleeType->castAs<BlockPointerType>()->getPointeeType();
+    Kind = FK_BlockPointer;
+  }
+  const FunctionType *FnType = CalleeType->castAs<FunctionType>();
+
+  // Verify that this is a legal result type of a function.
+  if (DestType->isArrayType() || DestType->isFunctionType()) {
+    unsigned diagID = diag::err_func_returning_array_function;
+    if (Kind == FK_BlockPointer)
+      diagID = diag::err_block_returning_array_function;
+
+    S.Diag(E->getExprLoc(), diagID)
+      << DestType->isFunctionType() << DestType;
+    return ExprError();
+  }
+
+  // Otherwise, go ahead and set DestType as the call's result.
+  E->setType(DestType.getNonLValueExprType(S.Context));
+  E->setValueKind(Expr::getValueKindForType(DestType));
+  assert(E->getObjectKind() == OK_Ordinary);
+
+  // Rebuild the function type, replacing the result type with DestType.
+  if (const FunctionProtoType *Proto = dyn_cast<FunctionProtoType>(FnType))
+    DestType = S.Context.getFunctionType(DestType,
+                                         Proto->arg_type_begin(),
+                                         Proto->getNumArgs(),
+                                         Proto->getExtProtoInfo());
+  else
+    DestType = S.Context.getFunctionNoProtoType(DestType,
+                                                FnType->getExtInfo());
+
+  // Rebuild the appropriate pointer-to-function type.
+  switch (Kind) { 
+  case FK_MemberFunction:
+    // Nothing to do.
+    break;
+
+  case FK_FunctionPointer:
+    DestType = S.Context.getPointerType(DestType);
+    break;
+
+  case FK_BlockPointer:
+    DestType = S.Context.getBlockPointerType(DestType);
+    break;
+  }
+
+  // Finally, we can recurse.
+  ExprResult CalleeResult = Visit(CalleeExpr);
+  if (!CalleeResult.isUsable()) return ExprError();
+  E->setCallee(CalleeResult.take());
+
+  // Bind a temporary if necessary.
+  return S.MaybeBindToTemporary(E);
+}
+
+ExprResult RebuildUnknownAnyExpr::VisitObjCMessageExpr(ObjCMessageExpr *E) {
+  // Verify that this is a legal result type of a call.
+  if (DestType->isArrayType() || DestType->isFunctionType()) {
+    S.Diag(E->getExprLoc(), diag::err_func_returning_array_function)
+      << DestType->isFunctionType() << DestType;
+    return ExprError();
+  }
+
+  // Rewrite the method result type if available.
+  if (ObjCMethodDecl *Method = E->getMethodDecl()) {
+    assert(Method->getResultType() == S.Context.UnknownAnyTy);
+    Method->setResultType(DestType);
+  }
+
+  // Change the type of the message.
+  E->setType(DestType.getNonReferenceType());
+  E->setValueKind(Expr::getValueKindForType(DestType));
+
+  return S.MaybeBindToTemporary(E);
+}
+
+ExprResult RebuildUnknownAnyExpr::VisitImplicitCastExpr(ImplicitCastExpr *E) {
+  // The only case we should ever see here is a function-to-pointer decay.
+  if (E->getCastKind() == CK_FunctionToPointerDecay) {
+    assert(E->getValueKind() == VK_RValue);
+    assert(E->getObjectKind() == OK_Ordinary);
+  
+    E->setType(DestType);
+  
+    // Rebuild the sub-expression as the pointee (function) type.
+    DestType = DestType->castAs<PointerType>()->getPointeeType();
+  
+    ExprResult Result = Visit(E->getSubExpr());
+    if (!Result.isUsable()) return ExprError();
+  
+    E->setSubExpr(Result.take());
+    return S.Owned(E);
+  } else if (E->getCastKind() == CK_LValueToRValue) {
+    assert(E->getValueKind() == VK_RValue);
+    assert(E->getObjectKind() == OK_Ordinary);
+
+    assert(isa<BlockPointerType>(E->getType()));
+
+    E->setType(DestType);
+
+    // The sub-expression has to be a lvalue reference, so rebuild it as such.
+    DestType = S.Context.getLValueReferenceType(DestType);
+
+    ExprResult Result = Visit(E->getSubExpr());
+    if (!Result.isUsable()) return ExprError();
+
+    E->setSubExpr(Result.take());
+    return S.Owned(E);
+  } else {
+    llvm_unreachable("Unhandled cast type!");
+  }
+}
+
+ExprResult RebuildUnknownAnyExpr::resolveDecl(Expr *E, ValueDecl *VD) {
+  ExprValueKind ValueKind = VK_LValue;
+  QualType Type = DestType;
+
+  // We know how to make this work for certain kinds of decls:
+
+  //  - functions
+  if (FunctionDecl *FD = dyn_cast<FunctionDecl>(VD)) {
+    if (const PointerType *Ptr = Type->getAs<PointerType>()) {
+      DestType = Ptr->getPointeeType();
+      ExprResult Result = resolveDecl(E, VD);
+      if (Result.isInvalid()) return ExprError();
+      return S.ImpCastExprToType(Result.take(), Type,
+                                 CK_FunctionToPointerDecay, VK_RValue);
+    }
+
+    if (!Type->isFunctionType()) {
+      S.Diag(E->getExprLoc(), diag::err_unknown_any_function)
+        << VD << E->getSourceRange();
+      return ExprError();
+    }
+
+    if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD))
+      if (MD->isInstance()) {
+        ValueKind = VK_RValue;
+        Type = S.Context.BoundMemberTy;
+      }
+
+    // Function references aren't l-values in C.
+    if (!S.getLangOpts().CPlusPlus)
+      ValueKind = VK_RValue;
+
+  //  - variables
+  } else if (isa<VarDecl>(VD)) {
+    if (const ReferenceType *RefTy = Type->getAs<ReferenceType>()) {
+      Type = RefTy->getPointeeType();
+    } else if (Type->isFunctionType()) {
+      S.Diag(E->getExprLoc(), diag::err_unknown_any_var_function_type)
+        << VD << E->getSourceRange();
+      return ExprError();
+    }
+
+  //  - nothing else
+  } else {
+    S.Diag(E->getExprLoc(), diag::err_unsupported_unknown_any_decl)
+      << VD << E->getSourceRange();
+    return ExprError();
+  }
+
+  VD->setType(DestType);
+  E->setType(Type);
+  E->setValueKind(ValueKind);
+  return S.Owned(E);
+}
+
+/// Check a cast of an unknown-any type.  We intentionally only
+/// trigger this for C-style casts.
+ExprResult Sema::checkUnknownAnyCast(SourceRange TypeRange, QualType CastType,
+                                     Expr *CastExpr, CastKind &CastKind,
+                                     ExprValueKind &VK, CXXCastPath &Path) {
+  // Rewrite the casted expression from scratch.
+  ExprResult result = RebuildUnknownAnyExpr(*this, CastType).Visit(CastExpr);
+  if (!result.isUsable()) return ExprError();
+
+  CastExpr = result.take();
+  VK = CastExpr->getValueKind();
+  CastKind = CK_NoOp;
+
+  return CastExpr;
+}
+
+ExprResult Sema::forceUnknownAnyToType(Expr *E, QualType ToType) {
+  return RebuildUnknownAnyExpr(*this, ToType).Visit(E);
+}
+
+static ExprResult diagnoseUnknownAnyExpr(Sema &S, Expr *E) {
+  Expr *orig = E;
+  unsigned diagID = diag::err_uncasted_use_of_unknown_any;
+  while (true) {
+    E = E->IgnoreParenImpCasts();
+    if (CallExpr *call = dyn_cast<CallExpr>(E)) {
+      E = call->getCallee();
+      diagID = diag::err_uncasted_call_of_unknown_any;
+    } else {
+      break;
+    }
+  }
+
+  SourceLocation loc;
+  NamedDecl *d;
+  if (DeclRefExpr *ref = dyn_cast<DeclRefExpr>(E)) {
+    loc = ref->getLocation();
+    d = ref->getDecl();
+  } else if (MemberExpr *mem = dyn_cast<MemberExpr>(E)) {
+    loc = mem->getMemberLoc();
+    d = mem->getMemberDecl();
+  } else if (ObjCMessageExpr *msg = dyn_cast<ObjCMessageExpr>(E)) {
+    diagID = diag::err_uncasted_call_of_unknown_any;
+    loc = msg->getSelectorStartLoc();
+    d = msg->getMethodDecl();
+    if (!d) {
+      S.Diag(loc, diag::err_uncasted_send_to_unknown_any_method)
+        << static_cast<unsigned>(msg->isClassMessage()) << msg->getSelector()
+        << orig->getSourceRange();
+      return ExprError();
+    }
+  } else {
+    S.Diag(E->getExprLoc(), diag::err_unsupported_unknown_any_expr)
+      << E->getSourceRange();
+    return ExprError();
+  }
+
+  S.Diag(loc, diagID) << d << orig->getSourceRange();
+
+  // Never recoverable.
+  return ExprError();
+}
+
+/// Check for operands with placeholder types and complain if found.
+/// Returns true if there was an error and no recovery was possible.
+ExprResult Sema::CheckPlaceholderExpr(Expr *E) {
+  const BuiltinType *placeholderType = E->getType()->getAsPlaceholderType();
+  if (!placeholderType) return Owned(E);
+
+  switch (placeholderType->getKind()) {
+
+  // Overloaded expressions.
+  case BuiltinType::Overload: {
+    // Try to resolve a single function template specialization.
+    // This is obligatory.
+    ExprResult result = Owned(E);
+    if (ResolveAndFixSingleFunctionTemplateSpecialization(result, false)) {
+      return result;
+
+    // If that failed, try to recover with a call.
+    } else {
+      tryToRecoverWithCall(result, PDiag(diag::err_ovl_unresolvable),
+                           /*complain*/ true);
+      return result;
+    }
+  }
+
+  // Bound member functions.
+  case BuiltinType::BoundMember: {
+    ExprResult result = Owned(E);
+    tryToRecoverWithCall(result, PDiag(diag::err_bound_member_function),
+                         /*complain*/ true);
+    return result;
+  }
+
+  // ARC unbridged casts.
+  case BuiltinType::ARCUnbridgedCast: {
+    Expr *realCast = stripARCUnbridgedCast(E);
+    diagnoseARCUnbridgedCast(realCast);
+    return Owned(realCast);
+  }
+
+  // Expressions of unknown type.
+  case BuiltinType::UnknownAny:
+    return diagnoseUnknownAnyExpr(*this, E);
+
+  // Pseudo-objects.
+  case BuiltinType::PseudoObject:
+    return checkPseudoObjectRValue(E);
+
+  // Everything else should be impossible.
+#define BUILTIN_TYPE(Id, SingletonId) \
+  case BuiltinType::Id:
+#define PLACEHOLDER_TYPE(Id, SingletonId)
+#include "clang/AST/BuiltinTypes.def"
+    break;
+  }
+
+  llvm_unreachable("invalid placeholder type!");
+}
+
+bool Sema::CheckCaseExpression(Expr *E) {
+  if (E->isTypeDependent())
+    return true;
+  if (E->isValueDependent() || E->isIntegerConstantExpr(Context))
+    return E->getType()->isIntegralOrEnumerationType();
+  return false;
+}
+
+/// ActOnObjCBoolLiteral - Parse {__objc_yes,__objc_no} literals.
+ExprResult
+Sema::ActOnObjCBoolLiteral(SourceLocation OpLoc, tok::TokenKind Kind) {
+  assert((Kind == tok::kw___objc_yes || Kind == tok::kw___objc_no) &&
+         "Unknown Objective-C Boolean value!");
+  return Owned(new (Context) ObjCBoolLiteralExpr(Kind == tok::kw___objc_yes,
+                                        Context.ObjCBuiltinBoolTy, OpLoc));
+}
diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp
new file mode 100644
index 0000000..af86cb2
--- /dev/null
+++ b/clang/lib/Sema/SemaExprCXX.cpp
@@ -0,0 +1,5362 @@
+//===--- SemaExprCXX.cpp - Semantic Analysis for Expressions --------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+//  This file implements semantic analysis for C++ expressions.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Sema/SemaInternal.h"
+#include "clang/Sema/DeclSpec.h"
+#include "clang/Sema/Initialization.h"
+#include "clang/Sema/Lookup.h"
+#include "clang/Sema/ParsedTemplate.h"
+#include "clang/Sema/ScopeInfo.h"
+#include "clang/Sema/Scope.h"
+#include "clang/Sema/TemplateDeduction.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/CharUnits.h"
+#include "clang/AST/CXXInheritance.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/AST/ExprCXX.h"
+#include "clang/AST/ExprObjC.h"
+#include "clang/AST/TypeLoc.h"
+#include "clang/Basic/PartialDiagnostic.h"
+#include "clang/Basic/TargetInfo.h"
+#include "clang/Lex/Preprocessor.h"
+#include "TypeLocBuilder.h"
+#include "llvm/ADT/APInt.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/Support/ErrorHandling.h"
+using namespace clang;
+using namespace sema;
+
+ParsedType Sema::getDestructorName(SourceLocation TildeLoc,
+                                   IdentifierInfo &II,
+                                   SourceLocation NameLoc,
+                                   Scope *S, CXXScopeSpec &SS,
+                                   ParsedType ObjectTypePtr,
+                                   bool EnteringContext) {
+  // Determine where to perform name lookup.
+
+  // FIXME: This area of the standard is very messy, and the current
+  // wording is rather unclear about which scopes we search for the
+  // destructor name; see core issues 399 and 555. Issue 399 in
+  // particular shows where the current description of destructor name
+  // lookup is completely out of line with existing practice, e.g.,
+  // this appears to be ill-formed:
+  //
+  //   namespace N {
+  //     template <typename T> struct S {
+  //       ~S();
+  //     };
+  //   }
+  //
+  //   void f(N::S<int>* s) {
+  //     s->N::S<int>::~S();
+  //   }
+  //
+  // See also PR6358 and PR6359.
+  // For this reason, we're currently only doing the C++03 version of this
+  // code; the C++0x version has to wait until we get a proper spec.
+  QualType SearchType;
+  DeclContext *LookupCtx = 0;
+  bool isDependent = false;
+  bool LookInScope = false;
+
+  // If we have an object type, it's because we are in a
+  // pseudo-destructor-expression or a member access expression, and
+  // we know what type we're looking for.
+  if (ObjectTypePtr)
+    SearchType = GetTypeFromParser(ObjectTypePtr);
+
+  if (SS.isSet()) {
+    NestedNameSpecifier *NNS = (NestedNameSpecifier *)SS.getScopeRep();
+
+    bool AlreadySearched = false;
+    bool LookAtPrefix = true;
+    // C++ [basic.lookup.qual]p6:
+    //   If a pseudo-destructor-name (5.2.4) contains a nested-name-specifier,
+    //   the type-names are looked up as types in the scope designated by the
+    //   nested-name-specifier. In a qualified-id of the form:
+    //
+    //     ::[opt] nested-name-specifier  ~ class-name
+    //
+    //   where the nested-name-specifier designates a namespace scope, and in
+    //   a qualified-id of the form:
+    //
+    //     ::opt nested-name-specifier class-name ::  ~ class-name
+    //
+    //   the class-names are looked up as types in the scope designated by
+    //   the nested-name-specifier.
+    //
+    // Here, we check the first case (completely) and determine whether the
+    // code below is permitted to look at the prefix of the
+    // nested-name-specifier.
+    DeclContext *DC = computeDeclContext(SS, EnteringContext);
+    if (DC && DC->isFileContext()) {
+      AlreadySearched = true;
+      LookupCtx = DC;
+      isDependent = false;
+    } else if (DC && isa<CXXRecordDecl>(DC))
+      LookAtPrefix = false;
+
+    // The second case from the C++03 rules quoted further above.
+    NestedNameSpecifier *Prefix = 0;
+    if (AlreadySearched) {
+      // Nothing left to do.
+    } else if (LookAtPrefix && (Prefix = NNS->getPrefix())) {
+      CXXScopeSpec PrefixSS;
+      PrefixSS.Adopt(NestedNameSpecifierLoc(Prefix, SS.location_data()));
+      LookupCtx = computeDeclContext(PrefixSS, EnteringContext);
+      isDependent = isDependentScopeSpecifier(PrefixSS);
+    } else if (ObjectTypePtr) {
+      LookupCtx = computeDeclContext(SearchType);
+      isDependent = SearchType->isDependentType();
+    } else {
+      LookupCtx = computeDeclContext(SS, EnteringContext);
+      isDependent = LookupCtx && LookupCtx->isDependentContext();
+    }
+
+    LookInScope = false;
+  } else if (ObjectTypePtr) {
+    // C++ [basic.lookup.classref]p3:
+    //   If the unqualified-id is ~type-name, the type-name is looked up
+    //   in the context of the entire postfix-expression. If the type T
+    //   of the object expression is of a class type C, the type-name is
+    //   also looked up in the scope of class C. At least one of the
+    //   lookups shall find a name that refers to (possibly
+    //   cv-qualified) T.
+    LookupCtx = computeDeclContext(SearchType);
+    isDependent = SearchType->isDependentType();
+    assert((isDependent || !SearchType->isIncompleteType()) &&
+           "Caller should have completed object type");
+
+    LookInScope = true;
+  } else {
+    // Perform lookup into the current scope (only).
+    LookInScope = true;
+  }
+
+  TypeDecl *NonMatchingTypeDecl = 0;
+  LookupResult Found(*this, &II, NameLoc, LookupOrdinaryName);
+  for (unsigned Step = 0; Step != 2; ++Step) {
+    // Look for the name first in the computed lookup context (if we
+    // have one) and, if that fails to find a match, in the scope (if
+    // we're allowed to look there).
+    Found.clear();
+    if (Step == 0 && LookupCtx)
+      LookupQualifiedName(Found, LookupCtx);
+    else if (Step == 1 && LookInScope && S)
+      LookupName(Found, S);
+    else
+      continue;
+
+    // FIXME: Should we be suppressing ambiguities here?
+    if (Found.isAmbiguous())
+      return ParsedType();
+
+    if (TypeDecl *Type = Found.getAsSingle<TypeDecl>()) {
+      QualType T = Context.getTypeDeclType(Type);
+
+      if (SearchType.isNull() || SearchType->isDependentType() ||
+          Context.hasSameUnqualifiedType(T, SearchType)) {
+        // We found our type!
+
+        return ParsedType::make(T);
+      }
+
+      if (!SearchType.isNull())
+        NonMatchingTypeDecl = Type;
+    }
+
+    // If the name that we found is a class template name, and it is
+    // the same name as the template name in the last part of the
+    // nested-name-specifier (if present) or the object type, then
+    // this is the destructor for that class.
+    // FIXME: This is a workaround until we get real drafting for core
+    // issue 399, for which there isn't even an obvious direction.
+    if (ClassTemplateDecl *Template = Found.getAsSingle<ClassTemplateDecl>()) {
+      QualType MemberOfType;
+      if (SS.isSet()) {
+        if (DeclContext *Ctx = computeDeclContext(SS, EnteringContext)) {
+          // Figure out the type of the context, if it has one.
+          if (CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(Ctx))
+            MemberOfType = Context.getTypeDeclType(Record);
+        }
+      }
+      if (MemberOfType.isNull())
+        MemberOfType = SearchType;
+
+      if (MemberOfType.isNull())
+        continue;
+
+      // We're referring into a class template specialization. If the
+      // class template we found is the same as the template being
+      // specialized, we found what we are looking for.
+      if (const RecordType *Record = MemberOfType->getAs<RecordType>()) {
+        if (ClassTemplateSpecializationDecl *Spec
+              = dyn_cast<ClassTemplateSpecializationDecl>(Record->getDecl())) {
+          if (Spec->getSpecializedTemplate()->getCanonicalDecl() ==
+                Template->getCanonicalDecl())
+            return ParsedType::make(MemberOfType);
+        }
+
+        continue;
+      }
+
+      // We're referring to an unresolved class template
+      // specialization. Determine whether we class template we found
+      // is the same as the template being specialized or, if we don't
+      // know which template is being specialized, that it at least
+      // has the same name.
+      if (const TemplateSpecializationType *SpecType
+            = MemberOfType->getAs<TemplateSpecializationType>()) {
+        TemplateName SpecName = SpecType->getTemplateName();
+
+        // The class template we found is the same template being
+        // specialized.
+        if (TemplateDecl *SpecTemplate = SpecName.getAsTemplateDecl()) {
+          if (SpecTemplate->getCanonicalDecl() == Template->getCanonicalDecl())
+            return ParsedType::make(MemberOfType);
+
+          continue;
+        }
+
+        // The class template we found has the same name as the
+        // (dependent) template name being specialized.
+        if (DependentTemplateName *DepTemplate
+                                    = SpecName.getAsDependentTemplateName()) {
+          if (DepTemplate->isIdentifier() &&
+              DepTemplate->getIdentifier() == Template->getIdentifier())
+            return ParsedType::make(MemberOfType);
+
+          continue;
+        }
+      }
+    }
+  }
+
+  if (isDependent) {
+    // We didn't find our type, but that's okay: it's dependent
+    // anyway.
+    
+    // FIXME: What if we have no nested-name-specifier?
+    QualType T = CheckTypenameType(ETK_None, SourceLocation(),
+                                   SS.getWithLocInContext(Context),
+                                   II, NameLoc);
+    return ParsedType::make(T);
+  }
+
+  if (NonMatchingTypeDecl) {
+    QualType T = Context.getTypeDeclType(NonMatchingTypeDecl);
+    Diag(NameLoc, diag::err_destructor_expr_type_mismatch)
+      << T << SearchType;
+    Diag(NonMatchingTypeDecl->getLocation(), diag::note_destructor_type_here)
+      << T;
+  } else if (ObjectTypePtr)
+    Diag(NameLoc, diag::err_ident_in_dtor_not_a_type)
+      << &II;
+  else
+    Diag(NameLoc, diag::err_destructor_class_name);
+
+  return ParsedType();
+}
+
+ParsedType Sema::getDestructorType(const DeclSpec& DS, ParsedType ObjectType) {
+    if (DS.getTypeSpecType() == DeclSpec::TST_error || !ObjectType)
+      return ParsedType();
+    assert(DS.getTypeSpecType() == DeclSpec::TST_decltype 
+           && "only get destructor types from declspecs");
+    QualType T = BuildDecltypeType(DS.getRepAsExpr(), DS.getTypeSpecTypeLoc());
+    QualType SearchType = GetTypeFromParser(ObjectType);
+    if (SearchType->isDependentType() || Context.hasSameUnqualifiedType(SearchType, T)) {
+      return ParsedType::make(T);
+    }
+      
+    Diag(DS.getTypeSpecTypeLoc(), diag::err_destructor_expr_type_mismatch)
+      << T << SearchType;
+    return ParsedType();
+}
+
+/// \brief Build a C++ typeid expression with a type operand.
+ExprResult Sema::BuildCXXTypeId(QualType TypeInfoType,
+                                SourceLocation TypeidLoc,
+                                TypeSourceInfo *Operand,
+                                SourceLocation RParenLoc) {
+  // C++ [expr.typeid]p4:
+  //   The top-level cv-qualifiers of the lvalue expression or the type-id
+  //   that is the operand of typeid are always ignored.
+  //   If the type of the type-id is a class type or a reference to a class
+  //   type, the class shall be completely-defined.
+  Qualifiers Quals;
+  QualType T
+    = Context.getUnqualifiedArrayType(Operand->getType().getNonReferenceType(),
+                                      Quals);
+  if (T->getAs<RecordType>() &&
+      RequireCompleteType(TypeidLoc, T, diag::err_incomplete_typeid))
+    return ExprError();
+
+  return Owned(new (Context) CXXTypeidExpr(TypeInfoType.withConst(),
+                                           Operand,
+                                           SourceRange(TypeidLoc, RParenLoc)));
+}
+
+/// \brief Build a C++ typeid expression with an expression operand.
+ExprResult Sema::BuildCXXTypeId(QualType TypeInfoType,
+                                SourceLocation TypeidLoc,
+                                Expr *E,
+                                SourceLocation RParenLoc) {
+  if (E && !E->isTypeDependent()) {
+    if (E->getType()->isPlaceholderType()) {
+      ExprResult result = CheckPlaceholderExpr(E);
+      if (result.isInvalid()) return ExprError();
+      E = result.take();
+    }
+
+    QualType T = E->getType();
+    if (const RecordType *RecordT = T->getAs<RecordType>()) {
+      CXXRecordDecl *RecordD = cast<CXXRecordDecl>(RecordT->getDecl());
+      // C++ [expr.typeid]p3:
+      //   [...] If the type of the expression is a class type, the class
+      //   shall be completely-defined.
+      if (RequireCompleteType(TypeidLoc, T, diag::err_incomplete_typeid))
+        return ExprError();
+
+      // C++ [expr.typeid]p3:
+      //   When typeid is applied to an expression other than an glvalue of a
+      //   polymorphic class type [...] [the] expression is an unevaluated
+      //   operand. [...]
+      if (RecordD->isPolymorphic() && E->Classify(Context).isGLValue()) {
+        // The subexpression is potentially evaluated; switch the context
+        // and recheck the subexpression.
+        ExprResult Result = TranformToPotentiallyEvaluated(E);
+        if (Result.isInvalid()) return ExprError();
+        E = Result.take();
+
+        // We require a vtable to query the type at run time.
+        MarkVTableUsed(TypeidLoc, RecordD);
+      }
+    }
+
+    // C++ [expr.typeid]p4:
+    //   [...] If the type of the type-id is a reference to a possibly
+    //   cv-qualified type, the result of the typeid expression refers to a
+    //   std::type_info object representing the cv-unqualified referenced
+    //   type.
+    Qualifiers Quals;
+    QualType UnqualT = Context.getUnqualifiedArrayType(T, Quals);
+    if (!Context.hasSameType(T, UnqualT)) {
+      T = UnqualT;
+      E = ImpCastExprToType(E, UnqualT, CK_NoOp, E->getValueKind()).take();
+    }
+  }
+
+  return Owned(new (Context) CXXTypeidExpr(TypeInfoType.withConst(),
+                                           E,
+                                           SourceRange(TypeidLoc, RParenLoc)));
+}
+
+/// ActOnCXXTypeidOfType - Parse typeid( type-id ) or typeid (expression);
+ExprResult
+Sema::ActOnCXXTypeid(SourceLocation OpLoc, SourceLocation LParenLoc,
+                     bool isType, void *TyOrExpr, SourceLocation RParenLoc) {
+  // Find the std::type_info type.
+  if (!getStdNamespace())
+    return ExprError(Diag(OpLoc, diag::err_need_header_before_typeid));
+
+  if (!CXXTypeInfoDecl) {
+    IdentifierInfo *TypeInfoII = &PP.getIdentifierTable().get("type_info");
+    LookupResult R(*this, TypeInfoII, SourceLocation(), LookupTagName);
+    LookupQualifiedName(R, getStdNamespace());
+    CXXTypeInfoDecl = R.getAsSingle<RecordDecl>();
+    if (!CXXTypeInfoDecl)
+      return ExprError(Diag(OpLoc, diag::err_need_header_before_typeid));
+  }
+
+  QualType TypeInfoType = Context.getTypeDeclType(CXXTypeInfoDecl);
+
+  if (isType) {
+    // The operand is a type; handle it as such.
+    TypeSourceInfo *TInfo = 0;
+    QualType T = GetTypeFromParser(ParsedType::getFromOpaquePtr(TyOrExpr),
+                                   &TInfo);
+    if (T.isNull())
+      return ExprError();
+
+    if (!TInfo)
+      TInfo = Context.getTrivialTypeSourceInfo(T, OpLoc);
+
+    return BuildCXXTypeId(TypeInfoType, OpLoc, TInfo, RParenLoc);
+  }
+
+  // The operand is an expression.
+  return BuildCXXTypeId(TypeInfoType, OpLoc, (Expr*)TyOrExpr, RParenLoc);
+}
+
+/// Retrieve the UuidAttr associated with QT.
+static UuidAttr *GetUuidAttrOfType(QualType QT) {
+  // Optionally remove one level of pointer, reference or array indirection.
+  const Type *Ty = QT.getTypePtr();;
+  if (QT->isPointerType() || QT->isReferenceType())
+    Ty = QT->getPointeeType().getTypePtr();
+  else if (QT->isArrayType())
+    Ty = cast<ArrayType>(QT)->getElementType().getTypePtr();
+
+  // Loop all record redeclaration looking for an uuid attribute.
+  CXXRecordDecl *RD = Ty->getAsCXXRecordDecl();
+  for (CXXRecordDecl::redecl_iterator I = RD->redecls_begin(),
+       E = RD->redecls_end(); I != E; ++I) {
+    if (UuidAttr *Uuid = I->getAttr<UuidAttr>())
+      return Uuid;
+  }
+
+  return 0;
+}
+
+/// \brief Build a Microsoft __uuidof expression with a type operand.
+ExprResult Sema::BuildCXXUuidof(QualType TypeInfoType,
+                                SourceLocation TypeidLoc,
+                                TypeSourceInfo *Operand,
+                                SourceLocation RParenLoc) {
+  if (!Operand->getType()->isDependentType()) {
+    if (!GetUuidAttrOfType(Operand->getType()))
+      return ExprError(Diag(TypeidLoc, diag::err_uuidof_without_guid));
+  }
+
+  // FIXME: add __uuidof semantic analysis for type operand.
+  return Owned(new (Context) CXXUuidofExpr(TypeInfoType.withConst(),
+                                           Operand,
+                                           SourceRange(TypeidLoc, RParenLoc)));
+}
+
+/// \brief Build a Microsoft __uuidof expression with an expression operand.
+ExprResult Sema::BuildCXXUuidof(QualType TypeInfoType,
+                                SourceLocation TypeidLoc,
+                                Expr *E,
+                                SourceLocation RParenLoc) {
+  if (!E->getType()->isDependentType()) {
+    if (!GetUuidAttrOfType(E->getType()) &&
+        !E->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull))
+      return ExprError(Diag(TypeidLoc, diag::err_uuidof_without_guid));
+  }
+  // FIXME: add __uuidof semantic analysis for type operand.
+  return Owned(new (Context) CXXUuidofExpr(TypeInfoType.withConst(),
+                                           E,
+                                           SourceRange(TypeidLoc, RParenLoc)));
+}
+
+/// ActOnCXXUuidof - Parse __uuidof( type-id ) or __uuidof (expression);
+ExprResult
+Sema::ActOnCXXUuidof(SourceLocation OpLoc, SourceLocation LParenLoc,
+                     bool isType, void *TyOrExpr, SourceLocation RParenLoc) {
+  // If MSVCGuidDecl has not been cached, do the lookup.
+  if (!MSVCGuidDecl) {
+    IdentifierInfo *GuidII = &PP.getIdentifierTable().get("_GUID");
+    LookupResult R(*this, GuidII, SourceLocation(), LookupTagName);
+    LookupQualifiedName(R, Context.getTranslationUnitDecl());
+    MSVCGuidDecl = R.getAsSingle<RecordDecl>();
+    if (!MSVCGuidDecl)
+      return ExprError(Diag(OpLoc, diag::err_need_header_before_ms_uuidof));
+  }
+
+  QualType GuidType = Context.getTypeDeclType(MSVCGuidDecl);
+
+  if (isType) {
+    // The operand is a type; handle it as such.
+    TypeSourceInfo *TInfo = 0;
+    QualType T = GetTypeFromParser(ParsedType::getFromOpaquePtr(TyOrExpr),
+                                   &TInfo);
+    if (T.isNull())
+      return ExprError();
+
+    if (!TInfo)
+      TInfo = Context.getTrivialTypeSourceInfo(T, OpLoc);
+
+    return BuildCXXUuidof(GuidType, OpLoc, TInfo, RParenLoc);
+  }
+
+  // The operand is an expression.
+  return BuildCXXUuidof(GuidType, OpLoc, (Expr*)TyOrExpr, RParenLoc);
+}
+
+/// ActOnCXXBoolLiteral - Parse {true,false} literals.
+ExprResult
+Sema::ActOnCXXBoolLiteral(SourceLocation OpLoc, tok::TokenKind Kind) {
+  assert((Kind == tok::kw_true || Kind == tok::kw_false) &&
+         "Unknown C++ Boolean value!");
+  return Owned(new (Context) CXXBoolLiteralExpr(Kind == tok::kw_true,
+                                                Context.BoolTy, OpLoc));
+}
+
+/// ActOnCXXNullPtrLiteral - Parse 'nullptr'.
+ExprResult
+Sema::ActOnCXXNullPtrLiteral(SourceLocation Loc) {
+  return Owned(new (Context) CXXNullPtrLiteralExpr(Context.NullPtrTy, Loc));
+}
+
+/// ActOnCXXThrow - Parse throw expressions.
+ExprResult
+Sema::ActOnCXXThrow(Scope *S, SourceLocation OpLoc, Expr *Ex) {
+  bool IsThrownVarInScope = false;
+  if (Ex) {
+    // C++0x [class.copymove]p31:
+    //   When certain criteria are met, an implementation is allowed to omit the 
+    //   copy/move construction of a class object [...]
+    //
+    //     - in a throw-expression, when the operand is the name of a 
+    //       non-volatile automatic object (other than a function or catch-
+    //       clause parameter) whose scope does not extend beyond the end of the 
+    //       innermost enclosing try-block (if there is one), the copy/move 
+    //       operation from the operand to the exception object (15.1) can be 
+    //       omitted by constructing the automatic object directly into the 
+    //       exception object
+    if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(Ex->IgnoreParens()))
+      if (VarDecl *Var = dyn_cast<VarDecl>(DRE->getDecl())) {
+        if (Var->hasLocalStorage() && !Var->getType().isVolatileQualified()) {
+          for( ; S; S = S->getParent()) {
+            if (S->isDeclScope(Var)) {
+              IsThrownVarInScope = true;
+              break;
+            }
+            
+            if (S->getFlags() &
+                (Scope::FnScope | Scope::ClassScope | Scope::BlockScope |
+                 Scope::FunctionPrototypeScope | Scope::ObjCMethodScope |
+                 Scope::TryScope))
+              break;
+          }
+        }
+      }
+  }
+  
+  return BuildCXXThrow(OpLoc, Ex, IsThrownVarInScope);
+}
+
+ExprResult Sema::BuildCXXThrow(SourceLocation OpLoc, Expr *Ex, 
+                               bool IsThrownVarInScope) {
+  // Don't report an error if 'throw' is used in system headers.
+  if (!getLangOpts().CXXExceptions &&
+      !getSourceManager().isInSystemHeader(OpLoc))
+    Diag(OpLoc, diag::err_exceptions_disabled) << "throw";
+  
+  if (Ex && !Ex->isTypeDependent()) {
+    ExprResult ExRes = CheckCXXThrowOperand(OpLoc, Ex, IsThrownVarInScope);
+    if (ExRes.isInvalid())
+      return ExprError();
+    Ex = ExRes.take();
+  }
+  
+  return Owned(new (Context) CXXThrowExpr(Ex, Context.VoidTy, OpLoc,
+                                          IsThrownVarInScope));
+}
+
+/// CheckCXXThrowOperand - Validate the operand of a throw.
+ExprResult Sema::CheckCXXThrowOperand(SourceLocation ThrowLoc, Expr *E,
+                                      bool IsThrownVarInScope) {
+  // C++ [except.throw]p3:
+  //   A throw-expression initializes a temporary object, called the exception
+  //   object, the type of which is determined by removing any top-level
+  //   cv-qualifiers from the static type of the operand of throw and adjusting
+  //   the type from "array of T" or "function returning T" to "pointer to T"
+  //   or "pointer to function returning T", [...]
+  if (E->getType().hasQualifiers())
+    E = ImpCastExprToType(E, E->getType().getUnqualifiedType(), CK_NoOp,
+                          E->getValueKind()).take();
+
+  ExprResult Res = DefaultFunctionArrayConversion(E);
+  if (Res.isInvalid())
+    return ExprError();
+  E = Res.take();
+
+  //   If the type of the exception would be an incomplete type or a pointer
+  //   to an incomplete type other than (cv) void the program is ill-formed.
+  QualType Ty = E->getType();
+  bool isPointer = false;
+  if (const PointerType* Ptr = Ty->getAs<PointerType>()) {
+    Ty = Ptr->getPointeeType();
+    isPointer = true;
+  }
+  if (!isPointer || !Ty->isVoidType()) {
+    if (RequireCompleteType(ThrowLoc, Ty,
+                            PDiag(isPointer ? diag::err_throw_incomplete_ptr
+                                            : diag::err_throw_incomplete)
+                              << E->getSourceRange()))
+      return ExprError();
+
+    if (RequireNonAbstractType(ThrowLoc, E->getType(),
+                               PDiag(diag::err_throw_abstract_type)
+                                 << E->getSourceRange()))
+      return ExprError();
+  }
+
+  // Initialize the exception result.  This implicitly weeds out
+  // abstract types or types with inaccessible copy constructors.
+  
+  // C++0x [class.copymove]p31:
+  //   When certain criteria are met, an implementation is allowed to omit the 
+  //   copy/move construction of a class object [...]
+  //
+  //     - in a throw-expression, when the operand is the name of a 
+  //       non-volatile automatic object (other than a function or catch-clause 
+  //       parameter) whose scope does not extend beyond the end of the 
+  //       innermost enclosing try-block (if there is one), the copy/move 
+  //       operation from the operand to the exception object (15.1) can be 
+  //       omitted by constructing the automatic object directly into the 
+  //       exception object
+  const VarDecl *NRVOVariable = 0;
+  if (IsThrownVarInScope)
+    NRVOVariable = getCopyElisionCandidate(QualType(), E, false);
+  
+  InitializedEntity Entity =
+      InitializedEntity::InitializeException(ThrowLoc, E->getType(),
+                                             /*NRVO=*/NRVOVariable != 0);
+  Res = PerformMoveOrCopyInitialization(Entity, NRVOVariable,
+                                        QualType(), E,
+                                        IsThrownVarInScope);
+  if (Res.isInvalid())
+    return ExprError();
+  E = Res.take();
+
+  // If the exception has class type, we need additional handling.
+  const RecordType *RecordTy = Ty->getAs<RecordType>();
+  if (!RecordTy)
+    return Owned(E);
+  CXXRecordDecl *RD = cast<CXXRecordDecl>(RecordTy->getDecl());
+
+  // If we are throwing a polymorphic class type or pointer thereof,
+  // exception handling will make use of the vtable.
+  MarkVTableUsed(ThrowLoc, RD);
+
+  // If a pointer is thrown, the referenced object will not be destroyed.
+  if (isPointer)
+    return Owned(E);
+
+  // If the class has a destructor, we must be able to call it.
+  if (RD->hasIrrelevantDestructor())
+    return Owned(E);
+
+  CXXDestructorDecl *Destructor = LookupDestructor(RD);
+  if (!Destructor)
+    return Owned(E);
+
+  MarkFunctionReferenced(E->getExprLoc(), Destructor);
+  CheckDestructorAccess(E->getExprLoc(), Destructor,
+                        PDiag(diag::err_access_dtor_exception) << Ty);
+  DiagnoseUseOfDecl(Destructor, E->getExprLoc());
+  return Owned(E);
+}
+
+QualType Sema::getCurrentThisType() {
+  DeclContext *DC = getFunctionLevelDeclContext();
+  QualType ThisTy = CXXThisTypeOverride;
+  if (CXXMethodDecl *method = dyn_cast<CXXMethodDecl>(DC)) {
+    if (method && method->isInstance())
+      ThisTy = method->getThisType(Context);
+  }
+  
+  return ThisTy;
+}
+
+Sema::CXXThisScopeRAII::CXXThisScopeRAII(Sema &S, 
+                                         Decl *ContextDecl,
+                                         unsigned CXXThisTypeQuals,
+                                         bool Enabled) 
+  : S(S), OldCXXThisTypeOverride(S.CXXThisTypeOverride), Enabled(false)
+{
+  if (!Enabled || !ContextDecl)
+    return;
+  
+  CXXRecordDecl *Record = 0;
+  if (ClassTemplateDecl *Template = dyn_cast<ClassTemplateDecl>(ContextDecl))
+    Record = Template->getTemplatedDecl();
+  else
+    Record = cast<CXXRecordDecl>(ContextDecl);
+    
+  S.CXXThisTypeOverride
+    = S.Context.getPointerType(
+        S.Context.getRecordType(Record).withCVRQualifiers(CXXThisTypeQuals));
+  
+  this->Enabled = true;
+}
+
+
+Sema::CXXThisScopeRAII::~CXXThisScopeRAII() {
+  if (Enabled) {
+    S.CXXThisTypeOverride = OldCXXThisTypeOverride;
+  }
+}
+
+void Sema::CheckCXXThisCapture(SourceLocation Loc, bool Explicit) {
+  // We don't need to capture this in an unevaluated context.
+  if (ExprEvalContexts.back().Context == Unevaluated && !Explicit)
+    return;
+
+  // Otherwise, check that we can capture 'this'.
+  unsigned NumClosures = 0;
+  for (unsigned idx = FunctionScopes.size() - 1; idx != 0; idx--) {
+    if (CapturingScopeInfo *CSI =
+            dyn_cast<CapturingScopeInfo>(FunctionScopes[idx])) {
+      if (CSI->CXXThisCaptureIndex != 0) {
+        // 'this' is already being captured; there isn't anything more to do.
+        break;
+      }
+      
+      if (CSI->ImpCaptureStyle == CapturingScopeInfo::ImpCap_LambdaByref ||
+          CSI->ImpCaptureStyle == CapturingScopeInfo::ImpCap_LambdaByval ||
+          CSI->ImpCaptureStyle == CapturingScopeInfo::ImpCap_Block ||
+          Explicit) {
+        // This closure can capture 'this'; continue looking upwards.
+        NumClosures++;
+        Explicit = false;
+        continue;
+      }
+      // This context can't implicitly capture 'this'; fail out.
+      Diag(Loc, diag::err_this_capture) << Explicit;
+      return;
+    }
+    break;
+  }
+
+  // Mark that we're implicitly capturing 'this' in all the scopes we skipped.
+  // FIXME: We need to delay this marking in PotentiallyPotentiallyEvaluated
+  // contexts.
+  for (unsigned idx = FunctionScopes.size() - 1;
+       NumClosures; --idx, --NumClosures) {
+    CapturingScopeInfo *CSI = cast<CapturingScopeInfo>(FunctionScopes[idx]);
+    Expr *ThisExpr = 0;
+    QualType ThisTy = getCurrentThisType();
+    if (LambdaScopeInfo *LSI = dyn_cast<LambdaScopeInfo>(CSI)) {
+      // For lambda expressions, build a field and an initializing expression.
+      CXXRecordDecl *Lambda = LSI->Lambda;
+      FieldDecl *Field
+        = FieldDecl::Create(Context, Lambda, Loc, Loc, 0, ThisTy,
+                            Context.getTrivialTypeSourceInfo(ThisTy, Loc),
+                            0, false, false);
+      Field->setImplicit(true);
+      Field->setAccess(AS_private);
+      Lambda->addDecl(Field);
+      ThisExpr = new (Context) CXXThisExpr(Loc, ThisTy, /*isImplicit=*/true);
+    }
+    bool isNested = NumClosures > 1;
+    CSI->addThisCapture(isNested, Loc, ThisTy, ThisExpr);
+  }
+}
+
+ExprResult Sema::ActOnCXXThis(SourceLocation Loc) {
+  /// C++ 9.3.2: In the body of a non-static member function, the keyword this
+  /// is a non-lvalue expression whose value is the address of the object for
+  /// which the function is called.
+
+  QualType ThisTy = getCurrentThisType();
+  if (ThisTy.isNull()) return Diag(Loc, diag::err_invalid_this_use);
+
+  CheckCXXThisCapture(Loc);
+  return Owned(new (Context) CXXThisExpr(Loc, ThisTy, /*isImplicit=*/false));
+}
+
+bool Sema::isThisOutsideMemberFunctionBody(QualType BaseType) {
+  // If we're outside the body of a member function, then we'll have a specified
+  // type for 'this'.
+  if (CXXThisTypeOverride.isNull())
+    return false;
+  
+  // Determine whether we're looking into a class that's currently being
+  // defined.
+  CXXRecordDecl *Class = BaseType->getAsCXXRecordDecl();
+  return Class && Class->isBeingDefined();
+}
+
+ExprResult
+Sema::ActOnCXXTypeConstructExpr(ParsedType TypeRep,
+                                SourceLocation LParenLoc,
+                                MultiExprArg exprs,
+                                SourceLocation RParenLoc) {
+  if (!TypeRep)
+    return ExprError();
+
+  TypeSourceInfo *TInfo;
+  QualType Ty = GetTypeFromParser(TypeRep, &TInfo);
+  if (!TInfo)
+    TInfo = Context.getTrivialTypeSourceInfo(Ty, SourceLocation());
+
+  return BuildCXXTypeConstructExpr(TInfo, LParenLoc, exprs, RParenLoc);
+}
+
+/// ActOnCXXTypeConstructExpr - Parse construction of a specified type.
+/// Can be interpreted either as function-style casting ("int(x)")
+/// or class type construction ("ClassType(x,y,z)")
+/// or creation of a value-initialized type ("int()").
+ExprResult
+Sema::BuildCXXTypeConstructExpr(TypeSourceInfo *TInfo,
+                                SourceLocation LParenLoc,
+                                MultiExprArg exprs,
+                                SourceLocation RParenLoc) {
+  QualType Ty = TInfo->getType();
+  unsigned NumExprs = exprs.size();
+  Expr **Exprs = (Expr**)exprs.get();
+  SourceLocation TyBeginLoc = TInfo->getTypeLoc().getBeginLoc();
+
+  if (Ty->isDependentType() ||
+      CallExpr::hasAnyTypeDependentArguments(
+        llvm::makeArrayRef(Exprs, NumExprs))) {
+    exprs.release();
+
+    return Owned(CXXUnresolvedConstructExpr::Create(Context, TInfo,
+                                                    LParenLoc,
+                                                    Exprs, NumExprs,
+                                                    RParenLoc));
+  }
+
+  bool ListInitialization = LParenLoc.isInvalid();
+  assert((!ListInitialization || (NumExprs == 1 && isa<InitListExpr>(Exprs[0])))
+         && "List initialization must have initializer list as expression.");
+  SourceRange FullRange = SourceRange(TyBeginLoc,
+      ListInitialization ? Exprs[0]->getSourceRange().getEnd() : RParenLoc);
+
+  // C++ [expr.type.conv]p1:
+  // If the expression list is a single expression, the type conversion
+  // expression is equivalent (in definedness, and if defined in meaning) to the
+  // corresponding cast expression.
+  if (NumExprs == 1 && !ListInitialization) {
+    Expr *Arg = Exprs[0];
+    exprs.release();
+    return BuildCXXFunctionalCastExpr(TInfo, LParenLoc, Arg, RParenLoc);
+  }
+
+  QualType ElemTy = Ty;
+  if (Ty->isArrayType()) {
+    if (!ListInitialization)
+      return ExprError(Diag(TyBeginLoc,
+                            diag::err_value_init_for_array_type) << FullRange);
+    ElemTy = Context.getBaseElementType(Ty);
+  }
+
+  if (!Ty->isVoidType() &&
+      RequireCompleteType(TyBeginLoc, ElemTy,
+                          PDiag(diag::err_invalid_incomplete_type_use)
+                            << FullRange))
+    return ExprError();
+
+  if (RequireNonAbstractType(TyBeginLoc, Ty,
+                             diag::err_allocation_of_abstract_type))
+    return ExprError();
+
+  InitializedEntity Entity = InitializedEntity::InitializeTemporary(TInfo);
+  InitializationKind Kind
+    = NumExprs ? ListInitialization
+                    ? InitializationKind::CreateDirectList(TyBeginLoc)
+                    : InitializationKind::CreateDirect(TyBeginLoc,
+                                                       LParenLoc, RParenLoc)
+               : InitializationKind::CreateValue(TyBeginLoc,
+                                                 LParenLoc, RParenLoc);
+  InitializationSequence InitSeq(*this, Entity, Kind, Exprs, NumExprs);
+  ExprResult Result = InitSeq.Perform(*this, Entity, Kind, move(exprs));
+
+  if (!Result.isInvalid() && ListInitialization &&
+      isa<InitListExpr>(Result.get())) {
+    // If the list-initialization doesn't involve a constructor call, we'll get
+    // the initializer-list (with corrected type) back, but that's not what we
+    // want, since it will be treated as an initializer list in further
+    // processing. Explicitly insert a cast here.
+    InitListExpr *List = cast<InitListExpr>(Result.take());
+    Result = Owned(CXXFunctionalCastExpr::Create(Context, List->getType(),
+                                    Expr::getValueKindForType(TInfo->getType()),
+                                                 TInfo, TyBeginLoc, CK_NoOp,
+                                                 List, /*Path=*/0, RParenLoc));
+  }
+
+  // FIXME: Improve AST representation?
+  return move(Result);
+}
+
+/// doesUsualArrayDeleteWantSize - Answers whether the usual
+/// operator delete[] for the given type has a size_t parameter.
+static bool doesUsualArrayDeleteWantSize(Sema &S, SourceLocation loc,
+                                         QualType allocType) {
+  const RecordType *record =
+    allocType->getBaseElementTypeUnsafe()->getAs<RecordType>();
+  if (!record) return false;
+
+  // Try to find an operator delete[] in class scope.
+
+  DeclarationName deleteName =
+    S.Context.DeclarationNames.getCXXOperatorName(OO_Array_Delete);
+  LookupResult ops(S, deleteName, loc, Sema::LookupOrdinaryName);
+  S.LookupQualifiedName(ops, record->getDecl());
+
+  // We're just doing this for information.
+  ops.suppressDiagnostics();
+
+  // Very likely: there's no operator delete[].
+  if (ops.empty()) return false;
+
+  // If it's ambiguous, it should be illegal to call operator delete[]
+  // on this thing, so it doesn't matter if we allocate extra space or not.
+  if (ops.isAmbiguous()) return false;
+
+  LookupResult::Filter filter = ops.makeFilter();
+  while (filter.hasNext()) {
+    NamedDecl *del = filter.next()->getUnderlyingDecl();
+
+    // C++0x [basic.stc.dynamic.deallocation]p2:
+    //   A template instance is never a usual deallocation function,
+    //   regardless of its signature.
+    if (isa<FunctionTemplateDecl>(del)) {
+      filter.erase();
+      continue;
+    }
+
+    // C++0x [basic.stc.dynamic.deallocation]p2:
+    //   If class T does not declare [an operator delete[] with one
+    //   parameter] but does declare a member deallocation function
+    //   named operator delete[] with exactly two parameters, the
+    //   second of which has type std::size_t, then this function
+    //   is a usual deallocation function.
+    if (!cast<CXXMethodDecl>(del)->isUsualDeallocationFunction()) {
+      filter.erase();
+      continue;
+    }
+  }
+  filter.done();
+
+  if (!ops.isSingleResult()) return false;
+
+  const FunctionDecl *del = cast<FunctionDecl>(ops.getFoundDecl());
+  return (del->getNumParams() == 2);
+}
+
+/// \brief Parsed a C++ 'new' expression (C++ 5.3.4).
+
+/// E.g.:
+/// @code new (memory) int[size][4] @endcode
+/// or
+/// @code ::new Foo(23, "hello") @endcode
+///
+/// \param StartLoc The first location of the expression.
+/// \param UseGlobal True if 'new' was prefixed with '::'.
+/// \param PlacementLParen Opening paren of the placement arguments.
+/// \param PlacementArgs Placement new arguments.
+/// \param PlacementRParen Closing paren of the placement arguments.
+/// \param TypeIdParens If the type is in parens, the source range.
+/// \param D The type to be allocated, as well as array dimensions.
+/// \param ConstructorLParen Opening paren of the constructor args, empty if
+///                          initializer-list syntax is used.
+/// \param ConstructorArgs Constructor/initialization arguments.
+/// \param ConstructorRParen Closing paren of the constructor args.
+ExprResult
+Sema::ActOnCXXNew(SourceLocation StartLoc, bool UseGlobal,
+                  SourceLocation PlacementLParen, MultiExprArg PlacementArgs,
+                  SourceLocation PlacementRParen, SourceRange TypeIdParens,
+                  Declarator &D, Expr *Initializer) {
+  bool TypeContainsAuto = D.getDeclSpec().getTypeSpecType() == DeclSpec::TST_auto;
+
+  Expr *ArraySize = 0;
+  // If the specified type is an array, unwrap it and save the expression.
+  if (D.getNumTypeObjects() > 0 &&
+      D.getTypeObject(0).Kind == DeclaratorChunk::Array) {
+    DeclaratorChunk &Chunk = D.getTypeObject(0);
+    if (TypeContainsAuto)
+      return ExprError(Diag(Chunk.Loc, diag::err_new_array_of_auto)
+        << D.getSourceRange());
+    if (Chunk.Arr.hasStatic)
+      return ExprError(Diag(Chunk.Loc, diag::err_static_illegal_in_new)
+        << D.getSourceRange());
+    if (!Chunk.Arr.NumElts)
+      return ExprError(Diag(Chunk.Loc, diag::err_array_new_needs_size)
+        << D.getSourceRange());
+
+    ArraySize = static_cast<Expr*>(Chunk.Arr.NumElts);
+    D.DropFirstTypeObject();
+  }
+
+  // Every dimension shall be of constant size.
+  if (ArraySize) {
+    for (unsigned I = 0, N = D.getNumTypeObjects(); I < N; ++I) {
+      if (D.getTypeObject(I).Kind != DeclaratorChunk::Array)
+        break;
+
+      DeclaratorChunk::ArrayTypeInfo &Array = D.getTypeObject(I).Arr;
+      if (Expr *NumElts = (Expr *)Array.NumElts) {
+        if (!NumElts->isTypeDependent() && !NumElts->isValueDependent()) {
+          Array.NumElts = VerifyIntegerConstantExpression(NumElts, 0,
+            PDiag(diag::err_new_array_nonconst)).take();
+          if (!Array.NumElts)
+            return ExprError();
+        }
+      }
+    }
+  }
+
+  TypeSourceInfo *TInfo = GetTypeForDeclarator(D, /*Scope=*/0);
+  QualType AllocType = TInfo->getType();
+  if (D.isInvalidType())
+    return ExprError();
+
+  SourceRange DirectInitRange;
+  if (ParenListExpr *List = dyn_cast_or_null<ParenListExpr>(Initializer))
+    DirectInitRange = List->getSourceRange();
+
+  return BuildCXXNew(StartLoc, UseGlobal,
+                     PlacementLParen,
+                     move(PlacementArgs),
+                     PlacementRParen,
+                     TypeIdParens,
+                     AllocType,
+                     TInfo,
+                     ArraySize,
+                     DirectInitRange,
+                     Initializer,
+                     TypeContainsAuto);
+}
+
+static bool isLegalArrayNewInitializer(CXXNewExpr::InitializationStyle Style,
+                                       Expr *Init) {
+  if (!Init)
+    return true;
+  if (ParenListExpr *PLE = dyn_cast<ParenListExpr>(Init))
+    return PLE->getNumExprs() == 0;
+  if (isa<ImplicitValueInitExpr>(Init))
+    return true;
+  else if (CXXConstructExpr *CCE = dyn_cast<CXXConstructExpr>(Init))
+    return !CCE->isListInitialization() &&
+           CCE->getConstructor()->isDefaultConstructor();
+  else if (Style == CXXNewExpr::ListInit) {
+    assert(isa<InitListExpr>(Init) &&
+           "Shouldn't create list CXXConstructExprs for arrays.");
+    return true;
+  }
+  return false;
+}
+
+ExprResult
+Sema::BuildCXXNew(SourceLocation StartLoc, bool UseGlobal,
+                  SourceLocation PlacementLParen,
+                  MultiExprArg PlacementArgs,
+                  SourceLocation PlacementRParen,
+                  SourceRange TypeIdParens,
+                  QualType AllocType,
+                  TypeSourceInfo *AllocTypeInfo,
+                  Expr *ArraySize,
+                  SourceRange DirectInitRange,
+                  Expr *Initializer,
+                  bool TypeMayContainAuto) {
+  SourceRange TypeRange = AllocTypeInfo->getTypeLoc().getSourceRange();
+
+  CXXNewExpr::InitializationStyle initStyle;
+  if (DirectInitRange.isValid()) {
+    assert(Initializer && "Have parens but no initializer.");
+    initStyle = CXXNewExpr::CallInit;
+  } else if (Initializer && isa<InitListExpr>(Initializer))
+    initStyle = CXXNewExpr::ListInit;
+  else {
+    // In template instantiation, the initializer could be a CXXDefaultArgExpr
+    // unwrapped from a CXXConstructExpr that was implicitly built. There is no
+    // particularly sane way we can handle this (especially since it can even
+    // occur for array new), so we throw the initializer away and have it be
+    // rebuilt.
+    if (Initializer && isa<CXXDefaultArgExpr>(Initializer))
+      Initializer = 0;
+    assert((!Initializer || isa<ImplicitValueInitExpr>(Initializer) ||
+            isa<CXXConstructExpr>(Initializer)) &&
+           "Initializer expression that cannot have been implicitly created.");
+    initStyle = CXXNewExpr::NoInit;
+  }
+
+  Expr **Inits = &Initializer;
+  unsigned NumInits = Initializer ? 1 : 0;
+  if (initStyle == CXXNewExpr::CallInit) {
+    if (ParenListExpr *List = dyn_cast<ParenListExpr>(Initializer)) {
+      Inits = List->getExprs();
+      NumInits = List->getNumExprs();
+    } else if (CXXConstructExpr *CCE = dyn_cast<CXXConstructExpr>(Initializer)){
+      if (!isa<CXXTemporaryObjectExpr>(CCE)) {
+        // Can happen in template instantiation. Since this is just an implicit
+        // construction, we just take it apart and rebuild it.
+        Inits = CCE->getArgs();
+        NumInits = CCE->getNumArgs();
+      }
+    }
+  }
+
+  // C++0x [decl.spec.auto]p6. Deduce the type which 'auto' stands in for.
+  if (TypeMayContainAuto && AllocType->getContainedAutoType()) {
+    if (initStyle == CXXNewExpr::NoInit || NumInits == 0)
+      return ExprError(Diag(StartLoc, diag::err_auto_new_requires_ctor_arg)
+                       << AllocType << TypeRange);
+    if (initStyle == CXXNewExpr::ListInit)
+      return ExprError(Diag(Inits[0]->getLocStart(),
+                            diag::err_auto_new_requires_parens)
+                       << AllocType << TypeRange);
+    if (NumInits > 1) {
+      Expr *FirstBad = Inits[1];
+      return ExprError(Diag(FirstBad->getLocStart(),
+                            diag::err_auto_new_ctor_multiple_expressions)
+                       << AllocType << TypeRange);
+    }
+    Expr *Deduce = Inits[0];
+    TypeSourceInfo *DeducedType = 0;
+    if (DeduceAutoType(AllocTypeInfo, Deduce, DeducedType) ==
+            DAR_Failed)
+      return ExprError(Diag(StartLoc, diag::err_auto_new_deduction_failure)
+                       << AllocType << Deduce->getType()
+                       << TypeRange << Deduce->getSourceRange());
+    if (!DeducedType)
+      return ExprError();
+
+    AllocTypeInfo = DeducedType;
+    AllocType = AllocTypeInfo->getType();
+  }
+
+  // Per C++0x [expr.new]p5, the type being constructed may be a
+  // typedef of an array type.
+  if (!ArraySize) {
+    if (const ConstantArrayType *Array
+                              = Context.getAsConstantArrayType(AllocType)) {
+      ArraySize = IntegerLiteral::Create(Context, Array->getSize(),
+                                         Context.getSizeType(),
+                                         TypeRange.getEnd());
+      AllocType = Array->getElementType();
+    }
+  }
+
+  if (CheckAllocatedType(AllocType, TypeRange.getBegin(), TypeRange))
+    return ExprError();
+
+  if (initStyle == CXXNewExpr::ListInit && isStdInitializerList(AllocType, 0)) {
+    Diag(AllocTypeInfo->getTypeLoc().getBeginLoc(),
+         diag::warn_dangling_std_initializer_list)
+        << /*at end of FE*/0 << Inits[0]->getSourceRange();
+  }
+
+  // In ARC, infer 'retaining' for the allocated 
+  if (getLangOpts().ObjCAutoRefCount &&
+      AllocType.getObjCLifetime() == Qualifiers::OCL_None &&
+      AllocType->isObjCLifetimeType()) {
+    AllocType = Context.getLifetimeQualifiedType(AllocType,
+                                    AllocType->getObjCARCImplicitLifetime());
+  }
+
+  QualType ResultType = Context.getPointerType(AllocType);
+    
+  // C++98 5.3.4p6: "The expression in a direct-new-declarator shall have
+  //   integral or enumeration type with a non-negative value."
+  // C++11 [expr.new]p6: The expression [...] shall be of integral or unscoped
+  //   enumeration type, or a class type for which a single non-explicit
+  //   conversion function to integral or unscoped enumeration type exists.
+  if (ArraySize && !ArraySize->isTypeDependent()) {
+    ExprResult ConvertedSize = ConvertToIntegralOrEnumerationType(
+      StartLoc, ArraySize,
+      PDiag(diag::err_array_size_not_integral) << getLangOpts().CPlusPlus0x,
+      PDiag(diag::err_array_size_incomplete_type)
+        << ArraySize->getSourceRange(),
+      PDiag(diag::err_array_size_explicit_conversion),
+      PDiag(diag::note_array_size_conversion),
+      PDiag(diag::err_array_size_ambiguous_conversion),
+      PDiag(diag::note_array_size_conversion),
+      PDiag(getLangOpts().CPlusPlus0x ?
+              diag::warn_cxx98_compat_array_size_conversion :
+              diag::ext_array_size_conversion),
+      /*AllowScopedEnumerations*/ false);
+    if (ConvertedSize.isInvalid())
+      return ExprError();
+
+    ArraySize = ConvertedSize.take();
+    QualType SizeType = ArraySize->getType();
+    if (!SizeType->isIntegralOrUnscopedEnumerationType())
+      return ExprError();
+
+    // C++98 [expr.new]p7:
+    //   The expression in a direct-new-declarator shall have integral type
+    //   with a non-negative value.
+    //
+    // Let's see if this is a constant < 0. If so, we reject it out of
+    // hand. Otherwise, if it's not a constant, we must have an unparenthesized
+    // array type.
+    //
+    // Note: such a construct has well-defined semantics in C++11: it throws
+    // std::bad_array_new_length.
+    if (!ArraySize->isValueDependent()) {
+      llvm::APSInt Value;
+      // We've already performed any required implicit conversion to integer or
+      // unscoped enumeration type.
+      if (ArraySize->isIntegerConstantExpr(Value, Context)) {
+        if (Value < llvm::APSInt(
+                        llvm::APInt::getNullValue(Value.getBitWidth()),
+                                 Value.isUnsigned())) {
+          if (getLangOpts().CPlusPlus0x)
+            Diag(ArraySize->getLocStart(),
+                 diag::warn_typecheck_negative_array_new_size)
+              << ArraySize->getSourceRange();
+          else
+            return ExprError(Diag(ArraySize->getLocStart(),
+                                  diag::err_typecheck_negative_array_size)
+                             << ArraySize->getSourceRange());
+        } else if (!AllocType->isDependentType()) {
+          unsigned ActiveSizeBits =
+            ConstantArrayType::getNumAddressingBits(Context, AllocType, Value);
+          if (ActiveSizeBits > ConstantArrayType::getMaxSizeBits(Context)) {
+            if (getLangOpts().CPlusPlus0x)
+              Diag(ArraySize->getLocStart(),
+                   diag::warn_array_new_too_large)
+                << Value.toString(10)
+                << ArraySize->getSourceRange();
+            else
+              return ExprError(Diag(ArraySize->getLocStart(),
+                                    diag::err_array_too_large)
+                               << Value.toString(10)
+                               << ArraySize->getSourceRange());
+          }
+        }
+      } else if (TypeIdParens.isValid()) {
+        // Can't have dynamic array size when the type-id is in parentheses.
+        Diag(ArraySize->getLocStart(), diag::ext_new_paren_array_nonconst)
+          << ArraySize->getSourceRange()
+          << FixItHint::CreateRemoval(TypeIdParens.getBegin())
+          << FixItHint::CreateRemoval(TypeIdParens.getEnd());
+
+        TypeIdParens = SourceRange();
+      }
+    }
+
+    // ARC: warn about ABI issues.
+    if (getLangOpts().ObjCAutoRefCount) {
+      QualType BaseAllocType = Context.getBaseElementType(AllocType);
+      if (BaseAllocType.hasStrongOrWeakObjCLifetime())
+        Diag(StartLoc, diag::warn_err_new_delete_object_array)
+          << 0 << BaseAllocType;
+    }
+
+    // Note that we do *not* convert the argument in any way.  It can
+    // be signed, larger than size_t, whatever.
+  }
+
+  FunctionDecl *OperatorNew = 0;
+  FunctionDecl *OperatorDelete = 0;
+  Expr **PlaceArgs = (Expr**)PlacementArgs.get();
+  unsigned NumPlaceArgs = PlacementArgs.size();
+
+  if (!AllocType->isDependentType() &&
+      !Expr::hasAnyTypeDependentArguments(
+        llvm::makeArrayRef(PlaceArgs, NumPlaceArgs)) &&
+      FindAllocationFunctions(StartLoc,
+                              SourceRange(PlacementLParen, PlacementRParen),
+                              UseGlobal, AllocType, ArraySize, PlaceArgs,
+                              NumPlaceArgs, OperatorNew, OperatorDelete))
+    return ExprError();
+
+  // If this is an array allocation, compute whether the usual array
+  // deallocation function for the type has a size_t parameter.
+  bool UsualArrayDeleteWantsSize = false;
+  if (ArraySize && !AllocType->isDependentType())
+    UsualArrayDeleteWantsSize
+      = doesUsualArrayDeleteWantSize(*this, StartLoc, AllocType);
+
+  SmallVector<Expr *, 8> AllPlaceArgs;
+  if (OperatorNew) {
+    // Add default arguments, if any.
+    const FunctionProtoType *Proto =
+      OperatorNew->getType()->getAs<FunctionProtoType>();
+    VariadicCallType CallType =
+      Proto->isVariadic() ? VariadicFunction : VariadicDoesNotApply;
+
+    if (GatherArgumentsForCall(PlacementLParen, OperatorNew,
+                               Proto, 1, PlaceArgs, NumPlaceArgs,
+                               AllPlaceArgs, CallType))
+      return ExprError();
+
+    NumPlaceArgs = AllPlaceArgs.size();
+    if (NumPlaceArgs > 0)
+      PlaceArgs = &AllPlaceArgs[0];
+
+    DiagnoseSentinelCalls(OperatorNew, PlacementLParen,
+                          PlaceArgs, NumPlaceArgs);
+
+    // FIXME: Missing call to CheckFunctionCall or equivalent
+  }
+
+  // Warn if the type is over-aligned and is being allocated by global operator
+  // new.
+  if (NumPlaceArgs == 0 && OperatorNew && 
+      (OperatorNew->isImplicit() ||
+       getSourceManager().isInSystemHeader(OperatorNew->getLocStart()))) {
+    if (unsigned Align = Context.getPreferredTypeAlign(AllocType.getTypePtr())){
+      unsigned SuitableAlign = Context.getTargetInfo().getSuitableAlign();
+      if (Align > SuitableAlign)
+        Diag(StartLoc, diag::warn_overaligned_type)
+            << AllocType
+            << unsigned(Align / Context.getCharWidth())
+            << unsigned(SuitableAlign / Context.getCharWidth());
+    }
+  }
+
+  QualType InitType = AllocType;
+  // Array 'new' can't have any initializers except empty parentheses.
+  // Initializer lists are also allowed, in C++11. Rely on the parser for the
+  // dialect distinction.
+  if (ResultType->isArrayType() || ArraySize) {
+    if (!isLegalArrayNewInitializer(initStyle, Initializer)) {
+      SourceRange InitRange(Inits[0]->getLocStart(),
+                            Inits[NumInits - 1]->getLocEnd());
+      Diag(StartLoc, diag::err_new_array_init_args) << InitRange;
+      return ExprError();
+    }
+    if (InitListExpr *ILE = dyn_cast_or_null<InitListExpr>(Initializer)) {
+      // We do the initialization typechecking against the array type
+      // corresponding to the number of initializers + 1 (to also check
+      // default-initialization).
+      unsigned NumElements = ILE->getNumInits() + 1;
+      InitType = Context.getConstantArrayType(AllocType,
+          llvm::APInt(Context.getTypeSize(Context.getSizeType()), NumElements),
+                                              ArrayType::Normal, 0);
+    }
+  }
+
+  if (!AllocType->isDependentType() &&
+      !Expr::hasAnyTypeDependentArguments(
+        llvm::makeArrayRef(Inits, NumInits))) {
+    // C++11 [expr.new]p15:
+    //   A new-expression that creates an object of type T initializes that
+    //   object as follows:
+    InitializationKind Kind
+    //     - If the new-initializer is omitted, the object is default-
+    //       initialized (8.5); if no initialization is performed,
+    //       the object has indeterminate value
+      = initStyle == CXXNewExpr::NoInit
+          ? InitializationKind::CreateDefault(TypeRange.getBegin())
+    //     - Otherwise, the new-initializer is interpreted according to the
+    //       initialization rules of 8.5 for direct-initialization.
+          : initStyle == CXXNewExpr::ListInit
+              ? InitializationKind::CreateDirectList(TypeRange.getBegin())
+              : InitializationKind::CreateDirect(TypeRange.getBegin(),
+                                                 DirectInitRange.getBegin(),
+                                                 DirectInitRange.getEnd());
+
+    InitializedEntity Entity
+      = InitializedEntity::InitializeNew(StartLoc, InitType);
+    InitializationSequence InitSeq(*this, Entity, Kind, Inits, NumInits);
+    ExprResult FullInit = InitSeq.Perform(*this, Entity, Kind,
+                                          MultiExprArg(Inits, NumInits));
+    if (FullInit.isInvalid())
+      return ExprError();
+
+    // FullInit is our initializer; strip off CXXBindTemporaryExprs, because
+    // we don't want the initialized object to be destructed.
+    if (CXXBindTemporaryExpr *Binder =
+            dyn_cast_or_null<CXXBindTemporaryExpr>(FullInit.get()))
+      FullInit = Owned(Binder->getSubExpr());
+
+    Initializer = FullInit.take();
+  }
+
+  // Mark the new and delete operators as referenced.
+  if (OperatorNew)
+    MarkFunctionReferenced(StartLoc, OperatorNew);
+  if (OperatorDelete)
+    MarkFunctionReferenced(StartLoc, OperatorDelete);
+
+  // C++0x [expr.new]p17:
+  //   If the new expression creates an array of objects of class type,
+  //   access and ambiguity control are done for the destructor.
+  QualType BaseAllocType = Context.getBaseElementType(AllocType);
+  if (ArraySize && !BaseAllocType->isDependentType()) {
+    if (const RecordType *BaseRecordType = BaseAllocType->getAs<RecordType>()) {
+      if (CXXDestructorDecl *dtor = LookupDestructor(
+              cast<CXXRecordDecl>(BaseRecordType->getDecl()))) {
+        MarkFunctionReferenced(StartLoc, dtor);
+        CheckDestructorAccess(StartLoc, dtor, 
+                              PDiag(diag::err_access_dtor)
+                                << BaseAllocType);
+        DiagnoseUseOfDecl(dtor, StartLoc);
+      }
+    }
+  }
+
+  PlacementArgs.release();
+
+  return Owned(new (Context) CXXNewExpr(Context, UseGlobal, OperatorNew,
+                                        OperatorDelete,
+                                        UsualArrayDeleteWantsSize,
+                                        PlaceArgs, NumPlaceArgs, TypeIdParens,
+                                        ArraySize, initStyle, Initializer,
+                                        ResultType, AllocTypeInfo,
+                                        StartLoc, DirectInitRange));
+}
+
+/// \brief Checks that a type is suitable as the allocated type
+/// in a new-expression.
+bool Sema::CheckAllocatedType(QualType AllocType, SourceLocation Loc,
+                              SourceRange R) {
+  // C++ 5.3.4p1: "[The] type shall be a complete object type, but not an
+  //   abstract class type or array thereof.
+  if (AllocType->isFunctionType())
+    return Diag(Loc, diag::err_bad_new_type)
+      << AllocType << 0 << R;
+  else if (AllocType->isReferenceType())
+    return Diag(Loc, diag::err_bad_new_type)
+      << AllocType << 1 << R;
+  else if (!AllocType->isDependentType() &&
+           RequireCompleteType(Loc, AllocType,
+                               PDiag(diag::err_new_incomplete_type)
+                                 << R))
+    return true;
+  else if (RequireNonAbstractType(Loc, AllocType,
+                                  diag::err_allocation_of_abstract_type))
+    return true;
+  else if (AllocType->isVariablyModifiedType())
+    return Diag(Loc, diag::err_variably_modified_new_type)
+             << AllocType;
+  else if (unsigned AddressSpace = AllocType.getAddressSpace())
+    return Diag(Loc, diag::err_address_space_qualified_new)
+      << AllocType.getUnqualifiedType() << AddressSpace;
+  else if (getLangOpts().ObjCAutoRefCount) {
+    if (const ArrayType *AT = Context.getAsArrayType(AllocType)) {
+      QualType BaseAllocType = Context.getBaseElementType(AT);
+      if (BaseAllocType.getObjCLifetime() == Qualifiers::OCL_None &&
+          BaseAllocType->isObjCLifetimeType())
+        return Diag(Loc, diag::err_arc_new_array_without_ownership)
+          << BaseAllocType;
+    }
+  }
+           
+  return false;
+}
+
+/// \brief Determine whether the given function is a non-placement
+/// deallocation function.
+static bool isNonPlacementDeallocationFunction(FunctionDecl *FD) {
+  if (FD->isInvalidDecl())
+    return false;
+
+  if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(FD))
+    return Method->isUsualDeallocationFunction();
+
+  return ((FD->getOverloadedOperator() == OO_Delete ||
+           FD->getOverloadedOperator() == OO_Array_Delete) &&
+          FD->getNumParams() == 1);
+}
+
+/// FindAllocationFunctions - Finds the overloads of operator new and delete
+/// that are appropriate for the allocation.
+bool Sema::FindAllocationFunctions(SourceLocation StartLoc, SourceRange Range,
+                                   bool UseGlobal, QualType AllocType,
+                                   bool IsArray, Expr **PlaceArgs,
+                                   unsigned NumPlaceArgs,
+                                   FunctionDecl *&OperatorNew,
+                                   FunctionDecl *&OperatorDelete) {
+  // --- Choosing an allocation function ---
+  // C++ 5.3.4p8 - 14 & 18
+  // 1) If UseGlobal is true, only look in the global scope. Else, also look
+  //   in the scope of the allocated class.
+  // 2) If an array size is given, look for operator new[], else look for
+  //   operator new.
+  // 3) The first argument is always size_t. Append the arguments from the
+  //   placement form.
+
+  SmallVector<Expr*, 8> AllocArgs(1 + NumPlaceArgs);
+  // We don't care about the actual value of this argument.
+  // FIXME: Should the Sema create the expression and embed it in the syntax
+  // tree? Or should the consumer just recalculate the value?
+  IntegerLiteral Size(Context, llvm::APInt::getNullValue(
+                      Context.getTargetInfo().getPointerWidth(0)),
+                      Context.getSizeType(),
+                      SourceLocation());
+  AllocArgs[0] = &Size;
+  std::copy(PlaceArgs, PlaceArgs + NumPlaceArgs, AllocArgs.begin() + 1);
+
+  // C++ [expr.new]p8:
+  //   If the allocated type is a non-array type, the allocation
+  //   function's name is operator new and the deallocation function's
+  //   name is operator delete. If the allocated type is an array
+  //   type, the allocation function's name is operator new[] and the
+  //   deallocation function's name is operator delete[].
+  DeclarationName NewName = Context.DeclarationNames.getCXXOperatorName(
+                                        IsArray ? OO_Array_New : OO_New);
+  DeclarationName DeleteName = Context.DeclarationNames.getCXXOperatorName(
+                                        IsArray ? OO_Array_Delete : OO_Delete);
+
+  QualType AllocElemType = Context.getBaseElementType(AllocType);
+
+  if (AllocElemType->isRecordType() && !UseGlobal) {
+    CXXRecordDecl *Record
+      = cast<CXXRecordDecl>(AllocElemType->getAs<RecordType>()->getDecl());
+    if (FindAllocationOverload(StartLoc, Range, NewName, &AllocArgs[0],
+                          AllocArgs.size(), Record, /*AllowMissing=*/true,
+                          OperatorNew))
+      return true;
+  }
+  if (!OperatorNew) {
+    // Didn't find a member overload. Look for a global one.
+    DeclareGlobalNewDelete();
+    DeclContext *TUDecl = Context.getTranslationUnitDecl();
+    if (FindAllocationOverload(StartLoc, Range, NewName, &AllocArgs[0],
+                          AllocArgs.size(), TUDecl, /*AllowMissing=*/false,
+                          OperatorNew))
+      return true;
+  }
+
+  // We don't need an operator delete if we're running under
+  // -fno-exceptions.
+  if (!getLangOpts().Exceptions) {
+    OperatorDelete = 0;
+    return false;
+  }
+
+  // FindAllocationOverload can change the passed in arguments, so we need to
+  // copy them back.
+  if (NumPlaceArgs > 0)
+    std::copy(&AllocArgs[1], AllocArgs.end(), PlaceArgs);
+
+  // C++ [expr.new]p19:
+  //
+  //   If the new-expression begins with a unary :: operator, the
+  //   deallocation function's name is looked up in the global
+  //   scope. Otherwise, if the allocated type is a class type T or an
+  //   array thereof, the deallocation function's name is looked up in
+  //   the scope of T. If this lookup fails to find the name, or if
+  //   the allocated type is not a class type or array thereof, the
+  //   deallocation function's name is looked up in the global scope.
+  LookupResult FoundDelete(*this, DeleteName, StartLoc, LookupOrdinaryName);
+  if (AllocElemType->isRecordType() && !UseGlobal) {
+    CXXRecordDecl *RD
+      = cast<CXXRecordDecl>(AllocElemType->getAs<RecordType>()->getDecl());
+    LookupQualifiedName(FoundDelete, RD);
+  }
+  if (FoundDelete.isAmbiguous())
+    return true; // FIXME: clean up expressions?
+
+  if (FoundDelete.empty()) {
+    DeclareGlobalNewDelete();
+    LookupQualifiedName(FoundDelete, Context.getTranslationUnitDecl());
+  }
+
+  FoundDelete.suppressDiagnostics();
+
+  SmallVector<std::pair<DeclAccessPair,FunctionDecl*>, 2> Matches;
+
+  // Whether we're looking for a placement operator delete is dictated
+  // by whether we selected a placement operator new, not by whether
+  // we had explicit placement arguments.  This matters for things like
+  //   struct A { void *operator new(size_t, int = 0); ... };
+  //   A *a = new A()
+  bool isPlacementNew = (NumPlaceArgs > 0 || OperatorNew->param_size() != 1);
+
+  if (isPlacementNew) {
+    // C++ [expr.new]p20:
+    //   A declaration of a placement deallocation function matches the
+    //   declaration of a placement allocation function if it has the
+    //   same number of parameters and, after parameter transformations
+    //   (8.3.5), all parameter types except the first are
+    //   identical. [...]
+    //
+    // To perform this comparison, we compute the function type that
+    // the deallocation function should have, and use that type both
+    // for template argument deduction and for comparison purposes.
+    //
+    // FIXME: this comparison should ignore CC and the like.
+    QualType ExpectedFunctionType;
+    {
+      const FunctionProtoType *Proto
+        = OperatorNew->getType()->getAs<FunctionProtoType>();
+
+      SmallVector<QualType, 4> ArgTypes;
+      ArgTypes.push_back(Context.VoidPtrTy);
+      for (unsigned I = 1, N = Proto->getNumArgs(); I < N; ++I)
+        ArgTypes.push_back(Proto->getArgType(I));
+
+      FunctionProtoType::ExtProtoInfo EPI;
+      EPI.Variadic = Proto->isVariadic();
+
+      ExpectedFunctionType
+        = Context.getFunctionType(Context.VoidTy, ArgTypes.data(),
+                                  ArgTypes.size(), EPI);
+    }
+
+    for (LookupResult::iterator D = FoundDelete.begin(),
+                             DEnd = FoundDelete.end();
+         D != DEnd; ++D) {
+      FunctionDecl *Fn = 0;
+      if (FunctionTemplateDecl *FnTmpl
+            = dyn_cast<FunctionTemplateDecl>((*D)->getUnderlyingDecl())) {
+        // Perform template argument deduction to try to match the
+        // expected function type.
+        TemplateDeductionInfo Info(Context, StartLoc);
+        if (DeduceTemplateArguments(FnTmpl, 0, ExpectedFunctionType, Fn, Info))
+          continue;
+      } else
+        Fn = cast<FunctionDecl>((*D)->getUnderlyingDecl());
+
+      if (Context.hasSameType(Fn->getType(), ExpectedFunctionType))
+        Matches.push_back(std::make_pair(D.getPair(), Fn));
+    }
+  } else {
+    // C++ [expr.new]p20:
+    //   [...] Any non-placement deallocation function matches a
+    //   non-placement allocation function. [...]
+    for (LookupResult::iterator D = FoundDelete.begin(),
+                             DEnd = FoundDelete.end();
+         D != DEnd; ++D) {
+      if (FunctionDecl *Fn = dyn_cast<FunctionDecl>((*D)->getUnderlyingDecl()))
+        if (isNonPlacementDeallocationFunction(Fn))
+          Matches.push_back(std::make_pair(D.getPair(), Fn));
+    }
+  }
+
+  // C++ [expr.new]p20:
+  //   [...] If the lookup finds a single matching deallocation
+  //   function, that function will be called; otherwise, no
+  //   deallocation function will be called.
+  if (Matches.size() == 1) {
+    OperatorDelete = Matches[0].second;
+
+    // C++0x [expr.new]p20:
+    //   If the lookup finds the two-parameter form of a usual
+    //   deallocation function (3.7.4.2) and that function, considered
+    //   as a placement deallocation function, would have been
+    //   selected as a match for the allocation function, the program
+    //   is ill-formed.
+    if (NumPlaceArgs && getLangOpts().CPlusPlus0x &&
+        isNonPlacementDeallocationFunction(OperatorDelete)) {
+      Diag(StartLoc, diag::err_placement_new_non_placement_delete)
+        << SourceRange(PlaceArgs[0]->getLocStart(),
+                       PlaceArgs[NumPlaceArgs - 1]->getLocEnd());
+      Diag(OperatorDelete->getLocation(), diag::note_previous_decl)
+        << DeleteName;
+    } else {
+      CheckAllocationAccess(StartLoc, Range, FoundDelete.getNamingClass(),
+                            Matches[0].first);
+    }
+  }
+
+  return false;
+}
+
+/// FindAllocationOverload - Find an fitting overload for the allocation
+/// function in the specified scope.
+bool Sema::FindAllocationOverload(SourceLocation StartLoc, SourceRange Range,
+                                  DeclarationName Name, Expr** Args,
+                                  unsigned NumArgs, DeclContext *Ctx,
+                                  bool AllowMissing, FunctionDecl *&Operator,
+                                  bool Diagnose) {
+  LookupResult R(*this, Name, StartLoc, LookupOrdinaryName);
+  LookupQualifiedName(R, Ctx);
+  if (R.empty()) {
+    if (AllowMissing || !Diagnose)
+      return false;
+    return Diag(StartLoc, diag::err_ovl_no_viable_function_in_call)
+      << Name << Range;
+  }
+
+  if (R.isAmbiguous())
+    return true;
+
+  R.suppressDiagnostics();
+
+  OverloadCandidateSet Candidates(StartLoc);
+  for (LookupResult::iterator Alloc = R.begin(), AllocEnd = R.end();
+       Alloc != AllocEnd; ++Alloc) {
+    // Even member operator new/delete are implicitly treated as
+    // static, so don't use AddMemberCandidate.
+    NamedDecl *D = (*Alloc)->getUnderlyingDecl();
+
+    if (FunctionTemplateDecl *FnTemplate = dyn_cast<FunctionTemplateDecl>(D)) {
+      AddTemplateOverloadCandidate(FnTemplate, Alloc.getPair(),
+                                   /*ExplicitTemplateArgs=*/0,
+                                   llvm::makeArrayRef(Args, NumArgs),
+                                   Candidates,
+                                   /*SuppressUserConversions=*/false);
+      continue;
+    }
+
+    FunctionDecl *Fn = cast<FunctionDecl>(D);
+    AddOverloadCandidate(Fn, Alloc.getPair(),
+                         llvm::makeArrayRef(Args, NumArgs), Candidates,
+                         /*SuppressUserConversions=*/false);
+  }
+
+  // Do the resolution.
+  OverloadCandidateSet::iterator Best;
+  switch (Candidates.BestViableFunction(*this, StartLoc, Best)) {
+  case OR_Success: {
+    // Got one!
+    FunctionDecl *FnDecl = Best->Function;
+    MarkFunctionReferenced(StartLoc, FnDecl);
+    // The first argument is size_t, and the first parameter must be size_t,
+    // too. This is checked on declaration and can be assumed. (It can't be
+    // asserted on, though, since invalid decls are left in there.)
+    // Watch out for variadic allocator function.
+    unsigned NumArgsInFnDecl = FnDecl->getNumParams();
+    for (unsigned i = 0; (i < NumArgs && i < NumArgsInFnDecl); ++i) {
+      InitializedEntity Entity = InitializedEntity::InitializeParameter(Context,
+                                                       FnDecl->getParamDecl(i));
+
+      if (!Diagnose && !CanPerformCopyInitialization(Entity, Owned(Args[i])))
+        return true;
+
+      ExprResult Result
+        = PerformCopyInitialization(Entity, SourceLocation(), Owned(Args[i]));
+      if (Result.isInvalid())
+        return true;
+
+      Args[i] = Result.takeAs<Expr>();
+    }
+
+    Operator = FnDecl;
+
+    if (CheckAllocationAccess(StartLoc, Range, R.getNamingClass(),
+                              Best->FoundDecl, Diagnose) == AR_inaccessible)
+      return true;
+
+    return false;
+  }
+
+  case OR_No_Viable_Function:
+    if (Diagnose) {
+      Diag(StartLoc, diag::err_ovl_no_viable_function_in_call)
+        << Name << Range;
+      Candidates.NoteCandidates(*this, OCD_AllCandidates,
+                                llvm::makeArrayRef(Args, NumArgs));
+    }
+    return true;
+
+  case OR_Ambiguous:
+    if (Diagnose) {
+      Diag(StartLoc, diag::err_ovl_ambiguous_call)
+        << Name << Range;
+      Candidates.NoteCandidates(*this, OCD_ViableCandidates,
+                                llvm::makeArrayRef(Args, NumArgs));
+    }
+    return true;
+
+  case OR_Deleted: {
+    if (Diagnose) {
+      Diag(StartLoc, diag::err_ovl_deleted_call)
+        << Best->Function->isDeleted()
+        << Name 
+        << getDeletedOrUnavailableSuffix(Best->Function)
+        << Range;
+      Candidates.NoteCandidates(*this, OCD_AllCandidates,
+                                llvm::makeArrayRef(Args, NumArgs));
+    }
+    return true;
+  }
+  }
+  llvm_unreachable("Unreachable, bad result from BestViableFunction");
+}
+
+
+/// DeclareGlobalNewDelete - Declare the global forms of operator new and
+/// delete. These are:
+/// @code
+///   // C++03:
+///   void* operator new(std::size_t) throw(std::bad_alloc);
+///   void* operator new[](std::size_t) throw(std::bad_alloc);
+///   void operator delete(void *) throw();
+///   void operator delete[](void *) throw();
+///   // C++0x:
+///   void* operator new(std::size_t);
+///   void* operator new[](std::size_t);
+///   void operator delete(void *);
+///   void operator delete[](void *);
+/// @endcode
+/// C++0x operator delete is implicitly noexcept.
+/// Note that the placement and nothrow forms of new are *not* implicitly
+/// declared. Their use requires including \<new\>.
+void Sema::DeclareGlobalNewDelete() {
+  if (GlobalNewDeleteDeclared)
+    return;
+
+  // C++ [basic.std.dynamic]p2:
+  //   [...] The following allocation and deallocation functions (18.4) are
+  //   implicitly declared in global scope in each translation unit of a
+  //   program
+  //
+  //     C++03:
+  //     void* operator new(std::size_t) throw(std::bad_alloc);
+  //     void* operator new[](std::size_t) throw(std::bad_alloc);
+  //     void  operator delete(void*) throw();
+  //     void  operator delete[](void*) throw();
+  //     C++0x:
+  //     void* operator new(std::size_t);
+  //     void* operator new[](std::size_t);
+  //     void  operator delete(void*);
+  //     void  operator delete[](void*);
+  //
+  //   These implicit declarations introduce only the function names operator
+  //   new, operator new[], operator delete, operator delete[].
+  //
+  // Here, we need to refer to std::bad_alloc, so we will implicitly declare
+  // "std" or "bad_alloc" as necessary to form the exception specification.
+  // However, we do not make these implicit declarations visible to name
+  // lookup.
+  // Note that the C++0x versions of operator delete are deallocation functions,
+  // and thus are implicitly noexcept.
+  if (!StdBadAlloc && !getLangOpts().CPlusPlus0x) {
+    // The "std::bad_alloc" class has not yet been declared, so build it
+    // implicitly.
+    StdBadAlloc = CXXRecordDecl::Create(Context, TTK_Class,
+                                        getOrCreateStdNamespace(),
+                                        SourceLocation(), SourceLocation(),
+                                      &PP.getIdentifierTable().get("bad_alloc"),
+                                        0);
+    getStdBadAlloc()->setImplicit(true);
+  }
+
+  GlobalNewDeleteDeclared = true;
+
+  QualType VoidPtr = Context.getPointerType(Context.VoidTy);
+  QualType SizeT = Context.getSizeType();
+  bool AssumeSaneOperatorNew = getLangOpts().AssumeSaneOperatorNew;
+
+  DeclareGlobalAllocationFunction(
+      Context.DeclarationNames.getCXXOperatorName(OO_New),
+      VoidPtr, SizeT, AssumeSaneOperatorNew);
+  DeclareGlobalAllocationFunction(
+      Context.DeclarationNames.getCXXOperatorName(OO_Array_New),
+      VoidPtr, SizeT, AssumeSaneOperatorNew);
+  DeclareGlobalAllocationFunction(
+      Context.DeclarationNames.getCXXOperatorName(OO_Delete),
+      Context.VoidTy, VoidPtr);
+  DeclareGlobalAllocationFunction(
+      Context.DeclarationNames.getCXXOperatorName(OO_Array_Delete),
+      Context.VoidTy, VoidPtr);
+}
+
+/// DeclareGlobalAllocationFunction - Declares a single implicit global
+/// allocation function if it doesn't already exist.
+void Sema::DeclareGlobalAllocationFunction(DeclarationName Name,
+                                           QualType Return, QualType Argument,
+                                           bool AddMallocAttr) {
+  DeclContext *GlobalCtx = Context.getTranslationUnitDecl();
+
+  // Check if this function is already declared.
+  {
+    DeclContext::lookup_iterator Alloc, AllocEnd;
+    for (llvm::tie(Alloc, AllocEnd) = GlobalCtx->lookup(Name);
+         Alloc != AllocEnd; ++Alloc) {
+      // Only look at non-template functions, as it is the predefined,
+      // non-templated allocation function we are trying to declare here.
+      if (FunctionDecl *Func = dyn_cast<FunctionDecl>(*Alloc)) {
+        QualType InitialParamType =
+          Context.getCanonicalType(
+            Func->getParamDecl(0)->getType().getUnqualifiedType());
+        // FIXME: Do we need to check for default arguments here?
+        if (Func->getNumParams() == 1 && InitialParamType == Argument) {
+          if(AddMallocAttr && !Func->hasAttr<MallocAttr>())
+            Func->addAttr(::new (Context) MallocAttr(SourceLocation(), Context));
+          return;
+        }
+      }
+    }
+  }
+
+  QualType BadAllocType;
+  bool HasBadAllocExceptionSpec
+    = (Name.getCXXOverloadedOperator() == OO_New ||
+       Name.getCXXOverloadedOperator() == OO_Array_New);
+  if (HasBadAllocExceptionSpec && !getLangOpts().CPlusPlus0x) {
+    assert(StdBadAlloc && "Must have std::bad_alloc declared");
+    BadAllocType = Context.getTypeDeclType(getStdBadAlloc());
+  }
+
+  FunctionProtoType::ExtProtoInfo EPI;
+  if (HasBadAllocExceptionSpec) {
+    if (!getLangOpts().CPlusPlus0x) {
+      EPI.ExceptionSpecType = EST_Dynamic;
+      EPI.NumExceptions = 1;
+      EPI.Exceptions = &BadAllocType;
+    }
+  } else {
+    EPI.ExceptionSpecType = getLangOpts().CPlusPlus0x ?
+                                EST_BasicNoexcept : EST_DynamicNone;
+  }
+
+  QualType FnType = Context.getFunctionType(Return, &Argument, 1, EPI);
+  FunctionDecl *Alloc =
+    FunctionDecl::Create(Context, GlobalCtx, SourceLocation(),
+                         SourceLocation(), Name,
+                         FnType, /*TInfo=*/0, SC_None,
+                         SC_None, false, true);
+  Alloc->setImplicit();
+
+  if (AddMallocAttr)
+    Alloc->addAttr(::new (Context) MallocAttr(SourceLocation(), Context));
+
+  ParmVarDecl *Param = ParmVarDecl::Create(Context, Alloc, SourceLocation(),
+                                           SourceLocation(), 0,
+                                           Argument, /*TInfo=*/0,
+                                           SC_None, SC_None, 0);
+  Alloc->setParams(Param);
+
+  // FIXME: Also add this declaration to the IdentifierResolver, but
+  // make sure it is at the end of the chain to coincide with the
+  // global scope.
+  Context.getTranslationUnitDecl()->addDecl(Alloc);
+}
+
+bool Sema::FindDeallocationFunction(SourceLocation StartLoc, CXXRecordDecl *RD,
+                                    DeclarationName Name,
+                                    FunctionDecl* &Operator, bool Diagnose) {
+  LookupResult Found(*this, Name, StartLoc, LookupOrdinaryName);
+  // Try to find operator delete/operator delete[] in class scope.
+  LookupQualifiedName(Found, RD);
+
+  if (Found.isAmbiguous())
+    return true;
+
+  Found.suppressDiagnostics();
+
+  SmallVector<DeclAccessPair,4> Matches;
+  for (LookupResult::iterator F = Found.begin(), FEnd = Found.end();
+       F != FEnd; ++F) {
+    NamedDecl *ND = (*F)->getUnderlyingDecl();
+
+    // Ignore template operator delete members from the check for a usual
+    // deallocation function.
+    if (isa<FunctionTemplateDecl>(ND))
+      continue;
+
+    if (cast<CXXMethodDecl>(ND)->isUsualDeallocationFunction())
+      Matches.push_back(F.getPair());
+  }
+
+  // There's exactly one suitable operator;  pick it.
+  if (Matches.size() == 1) {
+    Operator = cast<CXXMethodDecl>(Matches[0]->getUnderlyingDecl());
+
+    if (Operator->isDeleted()) {
+      if (Diagnose) {
+        Diag(StartLoc, diag::err_deleted_function_use);
+        NoteDeletedFunction(Operator);
+      }
+      return true;
+    }
+
+    if (CheckAllocationAccess(StartLoc, SourceRange(), Found.getNamingClass(),
+                              Matches[0], Diagnose) == AR_inaccessible)
+      return true;
+
+    return false;
+
+  // We found multiple suitable operators;  complain about the ambiguity.
+  } else if (!Matches.empty()) {
+    if (Diagnose) {
+      Diag(StartLoc, diag::err_ambiguous_suitable_delete_member_function_found)
+        << Name << RD;
+
+      for (SmallVectorImpl<DeclAccessPair>::iterator
+             F = Matches.begin(), FEnd = Matches.end(); F != FEnd; ++F)
+        Diag((*F)->getUnderlyingDecl()->getLocation(),
+             diag::note_member_declared_here) << Name;
+    }
+    return true;
+  }
+
+  // We did find operator delete/operator delete[] declarations, but
+  // none of them were suitable.
+  if (!Found.empty()) {
+    if (Diagnose) {
+      Diag(StartLoc, diag::err_no_suitable_delete_member_function_found)
+        << Name << RD;
+
+      for (LookupResult::iterator F = Found.begin(), FEnd = Found.end();
+           F != FEnd; ++F)
+        Diag((*F)->getUnderlyingDecl()->getLocation(),
+             diag::note_member_declared_here) << Name;
+    }
+    return true;
+  }
+
+  // Look for a global declaration.
+  DeclareGlobalNewDelete();
+  DeclContext *TUDecl = Context.getTranslationUnitDecl();
+
+  CXXNullPtrLiteralExpr Null(Context.VoidPtrTy, SourceLocation());
+  Expr* DeallocArgs[1];
+  DeallocArgs[0] = &Null;
+  if (FindAllocationOverload(StartLoc, SourceRange(), Name,
+                             DeallocArgs, 1, TUDecl, !Diagnose,
+                             Operator, Diagnose))
+    return true;
+
+  assert(Operator && "Did not find a deallocation function!");
+  return false;
+}
+
+/// ActOnCXXDelete - Parsed a C++ 'delete' expression (C++ 5.3.5), as in:
+/// @code ::delete ptr; @endcode
+/// or
+/// @code delete [] ptr; @endcode
+ExprResult
+Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal,
+                     bool ArrayForm, Expr *ExE) {
+  // C++ [expr.delete]p1:
+  //   The operand shall have a pointer type, or a class type having a single
+  //   conversion function to a pointer type. The result has type void.
+  //
+  // DR599 amends "pointer type" to "pointer to object type" in both cases.
+
+  ExprResult Ex = Owned(ExE);
+  FunctionDecl *OperatorDelete = 0;
+  bool ArrayFormAsWritten = ArrayForm;
+  bool UsualArrayDeleteWantsSize = false;
+
+  if (!Ex.get()->isTypeDependent()) {
+    // Perform lvalue-to-rvalue cast, if needed.
+    Ex = DefaultLvalueConversion(Ex.take());
+
+    QualType Type = Ex.get()->getType();
+
+    if (const RecordType *Record = Type->getAs<RecordType>()) {
+      if (RequireCompleteType(StartLoc, Type,
+                              PDiag(diag::err_delete_incomplete_class_type)))
+        return ExprError();
+
+      SmallVector<CXXConversionDecl*, 4> ObjectPtrConversions;
+
+      CXXRecordDecl *RD = cast<CXXRecordDecl>(Record->getDecl());
+      const UnresolvedSetImpl *Conversions = RD->getVisibleConversionFunctions();
+      for (UnresolvedSetImpl::iterator I = Conversions->begin(),
+             E = Conversions->end(); I != E; ++I) {
+        NamedDecl *D = I.getDecl();
+        if (isa<UsingShadowDecl>(D))
+          D = cast<UsingShadowDecl>(D)->getTargetDecl();
+
+        // Skip over templated conversion functions; they aren't considered.
+        if (isa<FunctionTemplateDecl>(D))
+          continue;
+
+        CXXConversionDecl *Conv = cast<CXXConversionDecl>(D);
+
+        QualType ConvType = Conv->getConversionType().getNonReferenceType();
+        if (const PointerType *ConvPtrType = ConvType->getAs<PointerType>())
+          if (ConvPtrType->getPointeeType()->isIncompleteOrObjectType())
+            ObjectPtrConversions.push_back(Conv);
+      }
+      if (ObjectPtrConversions.size() == 1) {
+        // We have a single conversion to a pointer-to-object type. Perform
+        // that conversion.
+        // TODO: don't redo the conversion calculation.
+        ExprResult Res =
+          PerformImplicitConversion(Ex.get(),
+                            ObjectPtrConversions.front()->getConversionType(),
+                                    AA_Converting);
+        if (Res.isUsable()) {
+          Ex = move(Res);
+          Type = Ex.get()->getType();
+        }
+      }
+      else if (ObjectPtrConversions.size() > 1) {
+        Diag(StartLoc, diag::err_ambiguous_delete_operand)
+              << Type << Ex.get()->getSourceRange();
+        for (unsigned i= 0; i < ObjectPtrConversions.size(); i++)
+          NoteOverloadCandidate(ObjectPtrConversions[i]);
+        return ExprError();
+      }
+    }
+
+    if (!Type->isPointerType())
+      return ExprError(Diag(StartLoc, diag::err_delete_operand)
+        << Type << Ex.get()->getSourceRange());
+
+    QualType Pointee = Type->getAs<PointerType>()->getPointeeType();
+    QualType PointeeElem = Context.getBaseElementType(Pointee);
+
+    if (unsigned AddressSpace = Pointee.getAddressSpace())
+      return Diag(Ex.get()->getLocStart(), 
+                  diag::err_address_space_qualified_delete)
+               << Pointee.getUnqualifiedType() << AddressSpace;
+
+    CXXRecordDecl *PointeeRD = 0;
+    if (Pointee->isVoidType() && !isSFINAEContext()) {
+      // The C++ standard bans deleting a pointer to a non-object type, which
+      // effectively bans deletion of "void*". However, most compilers support
+      // this, so we treat it as a warning unless we're in a SFINAE context.
+      Diag(StartLoc, diag::ext_delete_void_ptr_operand)
+        << Type << Ex.get()->getSourceRange();
+    } else if (Pointee->isFunctionType() || Pointee->isVoidType()) {
+      return ExprError(Diag(StartLoc, diag::err_delete_operand)
+        << Type << Ex.get()->getSourceRange());
+    } else if (!Pointee->isDependentType()) {
+      if (!RequireCompleteType(StartLoc, Pointee,
+                               PDiag(diag::warn_delete_incomplete)
+                                 << Ex.get()->getSourceRange())) {
+        if (const RecordType *RT = PointeeElem->getAs<RecordType>())
+          PointeeRD = cast<CXXRecordDecl>(RT->getDecl());
+      }
+    }
+
+    // C++ [expr.delete]p2:
+    //   [Note: a pointer to a const type can be the operand of a
+    //   delete-expression; it is not necessary to cast away the constness
+    //   (5.2.11) of the pointer expression before it is used as the operand
+    //   of the delete-expression. ]
+    if (!Context.hasSameType(Ex.get()->getType(), Context.VoidPtrTy))
+      Ex = Owned(ImplicitCastExpr::Create(Context, Context.VoidPtrTy,
+                                          CK_BitCast, Ex.take(), 0, VK_RValue));
+
+    if (Pointee->isArrayType() && !ArrayForm) {
+      Diag(StartLoc, diag::warn_delete_array_type)
+          << Type << Ex.get()->getSourceRange()
+          << FixItHint::CreateInsertion(PP.getLocForEndOfToken(StartLoc), "[]");
+      ArrayForm = true;
+    }
+
+    DeclarationName DeleteName = Context.DeclarationNames.getCXXOperatorName(
+                                      ArrayForm ? OO_Array_Delete : OO_Delete);
+
+    if (PointeeRD) {
+      if (!UseGlobal &&
+          FindDeallocationFunction(StartLoc, PointeeRD, DeleteName,
+                                   OperatorDelete))
+        return ExprError();
+
+      // If we're allocating an array of records, check whether the
+      // usual operator delete[] has a size_t parameter.
+      if (ArrayForm) {
+        // If the user specifically asked to use the global allocator,
+        // we'll need to do the lookup into the class.
+        if (UseGlobal)
+          UsualArrayDeleteWantsSize =
+            doesUsualArrayDeleteWantSize(*this, StartLoc, PointeeElem);
+
+        // Otherwise, the usual operator delete[] should be the
+        // function we just found.
+        else if (isa<CXXMethodDecl>(OperatorDelete))
+          UsualArrayDeleteWantsSize = (OperatorDelete->getNumParams() == 2);
+      }
+
+      if (!PointeeRD->hasIrrelevantDestructor())
+        if (CXXDestructorDecl *Dtor = LookupDestructor(PointeeRD)) {
+          MarkFunctionReferenced(StartLoc,
+                                    const_cast<CXXDestructorDecl*>(Dtor));
+          DiagnoseUseOfDecl(Dtor, StartLoc);
+        }
+
+      // C++ [expr.delete]p3:
+      //   In the first alternative (delete object), if the static type of the
+      //   object to be deleted is different from its dynamic type, the static
+      //   type shall be a base class of the dynamic type of the object to be
+      //   deleted and the static type shall have a virtual destructor or the
+      //   behavior is undefined.
+      //
+      // Note: a final class cannot be derived from, no issue there
+      if (PointeeRD->isPolymorphic() && !PointeeRD->hasAttr<FinalAttr>()) {
+        CXXDestructorDecl *dtor = PointeeRD->getDestructor();
+        if (dtor && !dtor->isVirtual()) {
+          if (PointeeRD->isAbstract()) {
+            // If the class is abstract, we warn by default, because we're
+            // sure the code has undefined behavior.
+            Diag(StartLoc, diag::warn_delete_abstract_non_virtual_dtor)
+                << PointeeElem;
+          } else if (!ArrayForm) {
+            // Otherwise, if this is not an array delete, it's a bit suspect,
+            // but not necessarily wrong.
+            Diag(StartLoc, diag::warn_delete_non_virtual_dtor) << PointeeElem;
+          }
+        }
+      }
+
+    } else if (getLangOpts().ObjCAutoRefCount &&
+               PointeeElem->isObjCLifetimeType() &&
+               (PointeeElem.getObjCLifetime() == Qualifiers::OCL_Strong ||
+                PointeeElem.getObjCLifetime() == Qualifiers::OCL_Weak) &&
+               ArrayForm) {
+      Diag(StartLoc, diag::warn_err_new_delete_object_array)
+        << 1 << PointeeElem;
+    }
+
+    if (!OperatorDelete) {
+      // Look for a global declaration.
+      DeclareGlobalNewDelete();
+      DeclContext *TUDecl = Context.getTranslationUnitDecl();
+      Expr *Arg = Ex.get();
+      if (FindAllocationOverload(StartLoc, SourceRange(), DeleteName,
+                                 &Arg, 1, TUDecl, /*AllowMissing=*/false,
+                                 OperatorDelete))
+        return ExprError();
+    }
+
+    MarkFunctionReferenced(StartLoc, OperatorDelete);
+    
+    // Check access and ambiguity of operator delete and destructor.
+    if (PointeeRD) {
+      if (CXXDestructorDecl *Dtor = LookupDestructor(PointeeRD)) {
+          CheckDestructorAccess(Ex.get()->getExprLoc(), Dtor, 
+                      PDiag(diag::err_access_dtor) << PointeeElem);
+      }
+    }
+
+  }
+
+  return Owned(new (Context) CXXDeleteExpr(Context.VoidTy, UseGlobal, ArrayForm,
+                                           ArrayFormAsWritten,
+                                           UsualArrayDeleteWantsSize,
+                                           OperatorDelete, Ex.take(), StartLoc));
+}
+
+/// \brief Check the use of the given variable as a C++ condition in an if,
+/// while, do-while, or switch statement.
+ExprResult Sema::CheckConditionVariable(VarDecl *ConditionVar,
+                                        SourceLocation StmtLoc,
+                                        bool ConvertToBoolean) {
+  QualType T = ConditionVar->getType();
+
+  // C++ [stmt.select]p2:
+  //   The declarator shall not specify a function or an array.
+  if (T->isFunctionType())
+    return ExprError(Diag(ConditionVar->getLocation(),
+                          diag::err_invalid_use_of_function_type)
+                       << ConditionVar->getSourceRange());
+  else if (T->isArrayType())
+    return ExprError(Diag(ConditionVar->getLocation(),
+                          diag::err_invalid_use_of_array_type)
+                     << ConditionVar->getSourceRange());
+
+  ExprResult Condition =
+    Owned(DeclRefExpr::Create(Context, NestedNameSpecifierLoc(),
+                              SourceLocation(),
+                              ConditionVar,
+                              /*enclosing*/ false,
+                              ConditionVar->getLocation(),
+                              ConditionVar->getType().getNonReferenceType(),
+                              VK_LValue));
+
+  MarkDeclRefReferenced(cast<DeclRefExpr>(Condition.get()));
+
+  if (ConvertToBoolean) {
+    Condition = CheckBooleanCondition(Condition.take(), StmtLoc);
+    if (Condition.isInvalid())
+      return ExprError();
+  }
+
+  return move(Condition);
+}
+
+/// CheckCXXBooleanCondition - Returns true if a conversion to bool is invalid.
+ExprResult Sema::CheckCXXBooleanCondition(Expr *CondExpr) {
+  // C++ 6.4p4:
+  // The value of a condition that is an initialized declaration in a statement
+  // other than a switch statement is the value of the declared variable
+  // implicitly converted to type bool. If that conversion is ill-formed, the
+  // program is ill-formed.
+  // The value of a condition that is an expression is the value of the
+  // expression, implicitly converted to bool.
+  //
+  return PerformContextuallyConvertToBool(CondExpr);
+}
+
+/// Helper function to determine whether this is the (deprecated) C++
+/// conversion from a string literal to a pointer to non-const char or
+/// non-const wchar_t (for narrow and wide string literals,
+/// respectively).
+bool
+Sema::IsStringLiteralToNonConstPointerConversion(Expr *From, QualType ToType) {
+  // Look inside the implicit cast, if it exists.
+  if (ImplicitCastExpr *Cast = dyn_cast<ImplicitCastExpr>(From))
+    From = Cast->getSubExpr();
+
+  // A string literal (2.13.4) that is not a wide string literal can
+  // be converted to an rvalue of type "pointer to char"; a wide
+  // string literal can be converted to an rvalue of type "pointer
+  // to wchar_t" (C++ 4.2p2).
+  if (StringLiteral *StrLit = dyn_cast<StringLiteral>(From->IgnoreParens()))
+    if (const PointerType *ToPtrType = ToType->getAs<PointerType>())
+      if (const BuiltinType *ToPointeeType
+          = ToPtrType->getPointeeType()->getAs<BuiltinType>()) {
+        // This conversion is considered only when there is an
+        // explicit appropriate pointer target type (C++ 4.2p2).
+        if (!ToPtrType->getPointeeType().hasQualifiers()) {
+          switch (StrLit->getKind()) {
+            case StringLiteral::UTF8:
+            case StringLiteral::UTF16:
+            case StringLiteral::UTF32:
+              // We don't allow UTF literals to be implicitly converted
+              break;
+            case StringLiteral::Ascii:
+              return (ToPointeeType->getKind() == BuiltinType::Char_U ||
+                      ToPointeeType->getKind() == BuiltinType::Char_S);
+            case StringLiteral::Wide:
+              return ToPointeeType->isWideCharType();
+          }
+        }
+      }
+
+  return false;
+}
+
+static ExprResult BuildCXXCastArgument(Sema &S,
+                                       SourceLocation CastLoc,
+                                       QualType Ty,
+                                       CastKind Kind,
+                                       CXXMethodDecl *Method,
+                                       DeclAccessPair FoundDecl,
+                                       bool HadMultipleCandidates,
+                                       Expr *From) {
+  switch (Kind) {
+  default: llvm_unreachable("Unhandled cast kind!");
+  case CK_ConstructorConversion: {
+    CXXConstructorDecl *Constructor = cast<CXXConstructorDecl>(Method);
+    ASTOwningVector<Expr*> ConstructorArgs(S);
+
+    if (S.CompleteConstructorCall(Constructor,
+                                  MultiExprArg(&From, 1),
+                                  CastLoc, ConstructorArgs))
+      return ExprError();
+
+    S.CheckConstructorAccess(CastLoc, Constructor,
+                             InitializedEntity::InitializeTemporary(Ty),
+                             Constructor->getAccess());
+    
+    ExprResult Result
+      = S.BuildCXXConstructExpr(CastLoc, Ty, cast<CXXConstructorDecl>(Method),
+                                move_arg(ConstructorArgs), 
+                                HadMultipleCandidates, /*ZeroInit*/ false, 
+                                CXXConstructExpr::CK_Complete, SourceRange());
+    if (Result.isInvalid())
+      return ExprError();
+
+    return S.MaybeBindToTemporary(Result.takeAs<Expr>());
+  }
+
+  case CK_UserDefinedConversion: {
+    assert(!From->getType()->isPointerType() && "Arg can't have pointer type!");
+
+    // Create an implicit call expr that calls it.
+    CXXConversionDecl *Conv = cast<CXXConversionDecl>(Method);
+    ExprResult Result = S.BuildCXXMemberCallExpr(From, FoundDecl, Conv,
+                                                 HadMultipleCandidates);
+    if (Result.isInvalid())
+      return ExprError();
+    // Record usage of conversion in an implicit cast.
+    Result = S.Owned(ImplicitCastExpr::Create(S.Context,
+                                              Result.get()->getType(),
+                                              CK_UserDefinedConversion,
+                                              Result.get(), 0,
+                                              Result.get()->getValueKind()));
+
+    S.CheckMemberOperatorAccess(CastLoc, From, /*arg*/ 0, FoundDecl);
+
+    return S.MaybeBindToTemporary(Result.get());
+  }
+  }
+}
+
+/// PerformImplicitConversion - Perform an implicit conversion of the
+/// expression From to the type ToType using the pre-computed implicit
+/// conversion sequence ICS. Returns the converted
+/// expression. Action is the kind of conversion we're performing,
+/// used in the error message.
+ExprResult
+Sema::PerformImplicitConversion(Expr *From, QualType ToType,
+                                const ImplicitConversionSequence &ICS,
+                                AssignmentAction Action, 
+                                CheckedConversionKind CCK) {
+  switch (ICS.getKind()) {
+  case ImplicitConversionSequence::StandardConversion: {
+    ExprResult Res = PerformImplicitConversion(From, ToType, ICS.Standard,
+                                               Action, CCK);
+    if (Res.isInvalid())
+      return ExprError();
+    From = Res.take();
+    break;
+  }
+
+  case ImplicitConversionSequence::UserDefinedConversion: {
+
+      FunctionDecl *FD = ICS.UserDefined.ConversionFunction;
+      CastKind CastKind;
+      QualType BeforeToType;
+      assert(FD && "FIXME: aggregate initialization from init list");
+      if (const CXXConversionDecl *Conv = dyn_cast<CXXConversionDecl>(FD)) {
+        CastKind = CK_UserDefinedConversion;
+
+        // If the user-defined conversion is specified by a conversion function,
+        // the initial standard conversion sequence converts the source type to
+        // the implicit object parameter of the conversion function.
+        BeforeToType = Context.getTagDeclType(Conv->getParent());
+      } else {
+        const CXXConstructorDecl *Ctor = cast<CXXConstructorDecl>(FD);
+        CastKind = CK_ConstructorConversion;
+        // Do no conversion if dealing with ... for the first conversion.
+        if (!ICS.UserDefined.EllipsisConversion) {
+          // If the user-defined conversion is specified by a constructor, the
+          // initial standard conversion sequence converts the source type to the
+          // type required by the argument of the constructor
+          BeforeToType = Ctor->getParamDecl(0)->getType().getNonReferenceType();
+        }
+      }
+      // Watch out for elipsis conversion.
+      if (!ICS.UserDefined.EllipsisConversion) {
+        ExprResult Res =
+          PerformImplicitConversion(From, BeforeToType,
+                                    ICS.UserDefined.Before, AA_Converting,
+                                    CCK);
+        if (Res.isInvalid())
+          return ExprError();
+        From = Res.take();
+      }
+
+      ExprResult CastArg
+        = BuildCXXCastArgument(*this,
+                               From->getLocStart(),
+                               ToType.getNonReferenceType(),
+                               CastKind, cast<CXXMethodDecl>(FD),
+                               ICS.UserDefined.FoundConversionFunction,
+                               ICS.UserDefined.HadMultipleCandidates,
+                               From);
+
+      if (CastArg.isInvalid())
+        return ExprError();
+
+      From = CastArg.take();
+
+      return PerformImplicitConversion(From, ToType, ICS.UserDefined.After,
+                                       AA_Converting, CCK);
+  }
+
+  case ImplicitConversionSequence::AmbiguousConversion:
+    ICS.DiagnoseAmbiguousConversion(*this, From->getExprLoc(),
+                          PDiag(diag::err_typecheck_ambiguous_condition)
+                            << From->getSourceRange());
+     return ExprError();
+
+  case ImplicitConversionSequence::EllipsisConversion:
+    llvm_unreachable("Cannot perform an ellipsis conversion");
+
+  case ImplicitConversionSequence::BadConversion:
+    return ExprError();
+  }
+
+  // Everything went well.
+  return Owned(From);
+}
+
+/// PerformImplicitConversion - Perform an implicit conversion of the
+/// expression From to the type ToType by following the standard
+/// conversion sequence SCS. Returns the converted
+/// expression. Flavor is the context in which we're performing this
+/// conversion, for use in error messages.
+ExprResult
+Sema::PerformImplicitConversion(Expr *From, QualType ToType,
+                                const StandardConversionSequence& SCS,
+                                AssignmentAction Action, 
+                                CheckedConversionKind CCK) {
+  bool CStyle = (CCK == CCK_CStyleCast || CCK == CCK_FunctionalCast);
+  
+  // Overall FIXME: we are recomputing too many types here and doing far too
+  // much extra work. What this means is that we need to keep track of more
+  // information that is computed when we try the implicit conversion initially,
+  // so that we don't need to recompute anything here.
+  QualType FromType = From->getType();
+  
+  if (SCS.CopyConstructor) {
+    // FIXME: When can ToType be a reference type?
+    assert(!ToType->isReferenceType());
+    if (SCS.Second == ICK_Derived_To_Base) {
+      ASTOwningVector<Expr*> ConstructorArgs(*this);
+      if (CompleteConstructorCall(cast<CXXConstructorDecl>(SCS.CopyConstructor),
+                                  MultiExprArg(*this, &From, 1),
+                                  /*FIXME:ConstructLoc*/SourceLocation(),
+                                  ConstructorArgs))
+        return ExprError();
+      return BuildCXXConstructExpr(/*FIXME:ConstructLoc*/SourceLocation(),
+                                   ToType, SCS.CopyConstructor,
+                                   move_arg(ConstructorArgs),
+                                   /*HadMultipleCandidates*/ false,
+                                   /*ZeroInit*/ false,
+                                   CXXConstructExpr::CK_Complete,
+                                   SourceRange());
+    }
+    return BuildCXXConstructExpr(/*FIXME:ConstructLoc*/SourceLocation(),
+                                 ToType, SCS.CopyConstructor,
+                                 MultiExprArg(*this, &From, 1),
+                                 /*HadMultipleCandidates*/ false,
+                                 /*ZeroInit*/ false,
+                                 CXXConstructExpr::CK_Complete,
+                                 SourceRange());
+  }
+
+  // Resolve overloaded function references.
+  if (Context.hasSameType(FromType, Context.OverloadTy)) {
+    DeclAccessPair Found;
+    FunctionDecl *Fn = ResolveAddressOfOverloadedFunction(From, ToType,
+                                                          true, Found);
+    if (!Fn)
+      return ExprError();
+
+    if (DiagnoseUseOfDecl(Fn, From->getLocStart()))
+      return ExprError();
+
+    From = FixOverloadedFunctionReference(From, Found, Fn);
+    FromType = From->getType();
+  }
+
+  // Perform the first implicit conversion.
+  switch (SCS.First) {
+  case ICK_Identity:
+    // Nothing to do.
+    break;
+
+  case ICK_Lvalue_To_Rvalue: {
+    assert(From->getObjectKind() != OK_ObjCProperty);
+    FromType = FromType.getUnqualifiedType();
+    ExprResult FromRes = DefaultLvalueConversion(From);
+    assert(!FromRes.isInvalid() && "Can't perform deduced conversion?!");
+    From = FromRes.take();
+    break;
+  }
+
+  case ICK_Array_To_Pointer:
+    FromType = Context.getArrayDecayedType(FromType);
+    From = ImpCastExprToType(From, FromType, CK_ArrayToPointerDecay, 
+                             VK_RValue, /*BasePath=*/0, CCK).take();
+    break;
+
+  case ICK_Function_To_Pointer:
+    FromType = Context.getPointerType(FromType);
+    From = ImpCastExprToType(From, FromType, CK_FunctionToPointerDecay, 
+                             VK_RValue, /*BasePath=*/0, CCK).take();
+    break;
+
+  default:
+    llvm_unreachable("Improper first standard conversion");
+  }
+
+  // Perform the second implicit conversion
+  switch (SCS.Second) {
+  case ICK_Identity:
+    // If both sides are functions (or pointers/references to them), there could
+    // be incompatible exception declarations.
+    if (CheckExceptionSpecCompatibility(From, ToType))
+      return ExprError();
+    // Nothing else to do.
+    break;
+
+  case ICK_NoReturn_Adjustment:
+    // If both sides are functions (or pointers/references to them), there could
+    // be incompatible exception declarations.
+    if (CheckExceptionSpecCompatibility(From, ToType))
+      return ExprError();
+
+    From = ImpCastExprToType(From, ToType, CK_NoOp, 
+                             VK_RValue, /*BasePath=*/0, CCK).take();
+    break;
+
+  case ICK_Integral_Promotion:
+  case ICK_Integral_Conversion:
+    From = ImpCastExprToType(From, ToType, CK_IntegralCast, 
+                             VK_RValue, /*BasePath=*/0, CCK).take();
+    break;
+
+  case ICK_Floating_Promotion:
+  case ICK_Floating_Conversion:
+    From = ImpCastExprToType(From, ToType, CK_FloatingCast, 
+                             VK_RValue, /*BasePath=*/0, CCK).take();
+    break;
+
+  case ICK_Complex_Promotion:
+  case ICK_Complex_Conversion: {
+    QualType FromEl = From->getType()->getAs<ComplexType>()->getElementType();
+    QualType ToEl = ToType->getAs<ComplexType>()->getElementType();
+    CastKind CK;
+    if (FromEl->isRealFloatingType()) {
+      if (ToEl->isRealFloatingType())
+        CK = CK_FloatingComplexCast;
+      else
+        CK = CK_FloatingComplexToIntegralComplex;
+    } else if (ToEl->isRealFloatingType()) {
+      CK = CK_IntegralComplexToFloatingComplex;
+    } else {
+      CK = CK_IntegralComplexCast;
+    }
+    From = ImpCastExprToType(From, ToType, CK, 
+                             VK_RValue, /*BasePath=*/0, CCK).take();
+    break;
+  }
+
+  case ICK_Floating_Integral:
+    if (ToType->isRealFloatingType())
+      From = ImpCastExprToType(From, ToType, CK_IntegralToFloating, 
+                               VK_RValue, /*BasePath=*/0, CCK).take();
+    else
+      From = ImpCastExprToType(From, ToType, CK_FloatingToIntegral, 
+                               VK_RValue, /*BasePath=*/0, CCK).take();
+    break;
+
+  case ICK_Compatible_Conversion:
+      From = ImpCastExprToType(From, ToType, CK_NoOp, 
+                               VK_RValue, /*BasePath=*/0, CCK).take();
+    break;
+
+  case ICK_Writeback_Conversion:
+  case ICK_Pointer_Conversion: {
+    if (SCS.IncompatibleObjC && Action != AA_Casting) {
+      // Diagnose incompatible Objective-C conversions
+      if (Action == AA_Initializing || Action == AA_Assigning)
+        Diag(From->getLocStart(),
+             diag::ext_typecheck_convert_incompatible_pointer)
+          << ToType << From->getType() << Action
+          << From->getSourceRange() << 0;
+      else
+        Diag(From->getLocStart(),
+             diag::ext_typecheck_convert_incompatible_pointer)
+          << From->getType() << ToType << Action
+          << From->getSourceRange() << 0;
+
+      if (From->getType()->isObjCObjectPointerType() &&
+          ToType->isObjCObjectPointerType())
+        EmitRelatedResultTypeNote(From);
+    } 
+    else if (getLangOpts().ObjCAutoRefCount &&
+             !CheckObjCARCUnavailableWeakConversion(ToType, 
+                                                    From->getType())) {
+      if (Action == AA_Initializing)
+        Diag(From->getLocStart(), 
+             diag::err_arc_weak_unavailable_assign);
+      else
+        Diag(From->getLocStart(),
+             diag::err_arc_convesion_of_weak_unavailable) 
+          << (Action == AA_Casting) << From->getType() << ToType 
+          << From->getSourceRange();
+    }
+             
+    CastKind Kind = CK_Invalid;
+    CXXCastPath BasePath;
+    if (CheckPointerConversion(From, ToType, Kind, BasePath, CStyle))
+      return ExprError();
+
+    // Make sure we extend blocks if necessary.
+    // FIXME: doing this here is really ugly.
+    if (Kind == CK_BlockPointerToObjCPointerCast) {
+      ExprResult E = From;
+      (void) PrepareCastToObjCObjectPointer(E);
+      From = E.take();
+    }
+
+    From = ImpCastExprToType(From, ToType, Kind, VK_RValue, &BasePath, CCK)
+             .take();
+    break;
+  }
+
+  case ICK_Pointer_Member: {
+    CastKind Kind = CK_Invalid;
+    CXXCastPath BasePath;
+    if (CheckMemberPointerConversion(From, ToType, Kind, BasePath, CStyle))
+      return ExprError();
+    if (CheckExceptionSpecCompatibility(From, ToType))
+      return ExprError();
+    From = ImpCastExprToType(From, ToType, Kind, VK_RValue, &BasePath, CCK)
+             .take();
+    break;
+  }
+
+  case ICK_Boolean_Conversion:
+    // Perform half-to-boolean conversion via float.
+    if (From->getType()->isHalfType()) {
+      From = ImpCastExprToType(From, Context.FloatTy, CK_FloatingCast).take();
+      FromType = Context.FloatTy;
+    }
+
+    From = ImpCastExprToType(From, Context.BoolTy,
+                             ScalarTypeToBooleanCastKind(FromType), 
+                             VK_RValue, /*BasePath=*/0, CCK).take();
+    break;
+
+  case ICK_Derived_To_Base: {
+    CXXCastPath BasePath;
+    if (CheckDerivedToBaseConversion(From->getType(),
+                                     ToType.getNonReferenceType(),
+                                     From->getLocStart(),
+                                     From->getSourceRange(),
+                                     &BasePath,
+                                     CStyle))
+      return ExprError();
+
+    From = ImpCastExprToType(From, ToType.getNonReferenceType(),
+                      CK_DerivedToBase, From->getValueKind(),
+                      &BasePath, CCK).take();
+    break;
+  }
+
+  case ICK_Vector_Conversion:
+    From = ImpCastExprToType(From, ToType, CK_BitCast, 
+                             VK_RValue, /*BasePath=*/0, CCK).take();
+    break;
+
+  case ICK_Vector_Splat:
+    From = ImpCastExprToType(From, ToType, CK_VectorSplat, 
+                             VK_RValue, /*BasePath=*/0, CCK).take();
+    break;
+
+  case ICK_Complex_Real:
+    // Case 1.  x -> _Complex y
+    if (const ComplexType *ToComplex = ToType->getAs<ComplexType>()) {
+      QualType ElType = ToComplex->getElementType();
+      bool isFloatingComplex = ElType->isRealFloatingType();
+
+      // x -> y
+      if (Context.hasSameUnqualifiedType(ElType, From->getType())) {
+        // do nothing
+      } else if (From->getType()->isRealFloatingType()) {
+        From = ImpCastExprToType(From, ElType,
+                isFloatingComplex ? CK_FloatingCast : CK_FloatingToIntegral).take();
+      } else {
+        assert(From->getType()->isIntegerType());
+        From = ImpCastExprToType(From, ElType,
+                isFloatingComplex ? CK_IntegralToFloating : CK_IntegralCast).take();
+      }
+      // y -> _Complex y
+      From = ImpCastExprToType(From, ToType,
+                   isFloatingComplex ? CK_FloatingRealToComplex
+                                     : CK_IntegralRealToComplex).take();
+
+    // Case 2.  _Complex x -> y
+    } else {
+      const ComplexType *FromComplex = From->getType()->getAs<ComplexType>();
+      assert(FromComplex);
+
+      QualType ElType = FromComplex->getElementType();
+      bool isFloatingComplex = ElType->isRealFloatingType();
+
+      // _Complex x -> x
+      From = ImpCastExprToType(From, ElType,
+                   isFloatingComplex ? CK_FloatingComplexToReal
+                                     : CK_IntegralComplexToReal, 
+                               VK_RValue, /*BasePath=*/0, CCK).take();
+
+      // x -> y
+      if (Context.hasSameUnqualifiedType(ElType, ToType)) {
+        // do nothing
+      } else if (ToType->isRealFloatingType()) {
+        From = ImpCastExprToType(From, ToType,
+                   isFloatingComplex ? CK_FloatingCast : CK_IntegralToFloating, 
+                                 VK_RValue, /*BasePath=*/0, CCK).take();
+      } else {
+        assert(ToType->isIntegerType());
+        From = ImpCastExprToType(From, ToType,
+                   isFloatingComplex ? CK_FloatingToIntegral : CK_IntegralCast, 
+                                 VK_RValue, /*BasePath=*/0, CCK).take();
+      }
+    }
+    break;
+  
+  case ICK_Block_Pointer_Conversion: {
+    From = ImpCastExprToType(From, ToType.getUnqualifiedType(), CK_BitCast,
+                             VK_RValue, /*BasePath=*/0, CCK).take();
+    break;
+  }
+      
+  case ICK_TransparentUnionConversion: {
+    ExprResult FromRes = Owned(From);
+    Sema::AssignConvertType ConvTy =
+      CheckTransparentUnionArgumentConstraints(ToType, FromRes);
+    if (FromRes.isInvalid())
+      return ExprError();
+    From = FromRes.take();
+    assert ((ConvTy == Sema::Compatible) &&
+            "Improper transparent union conversion");
+    (void)ConvTy;
+    break;
+  }
+
+  case ICK_Lvalue_To_Rvalue:
+  case ICK_Array_To_Pointer:
+  case ICK_Function_To_Pointer:
+  case ICK_Qualification:
+  case ICK_Num_Conversion_Kinds:
+    llvm_unreachable("Improper second standard conversion");
+  }
+
+  switch (SCS.Third) {
+  case ICK_Identity:
+    // Nothing to do.
+    break;
+
+  case ICK_Qualification: {
+    // The qualification keeps the category of the inner expression, unless the
+    // target type isn't a reference.
+    ExprValueKind VK = ToType->isReferenceType() ?
+                                  From->getValueKind() : VK_RValue;
+    From = ImpCastExprToType(From, ToType.getNonLValueExprType(Context),
+                             CK_NoOp, VK, /*BasePath=*/0, CCK).take();
+
+    if (SCS.DeprecatedStringLiteralToCharPtr &&
+        !getLangOpts().WritableStrings)
+      Diag(From->getLocStart(), diag::warn_deprecated_string_literal_conversion)
+        << ToType.getNonReferenceType();
+
+    break;
+    }
+
+  default:
+    llvm_unreachable("Improper third standard conversion");
+  }
+
+  // If this conversion sequence involved a scalar -> atomic conversion, perform
+  // that conversion now.
+  if (const AtomicType *ToAtomic = ToType->getAs<AtomicType>())
+    if (Context.hasSameType(ToAtomic->getValueType(), From->getType()))
+      From = ImpCastExprToType(From, ToType, CK_NonAtomicToAtomic, VK_RValue, 0,
+                               CCK).take();
+      
+  return Owned(From);
+}
+
+ExprResult Sema::ActOnUnaryTypeTrait(UnaryTypeTrait UTT,
+                                     SourceLocation KWLoc,
+                                     ParsedType Ty,
+                                     SourceLocation RParen) {
+  TypeSourceInfo *TSInfo;
+  QualType T = GetTypeFromParser(Ty, &TSInfo);
+
+  if (!TSInfo)
+    TSInfo = Context.getTrivialTypeSourceInfo(T);
+  return BuildUnaryTypeTrait(UTT, KWLoc, TSInfo, RParen);
+}
+
+/// \brief Check the completeness of a type in a unary type trait.
+///
+/// If the particular type trait requires a complete type, tries to complete
+/// it. If completing the type fails, a diagnostic is emitted and false
+/// returned. If completing the type succeeds or no completion was required,
+/// returns true.
+static bool CheckUnaryTypeTraitTypeCompleteness(Sema &S,
+                                                UnaryTypeTrait UTT,
+                                                SourceLocation Loc,
+                                                QualType ArgTy) {
+  // C++0x [meta.unary.prop]p3:
+  //   For all of the class templates X declared in this Clause, instantiating
+  //   that template with a template argument that is a class template
+  //   specialization may result in the implicit instantiation of the template
+  //   argument if and only if the semantics of X require that the argument
+  //   must be a complete type.
+  // We apply this rule to all the type trait expressions used to implement
+  // these class templates. We also try to follow any GCC documented behavior
+  // in these expressions to ensure portability of standard libraries.
+  switch (UTT) {
+    // is_complete_type somewhat obviously cannot require a complete type.
+  case UTT_IsCompleteType:
+    // Fall-through
+
+    // These traits are modeled on the type predicates in C++0x
+    // [meta.unary.cat] and [meta.unary.comp]. They are not specified as
+    // requiring a complete type, as whether or not they return true cannot be
+    // impacted by the completeness of the type.
+  case UTT_IsVoid:
+  case UTT_IsIntegral:
+  case UTT_IsFloatingPoint:
+  case UTT_IsArray:
+  case UTT_IsPointer:
+  case UTT_IsLvalueReference:
+  case UTT_IsRvalueReference:
+  case UTT_IsMemberFunctionPointer:
+  case UTT_IsMemberObjectPointer:
+  case UTT_IsEnum:
+  case UTT_IsUnion:
+  case UTT_IsClass:
+  case UTT_IsFunction:
+  case UTT_IsReference:
+  case UTT_IsArithmetic:
+  case UTT_IsFundamental:
+  case UTT_IsObject:
+  case UTT_IsScalar:
+  case UTT_IsCompound:
+  case UTT_IsMemberPointer:
+    // Fall-through
+
+    // These traits are modeled on type predicates in C++0x [meta.unary.prop]
+    // which requires some of its traits to have the complete type. However,
+    // the completeness of the type cannot impact these traits' semantics, and
+    // so they don't require it. This matches the comments on these traits in
+    // Table 49.
+  case UTT_IsConst:
+  case UTT_IsVolatile:
+  case UTT_IsSigned:
+  case UTT_IsUnsigned:
+    return true;
+
+    // C++0x [meta.unary.prop] Table 49 requires the following traits to be
+    // applied to a complete type.
+  case UTT_IsTrivial:
+  case UTT_IsTriviallyCopyable:
+  case UTT_IsStandardLayout:
+  case UTT_IsPOD:
+  case UTT_IsLiteral:
+  case UTT_IsEmpty:
+  case UTT_IsPolymorphic:
+  case UTT_IsAbstract:
+    // Fall-through
+
+  // These traits require a complete type.
+  case UTT_IsFinal:
+
+    // These trait expressions are designed to help implement predicates in
+    // [meta.unary.prop] despite not being named the same. They are specified
+    // by both GCC and the Embarcadero C++ compiler, and require the complete
+    // type due to the overarching C++0x type predicates being implemented
+    // requiring the complete type.
+  case UTT_HasNothrowAssign:
+  case UTT_HasNothrowConstructor:
+  case UTT_HasNothrowCopy:
+  case UTT_HasTrivialAssign:
+  case UTT_HasTrivialDefaultConstructor:
+  case UTT_HasTrivialCopy:
+  case UTT_HasTrivialDestructor:
+  case UTT_HasVirtualDestructor:
+    // Arrays of unknown bound are expressly allowed.
+    QualType ElTy = ArgTy;
+    if (ArgTy->isIncompleteArrayType())
+      ElTy = S.Context.getAsArrayType(ArgTy)->getElementType();
+
+    // The void type is expressly allowed.
+    if (ElTy->isVoidType())
+      return true;
+
+    return !S.RequireCompleteType(
+      Loc, ElTy, diag::err_incomplete_type_used_in_type_trait_expr);
+  }
+  llvm_unreachable("Type trait not handled by switch");
+}
+
+static bool EvaluateUnaryTypeTrait(Sema &Self, UnaryTypeTrait UTT,
+                                   SourceLocation KeyLoc, QualType T) {
+  assert(!T->isDependentType() && "Cannot evaluate traits of dependent type");
+
+  ASTContext &C = Self.Context;
+  switch(UTT) {
+    // Type trait expressions corresponding to the primary type category
+    // predicates in C++0x [meta.unary.cat].
+  case UTT_IsVoid:
+    return T->isVoidType();
+  case UTT_IsIntegral:
+    return T->isIntegralType(C);
+  case UTT_IsFloatingPoint:
+    return T->isFloatingType();
+  case UTT_IsArray:
+    return T->isArrayType();
+  case UTT_IsPointer:
+    return T->isPointerType();
+  case UTT_IsLvalueReference:
+    return T->isLValueReferenceType();
+  case UTT_IsRvalueReference:
+    return T->isRValueReferenceType();
+  case UTT_IsMemberFunctionPointer:
+    return T->isMemberFunctionPointerType();
+  case UTT_IsMemberObjectPointer:
+    return T->isMemberDataPointerType();
+  case UTT_IsEnum:
+    return T->isEnumeralType();
+  case UTT_IsUnion:
+    return T->isUnionType();
+  case UTT_IsClass:
+    return T->isClassType() || T->isStructureType();
+  case UTT_IsFunction:
+    return T->isFunctionType();
+
+    // Type trait expressions which correspond to the convenient composition
+    // predicates in C++0x [meta.unary.comp].
+  case UTT_IsReference:
+    return T->isReferenceType();
+  case UTT_IsArithmetic:
+    return T->isArithmeticType() && !T->isEnumeralType();
+  case UTT_IsFundamental:
+    return T->isFundamentalType();
+  case UTT_IsObject:
+    return T->isObjectType();
+  case UTT_IsScalar:
+    // Note: semantic analysis depends on Objective-C lifetime types to be
+    // considered scalar types. However, such types do not actually behave
+    // like scalar types at run time (since they may require retain/release
+    // operations), so we report them as non-scalar.
+    if (T->isObjCLifetimeType()) {
+      switch (T.getObjCLifetime()) {
+      case Qualifiers::OCL_None:
+      case Qualifiers::OCL_ExplicitNone:
+        return true;
+
+      case Qualifiers::OCL_Strong:
+      case Qualifiers::OCL_Weak:
+      case Qualifiers::OCL_Autoreleasing:
+        return false;
+      }
+    }
+      
+    return T->isScalarType();
+  case UTT_IsCompound:
+    return T->isCompoundType();
+  case UTT_IsMemberPointer:
+    return T->isMemberPointerType();
+
+    // Type trait expressions which correspond to the type property predicates
+    // in C++0x [meta.unary.prop].
+  case UTT_IsConst:
+    return T.isConstQualified();
+  case UTT_IsVolatile:
+    return T.isVolatileQualified();
+  case UTT_IsTrivial:
+    return T.isTrivialType(Self.Context);
+  case UTT_IsTriviallyCopyable:
+    return T.isTriviallyCopyableType(Self.Context);
+  case UTT_IsStandardLayout:
+    return T->isStandardLayoutType();
+  case UTT_IsPOD:
+    return T.isPODType(Self.Context);
+  case UTT_IsLiteral:
+    return T->isLiteralType();
+  case UTT_IsEmpty:
+    if (const CXXRecordDecl *RD = T->getAsCXXRecordDecl())
+      return !RD->isUnion() && RD->isEmpty();
+    return false;
+  case UTT_IsPolymorphic:
+    if (const CXXRecordDecl *RD = T->getAsCXXRecordDecl())
+      return RD->isPolymorphic();
+    return false;
+  case UTT_IsAbstract:
+    if (const CXXRecordDecl *RD = T->getAsCXXRecordDecl())
+      return RD->isAbstract();
+    return false;
+  case UTT_IsFinal:
+    if (const CXXRecordDecl *RD = T->getAsCXXRecordDecl())
+      return RD->hasAttr<FinalAttr>();
+    return false;
+  case UTT_IsSigned:
+    return T->isSignedIntegerType();
+  case UTT_IsUnsigned:
+    return T->isUnsignedIntegerType();
+
+    // Type trait expressions which query classes regarding their construction,
+    // destruction, and copying. Rather than being based directly on the
+    // related type predicates in the standard, they are specified by both
+    // GCC[1] and the Embarcadero C++ compiler[2], and Clang implements those
+    // specifications.
+    //
+    //   1: http://gcc.gnu/.org/onlinedocs/gcc/Type-Traits.html
+    //   2: http://docwiki.embarcadero.com/RADStudio/XE/en/Type_Trait_Functions_(C%2B%2B0x)_Index
+  case UTT_HasTrivialDefaultConstructor:
+    // http://gcc.gnu.org/onlinedocs/gcc/Type-Traits.html:
+    //   If __is_pod (type) is true then the trait is true, else if type is
+    //   a cv class or union type (or array thereof) with a trivial default
+    //   constructor ([class.ctor]) then the trait is true, else it is false.
+    if (T.isPODType(Self.Context))
+      return true;
+    if (const RecordType *RT =
+          C.getBaseElementType(T)->getAs<RecordType>())
+      return cast<CXXRecordDecl>(RT->getDecl())->hasTrivialDefaultConstructor();
+    return false;
+  case UTT_HasTrivialCopy:
+    // http://gcc.gnu.org/onlinedocs/gcc/Type-Traits.html:
+    //   If __is_pod (type) is true or type is a reference type then
+    //   the trait is true, else if type is a cv class or union type
+    //   with a trivial copy constructor ([class.copy]) then the trait
+    //   is true, else it is false.
+    if (T.isPODType(Self.Context) || T->isReferenceType())
+      return true;
+    if (const RecordType *RT = T->getAs<RecordType>())
+      return cast<CXXRecordDecl>(RT->getDecl())->hasTrivialCopyConstructor();
+    return false;
+  case UTT_HasTrivialAssign:
+    // http://gcc.gnu.org/onlinedocs/gcc/Type-Traits.html:
+    //   If type is const qualified or is a reference type then the
+    //   trait is false. Otherwise if __is_pod (type) is true then the
+    //   trait is true, else if type is a cv class or union type with
+    //   a trivial copy assignment ([class.copy]) then the trait is
+    //   true, else it is false.
+    // Note: the const and reference restrictions are interesting,
+    // given that const and reference members don't prevent a class
+    // from having a trivial copy assignment operator (but do cause
+    // errors if the copy assignment operator is actually used, q.v.
+    // [class.copy]p12).
+
+    if (C.getBaseElementType(T).isConstQualified())
+      return false;
+    if (T.isPODType(Self.Context))
+      return true;
+    if (const RecordType *RT = T->getAs<RecordType>())
+      return cast<CXXRecordDecl>(RT->getDecl())->hasTrivialCopyAssignment();
+    return false;
+  case UTT_HasTrivialDestructor:
+    // http://gcc.gnu.org/onlinedocs/gcc/Type-Traits.html:
+    //   If __is_pod (type) is true or type is a reference type
+    //   then the trait is true, else if type is a cv class or union
+    //   type (or array thereof) with a trivial destructor
+    //   ([class.dtor]) then the trait is true, else it is
+    //   false.
+    if (T.isPODType(Self.Context) || T->isReferenceType())
+      return true;
+      
+    // Objective-C++ ARC: autorelease types don't require destruction.
+    if (T->isObjCLifetimeType() && 
+        T.getObjCLifetime() == Qualifiers::OCL_Autoreleasing)
+      return true;
+      
+    if (const RecordType *RT =
+          C.getBaseElementType(T)->getAs<RecordType>())
+      return cast<CXXRecordDecl>(RT->getDecl())->hasTrivialDestructor();
+    return false;
+  // TODO: Propagate nothrowness for implicitly declared special members.
+  case UTT_HasNothrowAssign:
+    // http://gcc.gnu.org/onlinedocs/gcc/Type-Traits.html:
+    //   If type is const qualified or is a reference type then the
+    //   trait is false. Otherwise if __has_trivial_assign (type)
+    //   is true then the trait is true, else if type is a cv class
+    //   or union type with copy assignment operators that are known
+    //   not to throw an exception then the trait is true, else it is
+    //   false.
+    if (C.getBaseElementType(T).isConstQualified())
+      return false;
+    if (T->isReferenceType())
+      return false;
+    if (T.isPODType(Self.Context) || T->isObjCLifetimeType())
+      return true;     
+    if (const RecordType *RT = T->getAs<RecordType>()) {
+      CXXRecordDecl* RD = cast<CXXRecordDecl>(RT->getDecl());
+      if (RD->hasTrivialCopyAssignment())
+        return true;
+
+      bool FoundAssign = false;
+      DeclarationName Name = C.DeclarationNames.getCXXOperatorName(OO_Equal);
+      LookupResult Res(Self, DeclarationNameInfo(Name, KeyLoc),
+                       Sema::LookupOrdinaryName);
+      if (Self.LookupQualifiedName(Res, RD)) {
+        Res.suppressDiagnostics();
+        for (LookupResult::iterator Op = Res.begin(), OpEnd = Res.end();
+             Op != OpEnd; ++Op) {
+          if (isa<FunctionTemplateDecl>(*Op))
+            continue;
+          
+          CXXMethodDecl *Operator = cast<CXXMethodDecl>(*Op);
+          if (Operator->isCopyAssignmentOperator()) {
+            FoundAssign = true;
+            const FunctionProtoType *CPT
+                = Operator->getType()->getAs<FunctionProtoType>();
+            CPT = Self.ResolveExceptionSpec(KeyLoc, CPT);
+            if (!CPT)
+              return false;
+            if (CPT->getExceptionSpecType() == EST_Delayed)
+              return false;
+            if (!CPT->isNothrow(Self.Context))
+              return false;
+          }
+        }
+      }
+      
+      return FoundAssign;
+    }
+    return false;
+  case UTT_HasNothrowCopy:
+    // http://gcc.gnu.org/onlinedocs/gcc/Type-Traits.html:
+    //   If __has_trivial_copy (type) is true then the trait is true, else
+    //   if type is a cv class or union type with copy constructors that are
+    //   known not to throw an exception then the trait is true, else it is
+    //   false.
+    if (T.isPODType(C) || T->isReferenceType() || T->isObjCLifetimeType())
+      return true;
+    if (const RecordType *RT = T->getAs<RecordType>()) {
+      CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
+      if (RD->hasTrivialCopyConstructor())
+        return true;
+
+      bool FoundConstructor = false;
+      unsigned FoundTQs;
+      DeclContext::lookup_const_iterator Con, ConEnd;
+      for (llvm::tie(Con, ConEnd) = Self.LookupConstructors(RD);
+           Con != ConEnd; ++Con) {
+        // A template constructor is never a copy constructor.
+        // FIXME: However, it may actually be selected at the actual overload
+        // resolution point.
+        if (isa<FunctionTemplateDecl>(*Con))
+          continue;
+        CXXConstructorDecl *Constructor = cast<CXXConstructorDecl>(*Con);
+        if (Constructor->isCopyConstructor(FoundTQs)) {
+          FoundConstructor = true;
+          const FunctionProtoType *CPT
+              = Constructor->getType()->getAs<FunctionProtoType>();
+          CPT = Self.ResolveExceptionSpec(KeyLoc, CPT);
+          if (!CPT)
+            return false;
+          if (CPT->getExceptionSpecType() == EST_Delayed)
+            return false;
+          // FIXME: check whether evaluating default arguments can throw.
+          // For now, we'll be conservative and assume that they can throw.
+          if (!CPT->isNothrow(Self.Context) || CPT->getNumArgs() > 1)
+            return false;
+        }
+      }
+
+      return FoundConstructor;
+    }
+    return false;
+  case UTT_HasNothrowConstructor:
+    // http://gcc.gnu.org/onlinedocs/gcc/Type-Traits.html:
+    //   If __has_trivial_constructor (type) is true then the trait is
+    //   true, else if type is a cv class or union type (or array
+    //   thereof) with a default constructor that is known not to
+    //   throw an exception then the trait is true, else it is false.
+    if (T.isPODType(C) || T->isObjCLifetimeType())
+      return true;
+    if (const RecordType *RT = C.getBaseElementType(T)->getAs<RecordType>()) {
+      CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
+      if (RD->hasTrivialDefaultConstructor())
+        return true;
+
+      DeclContext::lookup_const_iterator Con, ConEnd;
+      for (llvm::tie(Con, ConEnd) = Self.LookupConstructors(RD);
+           Con != ConEnd; ++Con) {
+        // FIXME: In C++0x, a constructor template can be a default constructor.
+        if (isa<FunctionTemplateDecl>(*Con))
+          continue;
+        CXXConstructorDecl *Constructor = cast<CXXConstructorDecl>(*Con);
+        if (Constructor->isDefaultConstructor()) {
+          const FunctionProtoType *CPT
+              = Constructor->getType()->getAs<FunctionProtoType>();
+          CPT = Self.ResolveExceptionSpec(KeyLoc, CPT);
+          if (!CPT)
+            return false;
+          if (CPT->getExceptionSpecType() == EST_Delayed)
+            return false;
+          // TODO: check whether evaluating default arguments can throw.
+          // For now, we'll be conservative and assume that they can throw.
+          return CPT->isNothrow(Self.Context) && CPT->getNumArgs() == 0;
+        }
+      }
+    }
+    return false;
+  case UTT_HasVirtualDestructor:
+    // http://gcc.gnu.org/onlinedocs/gcc/Type-Traits.html:
+    //   If type is a class type with a virtual destructor ([class.dtor])
+    //   then the trait is true, else it is false.
+    if (const RecordType *Record = T->getAs<RecordType>()) {
+      CXXRecordDecl *RD = cast<CXXRecordDecl>(Record->getDecl());
+      if (CXXDestructorDecl *Destructor = Self.LookupDestructor(RD))
+        return Destructor->isVirtual();
+    }
+    return false;
+
+    // These type trait expressions are modeled on the specifications for the
+    // Embarcadero C++0x type trait functions:
+    //   http://docwiki.embarcadero.com/RADStudio/XE/en/Type_Trait_Functions_(C%2B%2B0x)_Index
+  case UTT_IsCompleteType:
+    // http://docwiki.embarcadero.com/RADStudio/XE/en/Is_complete_type_(typename_T_):
+    //   Returns True if and only if T is a complete type at the point of the
+    //   function call.
+    return !T->isIncompleteType();
+  }
+  llvm_unreachable("Type trait not covered by switch");
+}
+
+ExprResult Sema::BuildUnaryTypeTrait(UnaryTypeTrait UTT,
+                                     SourceLocation KWLoc,
+                                     TypeSourceInfo *TSInfo,
+                                     SourceLocation RParen) {
+  QualType T = TSInfo->getType();
+  if (!CheckUnaryTypeTraitTypeCompleteness(*this, UTT, KWLoc, T))
+    return ExprError();
+
+  bool Value = false;
+  if (!T->isDependentType())
+    Value = EvaluateUnaryTypeTrait(*this, UTT, KWLoc, T);
+
+  return Owned(new (Context) UnaryTypeTraitExpr(KWLoc, UTT, TSInfo, Value,
+                                                RParen, Context.BoolTy));
+}
+
+ExprResult Sema::ActOnBinaryTypeTrait(BinaryTypeTrait BTT,
+                                      SourceLocation KWLoc,
+                                      ParsedType LhsTy,
+                                      ParsedType RhsTy,
+                                      SourceLocation RParen) {
+  TypeSourceInfo *LhsTSInfo;
+  QualType LhsT = GetTypeFromParser(LhsTy, &LhsTSInfo);
+  if (!LhsTSInfo)
+    LhsTSInfo = Context.getTrivialTypeSourceInfo(LhsT);
+
+  TypeSourceInfo *RhsTSInfo;
+  QualType RhsT = GetTypeFromParser(RhsTy, &RhsTSInfo);
+  if (!RhsTSInfo)
+    RhsTSInfo = Context.getTrivialTypeSourceInfo(RhsT);
+
+  return BuildBinaryTypeTrait(BTT, KWLoc, LhsTSInfo, RhsTSInfo, RParen);
+}
+
+static bool evaluateTypeTrait(Sema &S, TypeTrait Kind, SourceLocation KWLoc,
+                              ArrayRef<TypeSourceInfo *> Args,
+                              SourceLocation RParenLoc) {
+  switch (Kind) {
+  case clang::TT_IsTriviallyConstructible: {
+    // C++11 [meta.unary.prop]:
+    //   is_trivially_constructible is defined as:
+    //
+    //     is_constructible<T, Args...>::value is true and the variable
+    //     definition for is_constructible, as defined below, is known to call no
+    //     operation that is not trivial.
+    //
+    //   The predicate condition for a template specialization 
+    //   is_constructible<T, Args...> shall be satisfied if and only if the 
+    //   following variable definition would be well-formed for some invented 
+    //   variable t:
+    //
+    //     T t(create<Args>()...);
+    if (Args.empty()) {
+      S.Diag(KWLoc, diag::err_type_trait_arity)
+        << 1 << 1 << 1 << (int)Args.size();
+      return false;
+    }
+    
+    bool SawVoid = false;
+    for (unsigned I = 0, N = Args.size(); I != N; ++I) {
+      if (Args[I]->getType()->isVoidType()) {
+        SawVoid = true;
+        continue;
+      }
+      
+      if (!Args[I]->getType()->isIncompleteType() &&
+        S.RequireCompleteType(KWLoc, Args[I]->getType(), 
+          diag::err_incomplete_type_used_in_type_trait_expr))
+        return false;
+    }
+    
+    // If any argument was 'void', of course it won't type-check.
+    if (SawVoid)
+      return false;
+    
+    llvm::SmallVector<OpaqueValueExpr, 2> OpaqueArgExprs;
+    llvm::SmallVector<Expr *, 2> ArgExprs;
+    ArgExprs.reserve(Args.size() - 1);
+    for (unsigned I = 1, N = Args.size(); I != N; ++I) {
+      QualType T = Args[I]->getType();
+      if (T->isObjectType() || T->isFunctionType())
+        T = S.Context.getRValueReferenceType(T);
+      OpaqueArgExprs.push_back(
+        OpaqueValueExpr(Args[I]->getTypeLoc().getLocStart(), 
+                        T.getNonLValueExprType(S.Context),
+                        Expr::getValueKindForType(T)));
+      ArgExprs.push_back(&OpaqueArgExprs.back());
+    }
+    
+    // Perform the initialization in an unevaluated context within a SFINAE 
+    // trap at translation unit scope.
+    EnterExpressionEvaluationContext Unevaluated(S, Sema::Unevaluated);
+    Sema::SFINAETrap SFINAE(S, /*AccessCheckingSFINAE=*/true);
+    Sema::ContextRAII TUContext(S, S.Context.getTranslationUnitDecl());
+    InitializedEntity To(InitializedEntity::InitializeTemporary(Args[0]));
+    InitializationKind InitKind(InitializationKind::CreateDirect(KWLoc, KWLoc,
+                                                                 RParenLoc));
+    InitializationSequence Init(S, To, InitKind, 
+                                ArgExprs.begin(), ArgExprs.size());
+    if (Init.Failed())
+      return false;
+    
+    ExprResult Result = Init.Perform(S, To, InitKind, 
+                                     MultiExprArg(ArgExprs.data(), 
+                                                  ArgExprs.size()));
+    if (Result.isInvalid() || SFINAE.hasErrorOccurred())
+      return false;
+    
+    // The initialization succeeded; not make sure there are no non-trivial 
+    // calls.
+    return !Result.get()->hasNonTrivialCall(S.Context);
+  }
+  }
+  
+  return false;
+}
+
+ExprResult Sema::BuildTypeTrait(TypeTrait Kind, SourceLocation KWLoc, 
+                                ArrayRef<TypeSourceInfo *> Args, 
+                                SourceLocation RParenLoc) {
+  bool Dependent = false;
+  for (unsigned I = 0, N = Args.size(); I != N; ++I) {
+    if (Args[I]->getType()->isDependentType()) {
+      Dependent = true;
+      break;
+    }
+  }
+  
+  bool Value = false;
+  if (!Dependent)
+    Value = evaluateTypeTrait(*this, Kind, KWLoc, Args, RParenLoc);
+  
+  return TypeTraitExpr::Create(Context, Context.BoolTy, KWLoc, Kind,
+                               Args, RParenLoc, Value);
+}
+
+ExprResult Sema::ActOnTypeTrait(TypeTrait Kind, SourceLocation KWLoc, 
+                                ArrayRef<ParsedType> Args, 
+                                SourceLocation RParenLoc) {
+  llvm::SmallVector<TypeSourceInfo *, 4> ConvertedArgs;
+  ConvertedArgs.reserve(Args.size());
+  
+  for (unsigned I = 0, N = Args.size(); I != N; ++I) {
+    TypeSourceInfo *TInfo;
+    QualType T = GetTypeFromParser(Args[I], &TInfo);
+    if (!TInfo)
+      TInfo = Context.getTrivialTypeSourceInfo(T, KWLoc);
+    
+    ConvertedArgs.push_back(TInfo);    
+  }
+  
+  return BuildTypeTrait(Kind, KWLoc, ConvertedArgs, RParenLoc);
+}
+
+static bool EvaluateBinaryTypeTrait(Sema &Self, BinaryTypeTrait BTT,
+                                    QualType LhsT, QualType RhsT,
+                                    SourceLocation KeyLoc) {
+  assert(!LhsT->isDependentType() && !RhsT->isDependentType() &&
+         "Cannot evaluate traits of dependent types");
+
+  switch(BTT) {
+  case BTT_IsBaseOf: {
+    // C++0x [meta.rel]p2
+    // Base is a base class of Derived without regard to cv-qualifiers or
+    // Base and Derived are not unions and name the same class type without
+    // regard to cv-qualifiers.
+
+    const RecordType *lhsRecord = LhsT->getAs<RecordType>();
+    if (!lhsRecord) return false;
+
+    const RecordType *rhsRecord = RhsT->getAs<RecordType>();
+    if (!rhsRecord) return false;
+
+    assert(Self.Context.hasSameUnqualifiedType(LhsT, RhsT)
+             == (lhsRecord == rhsRecord));
+
+    if (lhsRecord == rhsRecord)
+      return !lhsRecord->getDecl()->isUnion();
+
+    // C++0x [meta.rel]p2:
+    //   If Base and Derived are class types and are different types
+    //   (ignoring possible cv-qualifiers) then Derived shall be a
+    //   complete type.
+    if (Self.RequireCompleteType(KeyLoc, RhsT, 
+                          diag::err_incomplete_type_used_in_type_trait_expr))
+      return false;
+
+    return cast<CXXRecordDecl>(rhsRecord->getDecl())
+      ->isDerivedFrom(cast<CXXRecordDecl>(lhsRecord->getDecl()));
+  }
+  case BTT_IsSame:
+    return Self.Context.hasSameType(LhsT, RhsT);
+  case BTT_TypeCompatible:
+    return Self.Context.typesAreCompatible(LhsT.getUnqualifiedType(),
+                                           RhsT.getUnqualifiedType());
+  case BTT_IsConvertible:
+  case BTT_IsConvertibleTo: {
+    // C++0x [meta.rel]p4:
+    //   Given the following function prototype:
+    //
+    //     template <class T> 
+    //       typename add_rvalue_reference<T>::type create();
+    //
+    //   the predicate condition for a template specialization 
+    //   is_convertible<From, To> shall be satisfied if and only if 
+    //   the return expression in the following code would be 
+    //   well-formed, including any implicit conversions to the return
+    //   type of the function:
+    //
+    //     To test() { 
+    //       return create<From>();
+    //     }
+    //
+    //   Access checking is performed as if in a context unrelated to To and 
+    //   From. Only the validity of the immediate context of the expression 
+    //   of the return-statement (including conversions to the return type)
+    //   is considered.
+    //
+    // We model the initialization as a copy-initialization of a temporary
+    // of the appropriate type, which for this expression is identical to the
+    // return statement (since NRVO doesn't apply).
+    if (LhsT->isObjectType() || LhsT->isFunctionType())
+      LhsT = Self.Context.getRValueReferenceType(LhsT);
+    
+    InitializedEntity To(InitializedEntity::InitializeTemporary(RhsT));
+    OpaqueValueExpr From(KeyLoc, LhsT.getNonLValueExprType(Self.Context),
+                         Expr::getValueKindForType(LhsT));
+    Expr *FromPtr = &From;
+    InitializationKind Kind(InitializationKind::CreateCopy(KeyLoc, 
+                                                           SourceLocation()));
+    
+    // Perform the initialization in an unevaluated context within a SFINAE 
+    // trap at translation unit scope.
+    EnterExpressionEvaluationContext Unevaluated(Self, Sema::Unevaluated);
+    Sema::SFINAETrap SFINAE(Self, /*AccessCheckingSFINAE=*/true);
+    Sema::ContextRAII TUContext(Self, Self.Context.getTranslationUnitDecl());
+    InitializationSequence Init(Self, To, Kind, &FromPtr, 1);
+    if (Init.Failed())
+      return false;
+
+    ExprResult Result = Init.Perform(Self, To, Kind, MultiExprArg(&FromPtr, 1));
+    return !Result.isInvalid() && !SFINAE.hasErrorOccurred();
+  }
+      
+  case BTT_IsTriviallyAssignable: {
+    // C++11 [meta.unary.prop]p3:
+    //   is_trivially_assignable is defined as:
+    //     is_assignable<T, U>::value is true and the assignment, as defined by
+    //     is_assignable, is known to call no operation that is not trivial
+    //
+    //   is_assignable is defined as:
+    //     The expression declval<T>() = declval<U>() is well-formed when 
+    //     treated as an unevaluated operand (Clause 5).
+    //
+    //   For both, T and U shall be complete types, (possibly cv-qualified) 
+    //   void, or arrays of unknown bound.
+    if (!LhsT->isVoidType() && !LhsT->isIncompleteArrayType() &&
+        Self.RequireCompleteType(KeyLoc, LhsT, 
+          diag::err_incomplete_type_used_in_type_trait_expr))
+      return false;
+    if (!RhsT->isVoidType() && !RhsT->isIncompleteArrayType() &&
+        Self.RequireCompleteType(KeyLoc, RhsT, 
+          diag::err_incomplete_type_used_in_type_trait_expr))
+      return false;
+
+    // cv void is never assignable.
+    if (LhsT->isVoidType() || RhsT->isVoidType())
+      return false;
+
+    // Build expressions that emulate the effect of declval<T>() and 
+    // declval<U>().
+    if (LhsT->isObjectType() || LhsT->isFunctionType())
+      LhsT = Self.Context.getRValueReferenceType(LhsT);
+    if (RhsT->isObjectType() || RhsT->isFunctionType())
+      RhsT = Self.Context.getRValueReferenceType(RhsT);
+    OpaqueValueExpr Lhs(KeyLoc, LhsT.getNonLValueExprType(Self.Context),
+                        Expr::getValueKindForType(LhsT));
+    OpaqueValueExpr Rhs(KeyLoc, RhsT.getNonLValueExprType(Self.Context),
+                        Expr::getValueKindForType(RhsT));
+    
+    // Attempt the assignment in an unevaluated context within a SFINAE 
+    // trap at translation unit scope.
+    EnterExpressionEvaluationContext Unevaluated(Self, Sema::Unevaluated);
+    Sema::SFINAETrap SFINAE(Self, /*AccessCheckingSFINAE=*/true);
+    Sema::ContextRAII TUContext(Self, Self.Context.getTranslationUnitDecl());
+    ExprResult Result = Self.BuildBinOp(/*S=*/0, KeyLoc, BO_Assign, &Lhs, &Rhs);
+    if (Result.isInvalid() || SFINAE.hasErrorOccurred())
+      return false;
+
+    return !Result.get()->hasNonTrivialCall(Self.Context);
+  }
+  }
+  llvm_unreachable("Unknown type trait or not implemented");
+}
+
+ExprResult Sema::BuildBinaryTypeTrait(BinaryTypeTrait BTT,
+                                      SourceLocation KWLoc,
+                                      TypeSourceInfo *LhsTSInfo,
+                                      TypeSourceInfo *RhsTSInfo,
+                                      SourceLocation RParen) {
+  QualType LhsT = LhsTSInfo->getType();
+  QualType RhsT = RhsTSInfo->getType();
+
+  if (BTT == BTT_TypeCompatible) {
+    if (getLangOpts().CPlusPlus) {
+      Diag(KWLoc, diag::err_types_compatible_p_in_cplusplus)
+        << SourceRange(KWLoc, RParen);
+      return ExprError();
+    }
+  }
+
+  bool Value = false;
+  if (!LhsT->isDependentType() && !RhsT->isDependentType())
+    Value = EvaluateBinaryTypeTrait(*this, BTT, LhsT, RhsT, KWLoc);
+
+  // Select trait result type.
+  QualType ResultType;
+  switch (BTT) {
+  case BTT_IsBaseOf:       ResultType = Context.BoolTy; break;
+  case BTT_IsConvertible:  ResultType = Context.BoolTy; break;
+  case BTT_IsSame:         ResultType = Context.BoolTy; break;
+  case BTT_TypeCompatible: ResultType = Context.IntTy; break;
+  case BTT_IsConvertibleTo: ResultType = Context.BoolTy; break;
+  case BTT_IsTriviallyAssignable: ResultType = Context.BoolTy;
+  }
+
+  return Owned(new (Context) BinaryTypeTraitExpr(KWLoc, BTT, LhsTSInfo,
+                                                 RhsTSInfo, Value, RParen,
+                                                 ResultType));
+}
+
+ExprResult Sema::ActOnArrayTypeTrait(ArrayTypeTrait ATT,
+                                     SourceLocation KWLoc,
+                                     ParsedType Ty,
+                                     Expr* DimExpr,
+                                     SourceLocation RParen) {
+  TypeSourceInfo *TSInfo;
+  QualType T = GetTypeFromParser(Ty, &TSInfo);
+  if (!TSInfo)
+    TSInfo = Context.getTrivialTypeSourceInfo(T);
+
+  return BuildArrayTypeTrait(ATT, KWLoc, TSInfo, DimExpr, RParen);
+}
+
+static uint64_t EvaluateArrayTypeTrait(Sema &Self, ArrayTypeTrait ATT,
+                                           QualType T, Expr *DimExpr,
+                                           SourceLocation KeyLoc) {
+  assert(!T->isDependentType() && "Cannot evaluate traits of dependent type");
+
+  switch(ATT) {
+  case ATT_ArrayRank:
+    if (T->isArrayType()) {
+      unsigned Dim = 0;
+      while (const ArrayType *AT = Self.Context.getAsArrayType(T)) {
+        ++Dim;
+        T = AT->getElementType();
+      }
+      return Dim;
+    }
+    return 0;
+
+  case ATT_ArrayExtent: {
+    llvm::APSInt Value;
+    uint64_t Dim;
+    if (Self.VerifyIntegerConstantExpression(DimExpr, &Value,
+          Self.PDiag(diag::err_dimension_expr_not_constant_integer),
+          false).isInvalid())
+      return 0;
+    if (Value.isSigned() && Value.isNegative()) {
+      Self.Diag(KeyLoc, diag::err_dimension_expr_not_constant_integer)
+        << DimExpr->getSourceRange();
+      return 0;
+    }
+    Dim = Value.getLimitedValue();
+
+    if (T->isArrayType()) {
+      unsigned D = 0;
+      bool Matched = false;
+      while (const ArrayType *AT = Self.Context.getAsArrayType(T)) {
+        if (Dim == D) {
+          Matched = true;
+          break;
+        }
+        ++D;
+        T = AT->getElementType();
+      }
+
+      if (Matched && T->isArrayType()) {
+        if (const ConstantArrayType *CAT = Self.Context.getAsConstantArrayType(T))
+          return CAT->getSize().getLimitedValue();
+      }
+    }
+    return 0;
+  }
+  }
+  llvm_unreachable("Unknown type trait or not implemented");
+}
+
+ExprResult Sema::BuildArrayTypeTrait(ArrayTypeTrait ATT,
+                                     SourceLocation KWLoc,
+                                     TypeSourceInfo *TSInfo,
+                                     Expr* DimExpr,
+                                     SourceLocation RParen) {
+  QualType T = TSInfo->getType();
+
+  // FIXME: This should likely be tracked as an APInt to remove any host
+  // assumptions about the width of size_t on the target.
+  uint64_t Value = 0;
+  if (!T->isDependentType())
+    Value = EvaluateArrayTypeTrait(*this, ATT, T, DimExpr, KWLoc);
+
+  // While the specification for these traits from the Embarcadero C++
+  // compiler's documentation says the return type is 'unsigned int', Clang
+  // returns 'size_t'. On Windows, the primary platform for the Embarcadero
+  // compiler, there is no difference. On several other platforms this is an
+  // important distinction.
+  return Owned(new (Context) ArrayTypeTraitExpr(KWLoc, ATT, TSInfo, Value,
+                                                DimExpr, RParen,
+                                                Context.getSizeType()));
+}
+
+ExprResult Sema::ActOnExpressionTrait(ExpressionTrait ET,
+                                      SourceLocation KWLoc,
+                                      Expr *Queried,
+                                      SourceLocation RParen) {
+  // If error parsing the expression, ignore.
+  if (!Queried)
+    return ExprError();
+
+  ExprResult Result = BuildExpressionTrait(ET, KWLoc, Queried, RParen);
+
+  return move(Result);
+}
+
+static bool EvaluateExpressionTrait(ExpressionTrait ET, Expr *E) {
+  switch (ET) {
+  case ET_IsLValueExpr: return E->isLValue();
+  case ET_IsRValueExpr: return E->isRValue();
+  }
+  llvm_unreachable("Expression trait not covered by switch");
+}
+
+ExprResult Sema::BuildExpressionTrait(ExpressionTrait ET,
+                                      SourceLocation KWLoc,
+                                      Expr *Queried,
+                                      SourceLocation RParen) {
+  if (Queried->isTypeDependent()) {
+    // Delay type-checking for type-dependent expressions.
+  } else if (Queried->getType()->isPlaceholderType()) {
+    ExprResult PE = CheckPlaceholderExpr(Queried);
+    if (PE.isInvalid()) return ExprError();
+    return BuildExpressionTrait(ET, KWLoc, PE.take(), RParen);
+  }
+
+  bool Value = EvaluateExpressionTrait(ET, Queried);
+
+  return Owned(new (Context) ExpressionTraitExpr(KWLoc, ET, Queried, Value,
+                                                 RParen, Context.BoolTy));
+}
+
+QualType Sema::CheckPointerToMemberOperands(ExprResult &LHS, ExprResult &RHS,
+                                            ExprValueKind &VK,
+                                            SourceLocation Loc,
+                                            bool isIndirect) {
+  assert(!LHS.get()->getType()->isPlaceholderType() &&
+         !RHS.get()->getType()->isPlaceholderType() &&
+         "placeholders should have been weeded out by now");
+
+  // The LHS undergoes lvalue conversions if this is ->*.
+  if (isIndirect) {
+    LHS = DefaultLvalueConversion(LHS.take());
+    if (LHS.isInvalid()) return QualType();
+  }
+
+  // The RHS always undergoes lvalue conversions.
+  RHS = DefaultLvalueConversion(RHS.take());
+  if (RHS.isInvalid()) return QualType();
+
+  const char *OpSpelling = isIndirect ? "->*" : ".*";
+  // C++ 5.5p2
+  //   The binary operator .* [p3: ->*] binds its second operand, which shall
+  //   be of type "pointer to member of T" (where T is a completely-defined
+  //   class type) [...]
+  QualType RHSType = RHS.get()->getType();
+  const MemberPointerType *MemPtr = RHSType->getAs<MemberPointerType>();
+  if (!MemPtr) {
+    Diag(Loc, diag::err_bad_memptr_rhs)
+      << OpSpelling << RHSType << RHS.get()->getSourceRange();
+    return QualType();
+  }
+
+  QualType Class(MemPtr->getClass(), 0);
+
+  // Note: C++ [expr.mptr.oper]p2-3 says that the class type into which the
+  // member pointer points must be completely-defined. However, there is no
+  // reason for this semantic distinction, and the rule is not enforced by
+  // other compilers. Therefore, we do not check this property, as it is
+  // likely to be considered a defect.
+
+  // C++ 5.5p2
+  //   [...] to its first operand, which shall be of class T or of a class of
+  //   which T is an unambiguous and accessible base class. [p3: a pointer to
+  //   such a class]
+  QualType LHSType = LHS.get()->getType();
+  if (isIndirect) {
+    if (const PointerType *Ptr = LHSType->getAs<PointerType>())
+      LHSType = Ptr->getPointeeType();
+    else {
+      Diag(Loc, diag::err_bad_memptr_lhs)
+        << OpSpelling << 1 << LHSType
+        << FixItHint::CreateReplacement(SourceRange(Loc), ".*");
+      return QualType();
+    }
+  }
+
+  if (!Context.hasSameUnqualifiedType(Class, LHSType)) {
+    // If we want to check the hierarchy, we need a complete type.
+    if (RequireCompleteType(Loc, LHSType, PDiag(diag::err_bad_memptr_lhs)
+        << OpSpelling << (int)isIndirect)) {
+      return QualType();
+    }
+    CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
+                       /*DetectVirtual=*/false);
+    // FIXME: Would it be useful to print full ambiguity paths, or is that
+    // overkill?
+    if (!IsDerivedFrom(LHSType, Class, Paths) ||
+        Paths.isAmbiguous(Context.getCanonicalType(Class))) {
+      Diag(Loc, diag::err_bad_memptr_lhs) << OpSpelling
+        << (int)isIndirect << LHS.get()->getType();
+      return QualType();
+    }
+    // Cast LHS to type of use.
+    QualType UseType = isIndirect ? Context.getPointerType(Class) : Class;
+    ExprValueKind VK = isIndirect ? VK_RValue : LHS.get()->getValueKind();
+
+    CXXCastPath BasePath;
+    BuildBasePathArray(Paths, BasePath);
+    LHS = ImpCastExprToType(LHS.take(), UseType, CK_DerivedToBase, VK,
+                            &BasePath);
+  }
+
+  if (isa<CXXScalarValueInitExpr>(RHS.get()->IgnoreParens())) {
+    // Diagnose use of pointer-to-member type which when used as
+    // the functional cast in a pointer-to-member expression.
+    Diag(Loc, diag::err_pointer_to_member_type) << isIndirect;
+     return QualType();
+  }
+
+  // C++ 5.5p2
+  //   The result is an object or a function of the type specified by the
+  //   second operand.
+  // The cv qualifiers are the union of those in the pointer and the left side,
+  // in accordance with 5.5p5 and 5.2.5.
+  QualType Result = MemPtr->getPointeeType();
+  Result = Context.getCVRQualifiedType(Result, LHSType.getCVRQualifiers());
+
+  // C++0x [expr.mptr.oper]p6:
+  //   In a .* expression whose object expression is an rvalue, the program is
+  //   ill-formed if the second operand is a pointer to member function with
+  //   ref-qualifier &. In a ->* expression or in a .* expression whose object
+  //   expression is an lvalue, the program is ill-formed if the second operand
+  //   is a pointer to member function with ref-qualifier &&.
+  if (const FunctionProtoType *Proto = Result->getAs<FunctionProtoType>()) {
+    switch (Proto->getRefQualifier()) {
+    case RQ_None:
+      // Do nothing
+      break;
+
+    case RQ_LValue:
+      if (!isIndirect && !LHS.get()->Classify(Context).isLValue())
+        Diag(Loc, diag::err_pointer_to_member_oper_value_classify)
+          << RHSType << 1 << LHS.get()->getSourceRange();
+      break;
+
+    case RQ_RValue:
+      if (isIndirect || !LHS.get()->Classify(Context).isRValue())
+        Diag(Loc, diag::err_pointer_to_member_oper_value_classify)
+          << RHSType << 0 << LHS.get()->getSourceRange();
+      break;
+    }
+  }
+
+  // C++ [expr.mptr.oper]p6:
+  //   The result of a .* expression whose second operand is a pointer
+  //   to a data member is of the same value category as its
+  //   first operand. The result of a .* expression whose second
+  //   operand is a pointer to a member function is a prvalue. The
+  //   result of an ->* expression is an lvalue if its second operand
+  //   is a pointer to data member and a prvalue otherwise.
+  if (Result->isFunctionType()) {
+    VK = VK_RValue;
+    return Context.BoundMemberTy;
+  } else if (isIndirect) {
+    VK = VK_LValue;
+  } else {
+    VK = LHS.get()->getValueKind();
+  }
+
+  return Result;
+}
+
+/// \brief Try to convert a type to another according to C++0x 5.16p3.
+///
+/// This is part of the parameter validation for the ? operator. If either
+/// value operand is a class type, the two operands are attempted to be
+/// converted to each other. This function does the conversion in one direction.
+/// It returns true if the program is ill-formed and has already been diagnosed
+/// as such.
+static bool TryClassUnification(Sema &Self, Expr *From, Expr *To,
+                                SourceLocation QuestionLoc,
+                                bool &HaveConversion,
+                                QualType &ToType) {
+  HaveConversion = false;
+  ToType = To->getType();
+
+  InitializationKind Kind = InitializationKind::CreateCopy(To->getLocStart(),
+                                                           SourceLocation());
+  // C++0x 5.16p3
+  //   The process for determining whether an operand expression E1 of type T1
+  //   can be converted to match an operand expression E2 of type T2 is defined
+  //   as follows:
+  //   -- If E2 is an lvalue:
+  bool ToIsLvalue = To->isLValue();
+  if (ToIsLvalue) {
+    //   E1 can be converted to match E2 if E1 can be implicitly converted to
+    //   type "lvalue reference to T2", subject to the constraint that in the
+    //   conversion the reference must bind directly to E1.
+    QualType T = Self.Context.getLValueReferenceType(ToType);
+    InitializedEntity Entity = InitializedEntity::InitializeTemporary(T);
+
+    InitializationSequence InitSeq(Self, Entity, Kind, &From, 1);
+    if (InitSeq.isDirectReferenceBinding()) {
+      ToType = T;
+      HaveConversion = true;
+      return false;
+    }
+
+    if (InitSeq.isAmbiguous())
+      return InitSeq.Diagnose(Self, Entity, Kind, &From, 1);
+  }
+
+  //   -- If E2 is an rvalue, or if the conversion above cannot be done:
+  //      -- if E1 and E2 have class type, and the underlying class types are
+  //         the same or one is a base class of the other:
+  QualType FTy = From->getType();
+  QualType TTy = To->getType();
+  const RecordType *FRec = FTy->getAs<RecordType>();
+  const RecordType *TRec = TTy->getAs<RecordType>();
+  bool FDerivedFromT = FRec && TRec && FRec != TRec &&
+                       Self.IsDerivedFrom(FTy, TTy);
+  if (FRec && TRec &&
+      (FRec == TRec || FDerivedFromT || Self.IsDerivedFrom(TTy, FTy))) {
+    //         E1 can be converted to match E2 if the class of T2 is the
+    //         same type as, or a base class of, the class of T1, and
+    //         [cv2 > cv1].
+    if (FRec == TRec || FDerivedFromT) {
+      if (TTy.isAtLeastAsQualifiedAs(FTy)) {
+        InitializedEntity Entity = InitializedEntity::InitializeTemporary(TTy);
+        InitializationSequence InitSeq(Self, Entity, Kind, &From, 1);
+        if (InitSeq) {
+          HaveConversion = true;
+          return false;
+        }
+
+        if (InitSeq.isAmbiguous())
+          return InitSeq.Diagnose(Self, Entity, Kind, &From, 1);
+      }
+    }
+
+    return false;
+  }
+
+  //     -- Otherwise: E1 can be converted to match E2 if E1 can be
+  //        implicitly converted to the type that expression E2 would have
+  //        if E2 were converted to an rvalue (or the type it has, if E2 is
+  //        an rvalue).
+  //
+  // This actually refers very narrowly to the lvalue-to-rvalue conversion, not
+  // to the array-to-pointer or function-to-pointer conversions.
+  if (!TTy->getAs<TagType>())
+    TTy = TTy.getUnqualifiedType();
+
+  InitializedEntity Entity = InitializedEntity::InitializeTemporary(TTy);
+  InitializationSequence InitSeq(Self, Entity, Kind, &From, 1);
+  HaveConversion = !InitSeq.Failed();
+  ToType = TTy;
+  if (InitSeq.isAmbiguous())
+    return InitSeq.Diagnose(Self, Entity, Kind, &From, 1);
+
+  return false;
+}
+
+/// \brief Try to find a common type for two according to C++0x 5.16p5.
+///
+/// This is part of the parameter validation for the ? operator. If either
+/// value operand is a class type, overload resolution is used to find a
+/// conversion to a common type.
+static bool FindConditionalOverload(Sema &Self, ExprResult &LHS, ExprResult &RHS,
+                                    SourceLocation QuestionLoc) {
+  Expr *Args[2] = { LHS.get(), RHS.get() };
+  OverloadCandidateSet CandidateSet(QuestionLoc);
+  Self.AddBuiltinOperatorCandidates(OO_Conditional, QuestionLoc, Args, 2,
+                                    CandidateSet);
+
+  OverloadCandidateSet::iterator Best;
+  switch (CandidateSet.BestViableFunction(Self, QuestionLoc, Best)) {
+    case OR_Success: {
+      // We found a match. Perform the conversions on the arguments and move on.
+      ExprResult LHSRes =
+        Self.PerformImplicitConversion(LHS.get(), Best->BuiltinTypes.ParamTypes[0],
+                                       Best->Conversions[0], Sema::AA_Converting);
+      if (LHSRes.isInvalid())
+        break;
+      LHS = move(LHSRes);
+
+      ExprResult RHSRes =
+        Self.PerformImplicitConversion(RHS.get(), Best->BuiltinTypes.ParamTypes[1],
+                                       Best->Conversions[1], Sema::AA_Converting);
+      if (RHSRes.isInvalid())
+        break;
+      RHS = move(RHSRes);
+      if (Best->Function)
+        Self.MarkFunctionReferenced(QuestionLoc, Best->Function);
+      return false;
+    }
+    
+    case OR_No_Viable_Function:
+
+      // Emit a better diagnostic if one of the expressions is a null pointer
+      // constant and the other is a pointer type. In this case, the user most
+      // likely forgot to take the address of the other expression.
+      if (Self.DiagnoseConditionalForNull(LHS.get(), RHS.get(), QuestionLoc))
+        return true;
+
+      Self.Diag(QuestionLoc, diag::err_typecheck_cond_incompatible_operands)
+        << LHS.get()->getType() << RHS.get()->getType()
+        << LHS.get()->getSourceRange() << RHS.get()->getSourceRange();
+      return true;
+
+    case OR_Ambiguous:
+      Self.Diag(QuestionLoc, diag::err_conditional_ambiguous_ovl)
+        << LHS.get()->getType() << RHS.get()->getType()
+        << LHS.get()->getSourceRange() << RHS.get()->getSourceRange();
+      // FIXME: Print the possible common types by printing the return types of
+      // the viable candidates.
+      break;
+
+    case OR_Deleted:
+      llvm_unreachable("Conditional operator has only built-in overloads");
+  }
+  return true;
+}
+
+/// \brief Perform an "extended" implicit conversion as returned by
+/// TryClassUnification.
+static bool ConvertForConditional(Sema &Self, ExprResult &E, QualType T) {
+  InitializedEntity Entity = InitializedEntity::InitializeTemporary(T);
+  InitializationKind Kind = InitializationKind::CreateCopy(E.get()->getLocStart(),
+                                                           SourceLocation());
+  Expr *Arg = E.take();
+  InitializationSequence InitSeq(Self, Entity, Kind, &Arg, 1);
+  ExprResult Result = InitSeq.Perform(Self, Entity, Kind, MultiExprArg(&Arg, 1));
+  if (Result.isInvalid())
+    return true;
+
+  E = Result;
+  return false;
+}
+
+/// \brief Check the operands of ?: under C++ semantics.
+///
+/// See C++ [expr.cond]. Note that LHS is never null, even for the GNU x ?: y
+/// extension. In this case, LHS == Cond. (But they're not aliases.)
+QualType Sema::CXXCheckConditionalOperands(ExprResult &Cond, ExprResult &LHS, ExprResult &RHS,
+                                           ExprValueKind &VK, ExprObjectKind &OK,
+                                           SourceLocation QuestionLoc) {
+  // FIXME: Handle C99's complex types, vector types, block pointers and Obj-C++
+  // interface pointers.
+
+  // C++0x 5.16p1
+  //   The first expression is contextually converted to bool.
+  if (!Cond.get()->isTypeDependent()) {
+    ExprResult CondRes = CheckCXXBooleanCondition(Cond.take());
+    if (CondRes.isInvalid())
+      return QualType();
+    Cond = move(CondRes);
+  }
+
+  // Assume r-value.
+  VK = VK_RValue;
+  OK = OK_Ordinary;
+
+  // Either of the arguments dependent?
+  if (LHS.get()->isTypeDependent() || RHS.get()->isTypeDependent())
+    return Context.DependentTy;
+
+  // C++0x 5.16p2
+  //   If either the second or the third operand has type (cv) void, ...
+  QualType LTy = LHS.get()->getType();
+  QualType RTy = RHS.get()->getType();
+  bool LVoid = LTy->isVoidType();
+  bool RVoid = RTy->isVoidType();
+  if (LVoid || RVoid) {
+    //   ... then the [l2r] conversions are performed on the second and third
+    //   operands ...
+    LHS = DefaultFunctionArrayLvalueConversion(LHS.take());
+    RHS = DefaultFunctionArrayLvalueConversion(RHS.take());
+    if (LHS.isInvalid() || RHS.isInvalid())
+      return QualType();
+    LTy = LHS.get()->getType();
+    RTy = RHS.get()->getType();
+
+    //   ... and one of the following shall hold:
+    //   -- The second or the third operand (but not both) is a throw-
+    //      expression; the result is of the type of the other and is an rvalue.
+    bool LThrow = isa<CXXThrowExpr>(LHS.get());
+    bool RThrow = isa<CXXThrowExpr>(RHS.get());
+    if (LThrow && !RThrow)
+      return RTy;
+    if (RThrow && !LThrow)
+      return LTy;
+
+    //   -- Both the second and third operands have type void; the result is of
+    //      type void and is an rvalue.
+    if (LVoid && RVoid)
+      return Context.VoidTy;
+
+    // Neither holds, error.
+    Diag(QuestionLoc, diag::err_conditional_void_nonvoid)
+      << (LVoid ? RTy : LTy) << (LVoid ? 0 : 1)
+      << LHS.get()->getSourceRange() << RHS.get()->getSourceRange();
+    return QualType();
+  }
+
+  // Neither is void.
+
+  // C++0x 5.16p3
+  //   Otherwise, if the second and third operand have different types, and
+  //   either has (cv) class type, and attempt is made to convert each of those
+  //   operands to the other.
+  if (!Context.hasSameType(LTy, RTy) &&
+      (LTy->isRecordType() || RTy->isRecordType())) {
+    ImplicitConversionSequence ICSLeftToRight, ICSRightToLeft;
+    // These return true if a single direction is already ambiguous.
+    QualType L2RType, R2LType;
+    bool HaveL2R, HaveR2L;
+    if (TryClassUnification(*this, LHS.get(), RHS.get(), QuestionLoc, HaveL2R, L2RType))
+      return QualType();
+    if (TryClassUnification(*this, RHS.get(), LHS.get(), QuestionLoc, HaveR2L, R2LType))
+      return QualType();
+
+    //   If both can be converted, [...] the program is ill-formed.
+    if (HaveL2R && HaveR2L) {
+      Diag(QuestionLoc, diag::err_conditional_ambiguous)
+        << LTy << RTy << LHS.get()->getSourceRange() << RHS.get()->getSourceRange();
+      return QualType();
+    }
+
+    //   If exactly one conversion is possible, that conversion is applied to
+    //   the chosen operand and the converted operands are used in place of the
+    //   original operands for the remainder of this section.
+    if (HaveL2R) {
+      if (ConvertForConditional(*this, LHS, L2RType) || LHS.isInvalid())
+        return QualType();
+      LTy = LHS.get()->getType();
+    } else if (HaveR2L) {
+      if (ConvertForConditional(*this, RHS, R2LType) || RHS.isInvalid())
+        return QualType();
+      RTy = RHS.get()->getType();
+    }
+  }
+
+  // C++0x 5.16p4
+  //   If the second and third operands are glvalues of the same value
+  //   category and have the same type, the result is of that type and
+  //   value category and it is a bit-field if the second or the third
+  //   operand is a bit-field, or if both are bit-fields.
+  // We only extend this to bitfields, not to the crazy other kinds of
+  // l-values.
+  bool Same = Context.hasSameType(LTy, RTy);
+  if (Same &&
+      LHS.get()->isGLValue() &&
+      LHS.get()->getValueKind() == RHS.get()->getValueKind() &&
+      LHS.get()->isOrdinaryOrBitFieldObject() &&
+      RHS.get()->isOrdinaryOrBitFieldObject()) {
+    VK = LHS.get()->getValueKind();
+    if (LHS.get()->getObjectKind() == OK_BitField ||
+        RHS.get()->getObjectKind() == OK_BitField)
+      OK = OK_BitField;
+    return LTy;
+  }
+
+  // C++0x 5.16p5
+  //   Otherwise, the result is an rvalue. If the second and third operands
+  //   do not have the same type, and either has (cv) class type, ...
+  if (!Same && (LTy->isRecordType() || RTy->isRecordType())) {
+    //   ... overload resolution is used to determine the conversions (if any)
+    //   to be applied to the operands. If the overload resolution fails, the
+    //   program is ill-formed.
+    if (FindConditionalOverload(*this, LHS, RHS, QuestionLoc))
+      return QualType();
+  }
+
+  // C++0x 5.16p6
+  //   LValue-to-rvalue, array-to-pointer, and function-to-pointer standard
+  //   conversions are performed on the second and third operands.
+  LHS = DefaultFunctionArrayLvalueConversion(LHS.take());
+  RHS = DefaultFunctionArrayLvalueConversion(RHS.take());
+  if (LHS.isInvalid() || RHS.isInvalid())
+    return QualType();
+  LTy = LHS.get()->getType();
+  RTy = RHS.get()->getType();
+
+  //   After those conversions, one of the following shall hold:
+  //   -- The second and third operands have the same type; the result
+  //      is of that type. If the operands have class type, the result
+  //      is a prvalue temporary of the result type, which is
+  //      copy-initialized from either the second operand or the third
+  //      operand depending on the value of the first operand.
+  if (Context.getCanonicalType(LTy) == Context.getCanonicalType(RTy)) {
+    if (LTy->isRecordType()) {
+      // The operands have class type. Make a temporary copy.
+      InitializedEntity Entity = InitializedEntity::InitializeTemporary(LTy);
+      ExprResult LHSCopy = PerformCopyInitialization(Entity,
+                                                     SourceLocation(),
+                                                     LHS);
+      if (LHSCopy.isInvalid())
+        return QualType();
+
+      ExprResult RHSCopy = PerformCopyInitialization(Entity,
+                                                     SourceLocation(),
+                                                     RHS);
+      if (RHSCopy.isInvalid())
+        return QualType();
+
+      LHS = LHSCopy;
+      RHS = RHSCopy;
+    }
+
+    return LTy;
+  }
+
+  // Extension: conditional operator involving vector types.
+  if (LTy->isVectorType() || RTy->isVectorType())
+    return CheckVectorOperands(LHS, RHS, QuestionLoc, /*isCompAssign*/false);
+
+  //   -- The second and third operands have arithmetic or enumeration type;
+  //      the usual arithmetic conversions are performed to bring them to a
+  //      common type, and the result is of that type.
+  if (LTy->isArithmeticType() && RTy->isArithmeticType()) {
+    UsualArithmeticConversions(LHS, RHS);
+    if (LHS.isInvalid() || RHS.isInvalid())
+      return QualType();
+    return LHS.get()->getType();
+  }
+
+  //   -- The second and third operands have pointer type, or one has pointer
+  //      type and the other is a null pointer constant; pointer conversions
+  //      and qualification conversions are performed to bring them to their
+  //      composite pointer type. The result is of the composite pointer type.
+  //   -- The second and third operands have pointer to member type, or one has
+  //      pointer to member type and the other is a null pointer constant;
+  //      pointer to member conversions and qualification conversions are
+  //      performed to bring them to a common type, whose cv-qualification
+  //      shall match the cv-qualification of either the second or the third
+  //      operand. The result is of the common type.
+  bool NonStandardCompositeType = false;
+  QualType Composite = FindCompositePointerType(QuestionLoc, LHS, RHS,
+                              isSFINAEContext()? 0 : &NonStandardCompositeType);
+  if (!Composite.isNull()) {
+    if (NonStandardCompositeType)
+      Diag(QuestionLoc,
+           diag::ext_typecheck_cond_incompatible_operands_nonstandard)
+        << LTy << RTy << Composite
+        << LHS.get()->getSourceRange() << RHS.get()->getSourceRange();
+
+    return Composite;
+  }
+
+  // Similarly, attempt to find composite type of two objective-c pointers.
+  Composite = FindCompositeObjCPointerType(LHS, RHS, QuestionLoc);
+  if (!Composite.isNull())
+    return Composite;
+
+  // Check if we are using a null with a non-pointer type.
+  if (DiagnoseConditionalForNull(LHS.get(), RHS.get(), QuestionLoc))
+    return QualType();
+
+  Diag(QuestionLoc, diag::err_typecheck_cond_incompatible_operands)
+    << LHS.get()->getType() << RHS.get()->getType()
+    << LHS.get()->getSourceRange() << RHS.get()->getSourceRange();
+  return QualType();
+}
+
+/// \brief Find a merged pointer type and convert the two expressions to it.
+///
+/// This finds the composite pointer type (or member pointer type) for @p E1
+/// and @p E2 according to C++0x 5.9p2. It converts both expressions to this
+/// type and returns it.
+/// It does not emit diagnostics.
+///
+/// \param Loc The location of the operator requiring these two expressions to
+/// be converted to the composite pointer type.
+///
+/// If \p NonStandardCompositeType is non-NULL, then we are permitted to find
+/// a non-standard (but still sane) composite type to which both expressions
+/// can be converted. When such a type is chosen, \c *NonStandardCompositeType
+/// will be set true.
+QualType Sema::FindCompositePointerType(SourceLocation Loc,
+                                        Expr *&E1, Expr *&E2,
+                                        bool *NonStandardCompositeType) {
+  if (NonStandardCompositeType)
+    *NonStandardCompositeType = false;
+
+  assert(getLangOpts().CPlusPlus && "This function assumes C++");
+  QualType T1 = E1->getType(), T2 = E2->getType();
+
+  if (!T1->isAnyPointerType() && !T1->isMemberPointerType() &&
+      !T2->isAnyPointerType() && !T2->isMemberPointerType())
+   return QualType();
+
+  // C++0x 5.9p2
+  //   Pointer conversions and qualification conversions are performed on
+  //   pointer operands to bring them to their composite pointer type. If
+  //   one operand is a null pointer constant, the composite pointer type is
+  //   the type of the other operand.
+  if (E1->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull)) {
+    if (T2->isMemberPointerType())
+      E1 = ImpCastExprToType(E1, T2, CK_NullToMemberPointer).take();
+    else
+      E1 = ImpCastExprToType(E1, T2, CK_NullToPointer).take();
+    return T2;
+  }
+  if (E2->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull)) {
+    if (T1->isMemberPointerType())
+      E2 = ImpCastExprToType(E2, T1, CK_NullToMemberPointer).take();
+    else
+      E2 = ImpCastExprToType(E2, T1, CK_NullToPointer).take();
+    return T1;
+  }
+
+  // Now both have to be pointers or member pointers.
+  if ((!T1->isPointerType() && !T1->isMemberPointerType()) ||
+      (!T2->isPointerType() && !T2->isMemberPointerType()))
+    return QualType();
+
+  //   Otherwise, of one of the operands has type "pointer to cv1 void," then
+  //   the other has type "pointer to cv2 T" and the composite pointer type is
+  //   "pointer to cv12 void," where cv12 is the union of cv1 and cv2.
+  //   Otherwise, the composite pointer type is a pointer type similar to the
+  //   type of one of the operands, with a cv-qualification signature that is
+  //   the union of the cv-qualification signatures of the operand types.
+  // In practice, the first part here is redundant; it's subsumed by the second.
+  // What we do here is, we build the two possible composite types, and try the
+  // conversions in both directions. If only one works, or if the two composite
+  // types are the same, we have succeeded.
+  // FIXME: extended qualifiers?
+  typedef SmallVector<unsigned, 4> QualifierVector;
+  QualifierVector QualifierUnion;
+  typedef SmallVector<std::pair<const Type *, const Type *>, 4>
+      ContainingClassVector;
+  ContainingClassVector MemberOfClass;
+  QualType Composite1 = Context.getCanonicalType(T1),
+           Composite2 = Context.getCanonicalType(T2);
+  unsigned NeedConstBefore = 0;
+  do {
+    const PointerType *Ptr1, *Ptr2;
+    if ((Ptr1 = Composite1->getAs<PointerType>()) &&
+        (Ptr2 = Composite2->getAs<PointerType>())) {
+      Composite1 = Ptr1->getPointeeType();
+      Composite2 = Ptr2->getPointeeType();
+
+      // If we're allowed to create a non-standard composite type, keep track
+      // of where we need to fill in additional 'const' qualifiers.
+      if (NonStandardCompositeType &&
+          Composite1.getCVRQualifiers() != Composite2.getCVRQualifiers())
+        NeedConstBefore = QualifierUnion.size();
+
+      QualifierUnion.push_back(
+                 Composite1.getCVRQualifiers() | Composite2.getCVRQualifiers());
+      MemberOfClass.push_back(std::make_pair((const Type *)0, (const Type *)0));
+      continue;
+    }
+
+    const MemberPointerType *MemPtr1, *MemPtr2;
+    if ((MemPtr1 = Composite1->getAs<MemberPointerType>()) &&
+        (MemPtr2 = Composite2->getAs<MemberPointerType>())) {
+      Composite1 = MemPtr1->getPointeeType();
+      Composite2 = MemPtr2->getPointeeType();
+
+      // If we're allowed to create a non-standard composite type, keep track
+      // of where we need to fill in additional 'const' qualifiers.
+      if (NonStandardCompositeType &&
+          Composite1.getCVRQualifiers() != Composite2.getCVRQualifiers())
+        NeedConstBefore = QualifierUnion.size();
+
+      QualifierUnion.push_back(
+                 Composite1.getCVRQualifiers() | Composite2.getCVRQualifiers());
+      MemberOfClass.push_back(std::make_pair(MemPtr1->getClass(),
+                                             MemPtr2->getClass()));
+      continue;
+    }
+
+    // FIXME: block pointer types?
+
+    // Cannot unwrap any more types.
+    break;
+  } while (true);
+
+  if (NeedConstBefore && NonStandardCompositeType) {
+    // Extension: Add 'const' to qualifiers that come before the first qualifier
+    // mismatch, so that our (non-standard!) composite type meets the
+    // requirements of C++ [conv.qual]p4 bullet 3.
+    for (unsigned I = 0; I != NeedConstBefore; ++I) {
+      if ((QualifierUnion[I] & Qualifiers::Const) == 0) {
+        QualifierUnion[I] = QualifierUnion[I] | Qualifiers::Const;
+        *NonStandardCompositeType = true;
+      }
+    }
+  }
+
+  // Rewrap the composites as pointers or member pointers with the union CVRs.
+  ContainingClassVector::reverse_iterator MOC
+    = MemberOfClass.rbegin();
+  for (QualifierVector::reverse_iterator
+         I = QualifierUnion.rbegin(),
+         E = QualifierUnion.rend();
+       I != E; (void)++I, ++MOC) {
+    Qualifiers Quals = Qualifiers::fromCVRMask(*I);
+    if (MOC->first && MOC->second) {
+      // Rebuild member pointer type
+      Composite1 = Context.getMemberPointerType(
+                                    Context.getQualifiedType(Composite1, Quals),
+                                    MOC->first);
+      Composite2 = Context.getMemberPointerType(
+                                    Context.getQualifiedType(Composite2, Quals),
+                                    MOC->second);
+    } else {
+      // Rebuild pointer type
+      Composite1
+        = Context.getPointerType(Context.getQualifiedType(Composite1, Quals));
+      Composite2
+        = Context.getPointerType(Context.getQualifiedType(Composite2, Quals));
+    }
+  }
+
+  // Try to convert to the first composite pointer type.
+  InitializedEntity Entity1
+    = InitializedEntity::InitializeTemporary(Composite1);
+  InitializationKind Kind
+    = InitializationKind::CreateCopy(Loc, SourceLocation());
+  InitializationSequence E1ToC1(*this, Entity1, Kind, &E1, 1);
+  InitializationSequence E2ToC1(*this, Entity1, Kind, &E2, 1);
+
+  if (E1ToC1 && E2ToC1) {
+    // Conversion to Composite1 is viable.
+    if (!Context.hasSameType(Composite1, Composite2)) {
+      // Composite2 is a different type from Composite1. Check whether
+      // Composite2 is also viable.
+      InitializedEntity Entity2
+        = InitializedEntity::InitializeTemporary(Composite2);
+      InitializationSequence E1ToC2(*this, Entity2, Kind, &E1, 1);
+      InitializationSequence E2ToC2(*this, Entity2, Kind, &E2, 1);
+      if (E1ToC2 && E2ToC2) {
+        // Both Composite1 and Composite2 are viable and are different;
+        // this is an ambiguity.
+        return QualType();
+      }
+    }
+
+    // Convert E1 to Composite1
+    ExprResult E1Result
+      = E1ToC1.Perform(*this, Entity1, Kind, MultiExprArg(*this,&E1,1));
+    if (E1Result.isInvalid())
+      return QualType();
+    E1 = E1Result.takeAs<Expr>();
+
+    // Convert E2 to Composite1
+    ExprResult E2Result
+      = E2ToC1.Perform(*this, Entity1, Kind, MultiExprArg(*this,&E2,1));
+    if (E2Result.isInvalid())
+      return QualType();
+    E2 = E2Result.takeAs<Expr>();
+
+    return Composite1;
+  }
+
+  // Check whether Composite2 is viable.
+  InitializedEntity Entity2
+    = InitializedEntity::InitializeTemporary(Composite2);
+  InitializationSequence E1ToC2(*this, Entity2, Kind, &E1, 1);
+  InitializationSequence E2ToC2(*this, Entity2, Kind, &E2, 1);
+  if (!E1ToC2 || !E2ToC2)
+    return QualType();
+
+  // Convert E1 to Composite2
+  ExprResult E1Result
+    = E1ToC2.Perform(*this, Entity2, Kind, MultiExprArg(*this, &E1, 1));
+  if (E1Result.isInvalid())
+    return QualType();
+  E1 = E1Result.takeAs<Expr>();
+
+  // Convert E2 to Composite2
+  ExprResult E2Result
+    = E2ToC2.Perform(*this, Entity2, Kind, MultiExprArg(*this, &E2, 1));
+  if (E2Result.isInvalid())
+    return QualType();
+  E2 = E2Result.takeAs<Expr>();
+
+  return Composite2;
+}
+
+ExprResult Sema::MaybeBindToTemporary(Expr *E) {
+  if (!E)
+    return ExprError();
+
+  assert(!isa<CXXBindTemporaryExpr>(E) && "Double-bound temporary?");
+
+  // If the result is a glvalue, we shouldn't bind it.
+  if (!E->isRValue())
+    return Owned(E);
+
+  // In ARC, calls that return a retainable type can return retained,
+  // in which case we have to insert a consuming cast.
+  if (getLangOpts().ObjCAutoRefCount &&
+      E->getType()->isObjCRetainableType()) {
+
+    bool ReturnsRetained;
+
+    // For actual calls, we compute this by examining the type of the
+    // called value.
+    if (CallExpr *Call = dyn_cast<CallExpr>(E)) {
+      Expr *Callee = Call->getCallee()->IgnoreParens();
+      QualType T = Callee->getType();
+
+      if (T == Context.BoundMemberTy) {
+        // Handle pointer-to-members.
+        if (BinaryOperator *BinOp = dyn_cast<BinaryOperator>(Callee))
+          T = BinOp->getRHS()->getType();
+        else if (MemberExpr *Mem = dyn_cast<MemberExpr>(Callee))
+          T = Mem->getMemberDecl()->getType();
+      }
+      
+      if (const PointerType *Ptr = T->getAs<PointerType>())
+        T = Ptr->getPointeeType();
+      else if (const BlockPointerType *Ptr = T->getAs<BlockPointerType>())
+        T = Ptr->getPointeeType();
+      else if (const MemberPointerType *MemPtr = T->getAs<MemberPointerType>())
+        T = MemPtr->getPointeeType();
+      
+      const FunctionType *FTy = T->getAs<FunctionType>();
+      assert(FTy && "call to value not of function type?");
+      ReturnsRetained = FTy->getExtInfo().getProducesResult();
+
+    // ActOnStmtExpr arranges things so that StmtExprs of retainable
+    // type always produce a +1 object.
+    } else if (isa<StmtExpr>(E)) {
+      ReturnsRetained = true;
+
+    // We hit this case with the lambda conversion-to-block optimization;
+    // we don't want any extra casts here.
+    } else if (isa<CastExpr>(E) &&
+               isa<BlockExpr>(cast<CastExpr>(E)->getSubExpr())) {
+      return Owned(E);
+
+    // For message sends and property references, we try to find an
+    // actual method.  FIXME: we should infer retention by selector in
+    // cases where we don't have an actual method.
+    } else {
+      ObjCMethodDecl *D = 0;
+      if (ObjCMessageExpr *Send = dyn_cast<ObjCMessageExpr>(E)) {
+        D = Send->getMethodDecl();
+      } else if (ObjCNumericLiteral *NumLit = dyn_cast<ObjCNumericLiteral>(E)) {
+        D = NumLit->getObjCNumericLiteralMethod();
+      } else if (ObjCArrayLiteral *ArrayLit = dyn_cast<ObjCArrayLiteral>(E)) {
+        D = ArrayLit->getArrayWithObjectsMethod();
+      } else if (ObjCDictionaryLiteral *DictLit
+                                        = dyn_cast<ObjCDictionaryLiteral>(E)) {
+        D = DictLit->getDictWithObjectsMethod();
+      }
+
+      ReturnsRetained = (D && D->hasAttr<NSReturnsRetainedAttr>());
+
+      // Don't do reclaims on performSelector calls; despite their
+      // return type, the invoked method doesn't necessarily actually
+      // return an object.
+      if (!ReturnsRetained &&
+          D && D->getMethodFamily() == OMF_performSelector)
+        return Owned(E);
+    }
+
+    // Don't reclaim an object of Class type.
+    if (!ReturnsRetained && E->getType()->isObjCARCImplicitlyUnretainedType())
+      return Owned(E);
+
+    ExprNeedsCleanups = true;
+
+    CastKind ck = (ReturnsRetained ? CK_ARCConsumeObject
+                                   : CK_ARCReclaimReturnedObject);
+    return Owned(ImplicitCastExpr::Create(Context, E->getType(), ck, E, 0,
+                                          VK_RValue));
+  }
+
+  if (!getLangOpts().CPlusPlus)
+    return Owned(E);
+
+  // Search for the base element type (cf. ASTContext::getBaseElementType) with
+  // a fast path for the common case that the type is directly a RecordType.
+  const Type *T = Context.getCanonicalType(E->getType().getTypePtr());
+  const RecordType *RT = 0;
+  while (!RT) {
+    switch (T->getTypeClass()) {
+    case Type::Record:
+      RT = cast<RecordType>(T);
+      break;
+    case Type::ConstantArray:
+    case Type::IncompleteArray:
+    case Type::VariableArray:
+    case Type::DependentSizedArray:
+      T = cast<ArrayType>(T)->getElementType().getTypePtr();
+      break;
+    default:
+      return Owned(E);
+    }
+  }
+
+  // That should be enough to guarantee that this type is complete, if we're
+  // not processing a decltype expression.
+  CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
+  if (RD->isInvalidDecl() || RD->isDependentContext())
+    return Owned(E);
+
+  bool IsDecltype = ExprEvalContexts.back().IsDecltype;
+  CXXDestructorDecl *Destructor = IsDecltype ? 0 : LookupDestructor(RD);
+
+  if (Destructor) {
+    MarkFunctionReferenced(E->getExprLoc(), Destructor);
+    CheckDestructorAccess(E->getExprLoc(), Destructor,
+                          PDiag(diag::err_access_dtor_temp)
+                            << E->getType());
+    DiagnoseUseOfDecl(Destructor, E->getExprLoc());
+
+    // If destructor is trivial, we can avoid the extra copy.
+    if (Destructor->isTrivial())
+      return Owned(E);
+
+    // We need a cleanup, but we don't need to remember the temporary.
+    ExprNeedsCleanups = true;
+  }
+
+  CXXTemporary *Temp = CXXTemporary::Create(Context, Destructor);
+  CXXBindTemporaryExpr *Bind = CXXBindTemporaryExpr::Create(Context, Temp, E);
+
+  if (IsDecltype)
+    ExprEvalContexts.back().DelayedDecltypeBinds.push_back(Bind);
+
+  return Owned(Bind);
+}
+
+ExprResult
+Sema::MaybeCreateExprWithCleanups(ExprResult SubExpr) {
+  if (SubExpr.isInvalid())
+    return ExprError();
+
+  return Owned(MaybeCreateExprWithCleanups(SubExpr.take()));
+}
+
+Expr *Sema::MaybeCreateExprWithCleanups(Expr *SubExpr) {
+  assert(SubExpr && "sub expression can't be null!");
+
+  CleanupVarDeclMarking();
+
+  unsigned FirstCleanup = ExprEvalContexts.back().NumCleanupObjects;
+  assert(ExprCleanupObjects.size() >= FirstCleanup);
+  assert(ExprNeedsCleanups || ExprCleanupObjects.size() == FirstCleanup);
+  if (!ExprNeedsCleanups)
+    return SubExpr;
+
+  ArrayRef<ExprWithCleanups::CleanupObject> Cleanups
+    = llvm::makeArrayRef(ExprCleanupObjects.begin() + FirstCleanup,
+                         ExprCleanupObjects.size() - FirstCleanup);
+
+  Expr *E = ExprWithCleanups::Create(Context, SubExpr, Cleanups);
+  DiscardCleanupsInEvaluationContext();
+
+  return E;
+}
+
+Stmt *Sema::MaybeCreateStmtWithCleanups(Stmt *SubStmt) {
+  assert(SubStmt && "sub statement can't be null!");
+
+  CleanupVarDeclMarking();
+
+  if (!ExprNeedsCleanups)
+    return SubStmt;
+
+  // FIXME: In order to attach the temporaries, wrap the statement into
+  // a StmtExpr; currently this is only used for asm statements.
+  // This is hacky, either create a new CXXStmtWithTemporaries statement or
+  // a new AsmStmtWithTemporaries.
+  CompoundStmt *CompStmt = new (Context) CompoundStmt(Context, &SubStmt, 1,
+                                                      SourceLocation(),
+                                                      SourceLocation());
+  Expr *E = new (Context) StmtExpr(CompStmt, Context.VoidTy, SourceLocation(),
+                                   SourceLocation());
+  return MaybeCreateExprWithCleanups(E);
+}
+
+/// Process the expression contained within a decltype. For such expressions,
+/// certain semantic checks on temporaries are delayed until this point, and
+/// are omitted for the 'topmost' call in the decltype expression. If the
+/// topmost call bound a temporary, strip that temporary off the expression.
+ExprResult Sema::ActOnDecltypeExpression(Expr *E) {
+  ExpressionEvaluationContextRecord &Rec = ExprEvalContexts.back();
+  assert(Rec.IsDecltype && "not in a decltype expression");
+
+  // C++11 [expr.call]p11:
+  //   If a function call is a prvalue of object type,
+  // -- if the function call is either
+  //   -- the operand of a decltype-specifier, or
+  //   -- the right operand of a comma operator that is the operand of a
+  //      decltype-specifier,
+  //   a temporary object is not introduced for the prvalue.
+
+  // Recursively rebuild ParenExprs and comma expressions to strip out the
+  // outermost CXXBindTemporaryExpr, if any.
+  if (ParenExpr *PE = dyn_cast<ParenExpr>(E)) {
+    ExprResult SubExpr = ActOnDecltypeExpression(PE->getSubExpr());
+    if (SubExpr.isInvalid())
+      return ExprError();
+    if (SubExpr.get() == PE->getSubExpr())
+      return Owned(E);
+    return ActOnParenExpr(PE->getLParen(), PE->getRParen(), SubExpr.take());
+  }
+  if (BinaryOperator *BO = dyn_cast<BinaryOperator>(E)) {
+    if (BO->getOpcode() == BO_Comma) {
+      ExprResult RHS = ActOnDecltypeExpression(BO->getRHS());
+      if (RHS.isInvalid())
+        return ExprError();
+      if (RHS.get() == BO->getRHS())
+        return Owned(E);
+      return Owned(new (Context) BinaryOperator(BO->getLHS(), RHS.take(),
+                                                BO_Comma, BO->getType(),
+                                                BO->getValueKind(),
+                                                BO->getObjectKind(),
+                                                BO->getOperatorLoc()));
+    }
+  }
+
+  CXXBindTemporaryExpr *TopBind = dyn_cast<CXXBindTemporaryExpr>(E);
+  if (TopBind)
+    E = TopBind->getSubExpr();
+
+  // Disable the special decltype handling now.
+  Rec.IsDecltype = false;
+
+  // Perform the semantic checks we delayed until this point.
+  CallExpr *TopCall = dyn_cast<CallExpr>(E);
+  for (unsigned I = 0, N = Rec.DelayedDecltypeCalls.size(); I != N; ++I) {
+    CallExpr *Call = Rec.DelayedDecltypeCalls[I];
+    if (Call == TopCall)
+      continue;
+
+    if (CheckCallReturnType(Call->getCallReturnType(),
+                            Call->getLocStart(),
+                            Call, Call->getDirectCallee()))
+      return ExprError();
+  }
+
+  // Now all relevant types are complete, check the destructors are accessible
+  // and non-deleted, and annotate them on the temporaries.
+  for (unsigned I = 0, N = Rec.DelayedDecltypeBinds.size(); I != N; ++I) {
+    CXXBindTemporaryExpr *Bind = Rec.DelayedDecltypeBinds[I];
+    if (Bind == TopBind)
+      continue;
+
+    CXXTemporary *Temp = Bind->getTemporary();
+
+    CXXRecordDecl *RD =
+      Bind->getType()->getBaseElementTypeUnsafe()->getAsCXXRecordDecl();
+    CXXDestructorDecl *Destructor = LookupDestructor(RD);
+    Temp->setDestructor(Destructor);
+
+    MarkFunctionReferenced(E->getExprLoc(), Destructor);
+    CheckDestructorAccess(E->getExprLoc(), Destructor,
+                          PDiag(diag::err_access_dtor_temp)
+                            << E->getType());
+    DiagnoseUseOfDecl(Destructor, E->getExprLoc());
+
+    // We need a cleanup, but we don't need to remember the temporary.
+    ExprNeedsCleanups = true;
+  }
+
+  // Possibly strip off the top CXXBindTemporaryExpr.
+  return Owned(E);
+}
+
+ExprResult
+Sema::ActOnStartCXXMemberReference(Scope *S, Expr *Base, SourceLocation OpLoc,
+                                   tok::TokenKind OpKind, ParsedType &ObjectType,
+                                   bool &MayBePseudoDestructor) {
+  // Since this might be a postfix expression, get rid of ParenListExprs.
+  ExprResult Result = MaybeConvertParenListExprToParenExpr(S, Base);
+  if (Result.isInvalid()) return ExprError();
+  Base = Result.get();
+
+  Result = CheckPlaceholderExpr(Base);
+  if (Result.isInvalid()) return ExprError();
+  Base = Result.take();
+
+  QualType BaseType = Base->getType();
+  MayBePseudoDestructor = false;
+  if (BaseType->isDependentType()) {
+    // If we have a pointer to a dependent type and are using the -> operator,
+    // the object type is the type that the pointer points to. We might still
+    // have enough information about that type to do something useful.
+    if (OpKind == tok::arrow)
+      if (const PointerType *Ptr = BaseType->getAs<PointerType>())
+        BaseType = Ptr->getPointeeType();
+
+    ObjectType = ParsedType::make(BaseType);
+    MayBePseudoDestructor = true;
+    return Owned(Base);
+  }
+
+  // C++ [over.match.oper]p8:
+  //   [...] When operator->returns, the operator-> is applied  to the value
+  //   returned, with the original second operand.
+  if (OpKind == tok::arrow) {
+    // The set of types we've considered so far.
+    llvm::SmallPtrSet<CanQualType,8> CTypes;
+    SmallVector<SourceLocation, 8> Locations;
+    CTypes.insert(Context.getCanonicalType(BaseType));
+
+    while (BaseType->isRecordType()) {
+      Result = BuildOverloadedArrowExpr(S, Base, OpLoc);
+      if (Result.isInvalid())
+        return ExprError();
+      Base = Result.get();
+      if (CXXOperatorCallExpr *OpCall = dyn_cast<CXXOperatorCallExpr>(Base))
+        Locations.push_back(OpCall->getDirectCallee()->getLocation());
+      BaseType = Base->getType();
+      CanQualType CBaseType = Context.getCanonicalType(BaseType);
+      if (!CTypes.insert(CBaseType)) {
+        Diag(OpLoc, diag::err_operator_arrow_circular);
+        for (unsigned i = 0; i < Locations.size(); i++)
+          Diag(Locations[i], diag::note_declared_at);
+        return ExprError();
+      }
+    }
+
+    if (BaseType->isPointerType() || BaseType->isObjCObjectPointerType())
+      BaseType = BaseType->getPointeeType();
+  }
+
+  // Objective-C properties allow "." access on Objective-C pointer types,
+  // so adjust the base type to the object type itself.
+  if (BaseType->isObjCObjectPointerType())
+    BaseType = BaseType->getPointeeType();
+  
+  // C++ [basic.lookup.classref]p2:
+  //   [...] If the type of the object expression is of pointer to scalar
+  //   type, the unqualified-id is looked up in the context of the complete
+  //   postfix-expression.
+  //
+  // This also indicates that we could be parsing a pseudo-destructor-name.
+  // Note that Objective-C class and object types can be pseudo-destructor
+  // expressions or normal member (ivar or property) access expressions.
+  if (BaseType->isObjCObjectOrInterfaceType()) {
+    MayBePseudoDestructor = true;
+  } else if (!BaseType->isRecordType()) {
+    ObjectType = ParsedType();
+    MayBePseudoDestructor = true;
+    return Owned(Base);
+  }
+
+  // The object type must be complete (or dependent), or
+  // C++11 [expr.prim.general]p3:
+  //   Unlike the object expression in other contexts, *this is not required to
+  //   be of complete type for purposes of class member access (5.2.5) outside 
+  //   the member function body.
+  if (!BaseType->isDependentType() &&
+      !isThisOutsideMemberFunctionBody(BaseType) &&
+      RequireCompleteType(OpLoc, BaseType,
+                          PDiag(diag::err_incomplete_member_access)))
+    return ExprError();
+
+  // C++ [basic.lookup.classref]p2:
+  //   If the id-expression in a class member access (5.2.5) is an
+  //   unqualified-id, and the type of the object expression is of a class
+  //   type C (or of pointer to a class type C), the unqualified-id is looked
+  //   up in the scope of class C. [...]
+  ObjectType = ParsedType::make(BaseType);
+  return move(Base);
+}
+
+ExprResult Sema::DiagnoseDtorReference(SourceLocation NameLoc,
+                                                   Expr *MemExpr) {
+  SourceLocation ExpectedLParenLoc = PP.getLocForEndOfToken(NameLoc);
+  Diag(MemExpr->getLocStart(), diag::err_dtor_expr_without_call)
+    << isa<CXXPseudoDestructorExpr>(MemExpr)
+    << FixItHint::CreateInsertion(ExpectedLParenLoc, "()");
+
+  return ActOnCallExpr(/*Scope*/ 0,
+                       MemExpr,
+                       /*LPLoc*/ ExpectedLParenLoc,
+                       MultiExprArg(),
+                       /*RPLoc*/ ExpectedLParenLoc);
+}
+
+static bool CheckArrow(Sema& S, QualType& ObjectType, Expr *&Base, 
+                   tok::TokenKind& OpKind, SourceLocation OpLoc) {
+  if (Base->hasPlaceholderType()) {
+    ExprResult result = S.CheckPlaceholderExpr(Base);
+    if (result.isInvalid()) return true;
+    Base = result.take();
+  }
+  ObjectType = Base->getType();
+
+  // C++ [expr.pseudo]p2:
+  //   The left-hand side of the dot operator shall be of scalar type. The
+  //   left-hand side of the arrow operator shall be of pointer to scalar type.
+  //   This scalar type is the object type.
+  // Note that this is rather different from the normal handling for the
+  // arrow operator.
+  if (OpKind == tok::arrow) {
+    if (const PointerType *Ptr = ObjectType->getAs<PointerType>()) {
+      ObjectType = Ptr->getPointeeType();
+    } else if (!Base->isTypeDependent()) {
+      // The user wrote "p->" when she probably meant "p."; fix it.
+      S.Diag(OpLoc, diag::err_typecheck_member_reference_suggestion)
+        << ObjectType << true
+        << FixItHint::CreateReplacement(OpLoc, ".");
+      if (S.isSFINAEContext())
+        return true;
+
+      OpKind = tok::period;
+    }
+  }
+
+  return false;
+}
+
+ExprResult Sema::BuildPseudoDestructorExpr(Expr *Base,
+                                           SourceLocation OpLoc,
+                                           tok::TokenKind OpKind,
+                                           const CXXScopeSpec &SS,
+                                           TypeSourceInfo *ScopeTypeInfo,
+                                           SourceLocation CCLoc,
+                                           SourceLocation TildeLoc,
+                                         PseudoDestructorTypeStorage Destructed,
+                                           bool HasTrailingLParen) {
+  TypeSourceInfo *DestructedTypeInfo = Destructed.getTypeSourceInfo();
+
+  QualType ObjectType;
+  if (CheckArrow(*this, ObjectType, Base, OpKind, OpLoc))
+    return ExprError();
+
+  if (!ObjectType->isDependentType() && !ObjectType->isScalarType()) {
+    if (getLangOpts().MicrosoftMode && ObjectType->isVoidType())
+      Diag(OpLoc, diag::ext_pseudo_dtor_on_void) << Base->getSourceRange();
+    else
+      Diag(OpLoc, diag::err_pseudo_dtor_base_not_scalar)
+        << ObjectType << Base->getSourceRange();
+    return ExprError();
+  }
+
+  // C++ [expr.pseudo]p2:
+  //   [...] The cv-unqualified versions of the object type and of the type
+  //   designated by the pseudo-destructor-name shall be the same type.
+  if (DestructedTypeInfo) {
+    QualType DestructedType = DestructedTypeInfo->getType();
+    SourceLocation DestructedTypeStart
+      = DestructedTypeInfo->getTypeLoc().getLocalSourceRange().getBegin();
+    if (!DestructedType->isDependentType() && !ObjectType->isDependentType()) {
+      if (!Context.hasSameUnqualifiedType(DestructedType, ObjectType)) {
+        Diag(DestructedTypeStart, diag::err_pseudo_dtor_type_mismatch)
+          << ObjectType << DestructedType << Base->getSourceRange()
+          << DestructedTypeInfo->getTypeLoc().getLocalSourceRange();
+
+        // Recover by setting the destructed type to the object type.
+        DestructedType = ObjectType;
+        DestructedTypeInfo = Context.getTrivialTypeSourceInfo(ObjectType,
+                                                           DestructedTypeStart);
+        Destructed = PseudoDestructorTypeStorage(DestructedTypeInfo);
+      } else if (DestructedType.getObjCLifetime() != 
+                                                ObjectType.getObjCLifetime()) {
+        
+        if (DestructedType.getObjCLifetime() == Qualifiers::OCL_None) {
+          // Okay: just pretend that the user provided the correctly-qualified
+          // type.
+        } else {
+          Diag(DestructedTypeStart, diag::err_arc_pseudo_dtor_inconstant_quals)
+            << ObjectType << DestructedType << Base->getSourceRange()
+            << DestructedTypeInfo->getTypeLoc().getLocalSourceRange();
+        }
+        
+        // Recover by setting the destructed type to the object type.
+        DestructedType = ObjectType;
+        DestructedTypeInfo = Context.getTrivialTypeSourceInfo(ObjectType,
+                                                           DestructedTypeStart);
+        Destructed = PseudoDestructorTypeStorage(DestructedTypeInfo);
+      }
+    }
+  }
+
+  // C++ [expr.pseudo]p2:
+  //   [...] Furthermore, the two type-names in a pseudo-destructor-name of the
+  //   form
+  //
+  //     ::[opt] nested-name-specifier[opt] type-name :: ~ type-name
+  //
+  //   shall designate the same scalar type.
+  if (ScopeTypeInfo) {
+    QualType ScopeType = ScopeTypeInfo->getType();
+    if (!ScopeType->isDependentType() && !ObjectType->isDependentType() &&
+        !Context.hasSameUnqualifiedType(ScopeType, ObjectType)) {
+
+      Diag(ScopeTypeInfo->getTypeLoc().getLocalSourceRange().getBegin(),
+           diag::err_pseudo_dtor_type_mismatch)
+        << ObjectType << ScopeType << Base->getSourceRange()
+        << ScopeTypeInfo->getTypeLoc().getLocalSourceRange();
+
+      ScopeType = QualType();
+      ScopeTypeInfo = 0;
+    }
+  }
+
+  Expr *Result
+    = new (Context) CXXPseudoDestructorExpr(Context, Base,
+                                            OpKind == tok::arrow, OpLoc,
+                                            SS.getWithLocInContext(Context),
+                                            ScopeTypeInfo,
+                                            CCLoc,
+                                            TildeLoc,
+                                            Destructed);
+
+  if (HasTrailingLParen)
+    return Owned(Result);
+
+  return DiagnoseDtorReference(Destructed.getLocation(), Result);
+}
+
+ExprResult Sema::ActOnPseudoDestructorExpr(Scope *S, Expr *Base,
+                                           SourceLocation OpLoc,
+                                           tok::TokenKind OpKind,
+                                           CXXScopeSpec &SS,
+                                           UnqualifiedId &FirstTypeName,
+                                           SourceLocation CCLoc,
+                                           SourceLocation TildeLoc,
+                                           UnqualifiedId &SecondTypeName,
+                                           bool HasTrailingLParen) {
+  assert((FirstTypeName.getKind() == UnqualifiedId::IK_TemplateId ||
+          FirstTypeName.getKind() == UnqualifiedId::IK_Identifier) &&
+         "Invalid first type name in pseudo-destructor");
+  assert((SecondTypeName.getKind() == UnqualifiedId::IK_TemplateId ||
+          SecondTypeName.getKind() == UnqualifiedId::IK_Identifier) &&
+         "Invalid second type name in pseudo-destructor");
+
+  QualType ObjectType;
+  if (CheckArrow(*this, ObjectType, Base, OpKind, OpLoc))
+    return ExprError();
+
+  // Compute the object type that we should use for name lookup purposes. Only
+  // record types and dependent types matter.
+  ParsedType ObjectTypePtrForLookup;
+  if (!SS.isSet()) {
+    if (ObjectType->isRecordType())
+      ObjectTypePtrForLookup = ParsedType::make(ObjectType);
+    else if (ObjectType->isDependentType())
+      ObjectTypePtrForLookup = ParsedType::make(Context.DependentTy);
+  }
+
+  // Convert the name of the type being destructed (following the ~) into a
+  // type (with source-location information).
+  QualType DestructedType;
+  TypeSourceInfo *DestructedTypeInfo = 0;
+  PseudoDestructorTypeStorage Destructed;
+  if (SecondTypeName.getKind() == UnqualifiedId::IK_Identifier) {
+    ParsedType T = getTypeName(*SecondTypeName.Identifier,
+                               SecondTypeName.StartLocation,
+                               S, &SS, true, false, ObjectTypePtrForLookup);
+    if (!T &&
+        ((SS.isSet() && !computeDeclContext(SS, false)) ||
+         (!SS.isSet() && ObjectType->isDependentType()))) {
+      // The name of the type being destroyed is a dependent name, and we
+      // couldn't find anything useful in scope. Just store the identifier and
+      // it's location, and we'll perform (qualified) name lookup again at
+      // template instantiation time.
+      Destructed = PseudoDestructorTypeStorage(SecondTypeName.Identifier,
+                                               SecondTypeName.StartLocation);
+    } else if (!T) {
+      Diag(SecondTypeName.StartLocation,
+           diag::err_pseudo_dtor_destructor_non_type)
+        << SecondTypeName.Identifier << ObjectType;
+      if (isSFINAEContext())
+        return ExprError();
+
+      // Recover by assuming we had the right type all along.
+      DestructedType = ObjectType;
+    } else
+      DestructedType = GetTypeFromParser(T, &DestructedTypeInfo);
+  } else {
+    // Resolve the template-id to a type.
+    TemplateIdAnnotation *TemplateId = SecondTypeName.TemplateId;
+    ASTTemplateArgsPtr TemplateArgsPtr(*this,
+                                       TemplateId->getTemplateArgs(),
+                                       TemplateId->NumArgs);
+    TypeResult T = ActOnTemplateIdType(TemplateId->SS,
+                                       TemplateId->TemplateKWLoc,
+                                       TemplateId->Template,
+                                       TemplateId->TemplateNameLoc,
+                                       TemplateId->LAngleLoc,
+                                       TemplateArgsPtr,
+                                       TemplateId->RAngleLoc);
+    if (T.isInvalid() || !T.get()) {
+      // Recover by assuming we had the right type all along.
+      DestructedType = ObjectType;
+    } else
+      DestructedType = GetTypeFromParser(T.get(), &DestructedTypeInfo);
+  }
+
+  // If we've performed some kind of recovery, (re-)build the type source
+  // information.
+  if (!DestructedType.isNull()) {
+    if (!DestructedTypeInfo)
+      DestructedTypeInfo = Context.getTrivialTypeSourceInfo(DestructedType,
+                                                  SecondTypeName.StartLocation);
+    Destructed = PseudoDestructorTypeStorage(DestructedTypeInfo);
+  }
+
+  // Convert the name of the scope type (the type prior to '::') into a type.
+  TypeSourceInfo *ScopeTypeInfo = 0;
+  QualType ScopeType;
+  if (FirstTypeName.getKind() == UnqualifiedId::IK_TemplateId ||
+      FirstTypeName.Identifier) {
+    if (FirstTypeName.getKind() == UnqualifiedId::IK_Identifier) {
+      ParsedType T = getTypeName(*FirstTypeName.Identifier,
+                                 FirstTypeName.StartLocation,
+                                 S, &SS, true, false, ObjectTypePtrForLookup);
+      if (!T) {
+        Diag(FirstTypeName.StartLocation,
+             diag::err_pseudo_dtor_destructor_non_type)
+          << FirstTypeName.Identifier << ObjectType;
+
+        if (isSFINAEContext())
+          return ExprError();
+
+        // Just drop this type. It's unnecessary anyway.
+        ScopeType = QualType();
+      } else
+        ScopeType = GetTypeFromParser(T, &ScopeTypeInfo);
+    } else {
+      // Resolve the template-id to a type.
+      TemplateIdAnnotation *TemplateId = FirstTypeName.TemplateId;
+      ASTTemplateArgsPtr TemplateArgsPtr(*this,
+                                         TemplateId->getTemplateArgs(),
+                                         TemplateId->NumArgs);
+      TypeResult T = ActOnTemplateIdType(TemplateId->SS,
+                                         TemplateId->TemplateKWLoc,
+                                         TemplateId->Template,
+                                         TemplateId->TemplateNameLoc,
+                                         TemplateId->LAngleLoc,
+                                         TemplateArgsPtr,
+                                         TemplateId->RAngleLoc);
+      if (T.isInvalid() || !T.get()) {
+        // Recover by dropping this type.
+        ScopeType = QualType();
+      } else
+        ScopeType = GetTypeFromParser(T.get(), &ScopeTypeInfo);
+    }
+  }
+
+  if (!ScopeType.isNull() && !ScopeTypeInfo)
+    ScopeTypeInfo = Context.getTrivialTypeSourceInfo(ScopeType,
+                                                  FirstTypeName.StartLocation);
+
+
+  return BuildPseudoDestructorExpr(Base, OpLoc, OpKind, SS,
+                                   ScopeTypeInfo, CCLoc, TildeLoc,
+                                   Destructed, HasTrailingLParen);
+}
+
+ExprResult Sema::ActOnPseudoDestructorExpr(Scope *S, Expr *Base,
+                                           SourceLocation OpLoc,
+                                           tok::TokenKind OpKind,
+                                           SourceLocation TildeLoc, 
+                                           const DeclSpec& DS,
+                                           bool HasTrailingLParen) {
+  QualType ObjectType;
+  if (CheckArrow(*this, ObjectType, Base, OpKind, OpLoc))
+    return ExprError();
+
+  QualType T = BuildDecltypeType(DS.getRepAsExpr(), DS.getTypeSpecTypeLoc());
+
+  TypeLocBuilder TLB;
+  DecltypeTypeLoc DecltypeTL = TLB.push<DecltypeTypeLoc>(T);
+  DecltypeTL.setNameLoc(DS.getTypeSpecTypeLoc());
+  TypeSourceInfo *DestructedTypeInfo = TLB.getTypeSourceInfo(Context, T);
+  PseudoDestructorTypeStorage Destructed(DestructedTypeInfo);
+
+  return BuildPseudoDestructorExpr(Base, OpLoc, OpKind, CXXScopeSpec(),
+                                   0, SourceLocation(), TildeLoc,
+                                   Destructed, HasTrailingLParen);
+}
+
+ExprResult Sema::BuildCXXMemberCallExpr(Expr *E, NamedDecl *FoundDecl,
+                                        CXXConversionDecl *Method,
+                                        bool HadMultipleCandidates) {
+  if (Method->getParent()->isLambda() &&
+      Method->getConversionType()->isBlockPointerType()) {
+    // This is a lambda coversion to block pointer; check if the argument
+    // is a LambdaExpr.
+    Expr *SubE = E;
+    CastExpr *CE = dyn_cast<CastExpr>(SubE);
+    if (CE && CE->getCastKind() == CK_NoOp)
+      SubE = CE->getSubExpr();
+    SubE = SubE->IgnoreParens();
+    if (CXXBindTemporaryExpr *BE = dyn_cast<CXXBindTemporaryExpr>(SubE))
+      SubE = BE->getSubExpr();
+    if (isa<LambdaExpr>(SubE)) {
+      // For the conversion to block pointer on a lambda expression, we
+      // construct a special BlockLiteral instead; this doesn't really make
+      // a difference in ARC, but outside of ARC the resulting block literal
+      // follows the normal lifetime rules for block literals instead of being
+      // autoreleased.
+      DiagnosticErrorTrap Trap(Diags);
+      ExprResult Exp = BuildBlockForLambdaConversion(E->getExprLoc(),
+                                                     E->getExprLoc(),
+                                                     Method, E);
+      if (Exp.isInvalid())
+        Diag(E->getExprLoc(), diag::note_lambda_to_block_conv);
+      return Exp;
+    }
+  }
+      
+
+  ExprResult Exp = PerformObjectArgumentInitialization(E, /*Qualifier=*/0,
+                                          FoundDecl, Method);
+  if (Exp.isInvalid())
+    return true;
+
+  MemberExpr *ME =
+      new (Context) MemberExpr(Exp.take(), /*IsArrow=*/false, Method,
+                               SourceLocation(), Context.BoundMemberTy,
+                               VK_RValue, OK_Ordinary);
+  if (HadMultipleCandidates)
+    ME->setHadMultipleCandidates(true);
+
+  QualType ResultType = Method->getResultType();
+  ExprValueKind VK = Expr::getValueKindForType(ResultType);
+  ResultType = ResultType.getNonLValueExprType(Context);
+
+  MarkFunctionReferenced(Exp.get()->getLocStart(), Method);
+  CXXMemberCallExpr *CE =
+    new (Context) CXXMemberCallExpr(Context, ME, 0, 0, ResultType, VK,
+                                    Exp.get()->getLocEnd());
+  return CE;
+}
+
+ExprResult Sema::BuildCXXNoexceptExpr(SourceLocation KeyLoc, Expr *Operand,
+                                      SourceLocation RParen) {
+  CanThrowResult CanThrow = canThrow(Operand);
+  return Owned(new (Context) CXXNoexceptExpr(Context.BoolTy, Operand,
+                                             CanThrow, KeyLoc, RParen));
+}
+
+ExprResult Sema::ActOnNoexceptExpr(SourceLocation KeyLoc, SourceLocation,
+                                   Expr *Operand, SourceLocation RParen) {
+  return BuildCXXNoexceptExpr(KeyLoc, Operand, RParen);
+}
+
+/// Perform the conversions required for an expression used in a
+/// context that ignores the result.
+ExprResult Sema::IgnoredValueConversions(Expr *E) {
+  if (E->hasPlaceholderType()) {
+    ExprResult result = CheckPlaceholderExpr(E);
+    if (result.isInvalid()) return Owned(E);
+    E = result.take();
+  }
+
+  // C99 6.3.2.1:
+  //   [Except in specific positions,] an lvalue that does not have
+  //   array type is converted to the value stored in the
+  //   designated object (and is no longer an lvalue).
+  if (E->isRValue()) {
+    // In C, function designators (i.e. expressions of function type)
+    // are r-values, but we still want to do function-to-pointer decay
+    // on them.  This is both technically correct and convenient for
+    // some clients.
+    if (!getLangOpts().CPlusPlus && E->getType()->isFunctionType())
+      return DefaultFunctionArrayConversion(E);
+
+    return Owned(E);
+  }
+
+  // Otherwise, this rule does not apply in C++, at least not for the moment.
+  if (getLangOpts().CPlusPlus) return Owned(E);
+
+  // GCC seems to also exclude expressions of incomplete enum type.
+  if (const EnumType *T = E->getType()->getAs<EnumType>()) {
+    if (!T->getDecl()->isComplete()) {
+      // FIXME: stupid workaround for a codegen bug!
+      E = ImpCastExprToType(E, Context.VoidTy, CK_ToVoid).take();
+      return Owned(E);
+    }
+  }
+
+  ExprResult Res = DefaultFunctionArrayLvalueConversion(E);
+  if (Res.isInvalid())
+    return Owned(E);
+  E = Res.take();
+
+  if (!E->getType()->isVoidType())
+    RequireCompleteType(E->getExprLoc(), E->getType(),
+                        diag::err_incomplete_type);
+  return Owned(E);
+}
+
+ExprResult Sema::ActOnFinishFullExpr(Expr *FE) {
+  ExprResult FullExpr = Owned(FE);
+
+  if (!FullExpr.get())
+    return ExprError();
+
+  if (DiagnoseUnexpandedParameterPack(FullExpr.get()))
+    return ExprError();
+
+  // Top-level message sends default to 'id' when we're in a debugger.
+  if (getLangOpts().DebuggerCastResultToId &&
+      FullExpr.get()->getType() == Context.UnknownAnyTy &&
+      isa<ObjCMessageExpr>(FullExpr.get())) {
+    FullExpr = forceUnknownAnyToType(FullExpr.take(), Context.getObjCIdType());
+    if (FullExpr.isInvalid())
+      return ExprError();
+  }
+  
+  FullExpr = CheckPlaceholderExpr(FullExpr.take());
+  if (FullExpr.isInvalid())
+    return ExprError();
+
+  FullExpr = IgnoredValueConversions(FullExpr.take());
+  if (FullExpr.isInvalid())
+    return ExprError();
+
+  CheckImplicitConversions(FullExpr.get(), FullExpr.get()->getExprLoc());
+  return MaybeCreateExprWithCleanups(FullExpr);
+}
+
+StmtResult Sema::ActOnFinishFullStmt(Stmt *FullStmt) {
+  if (!FullStmt) return StmtError();
+
+  return MaybeCreateStmtWithCleanups(FullStmt);
+}
+
+Sema::IfExistsResult 
+Sema::CheckMicrosoftIfExistsSymbol(Scope *S,
+                                   CXXScopeSpec &SS,
+                                   const DeclarationNameInfo &TargetNameInfo) {
+  DeclarationName TargetName = TargetNameInfo.getName();
+  if (!TargetName)
+    return IER_DoesNotExist;
+  
+  // If the name itself is dependent, then the result is dependent.
+  if (TargetName.isDependentName())
+    return IER_Dependent;
+  
+  // Do the redeclaration lookup in the current scope.
+  LookupResult R(*this, TargetNameInfo, Sema::LookupAnyName,
+                 Sema::NotForRedeclaration);
+  LookupParsedName(R, S, &SS);
+  R.suppressDiagnostics();
+  
+  switch (R.getResultKind()) {
+  case LookupResult::Found:
+  case LookupResult::FoundOverloaded:
+  case LookupResult::FoundUnresolvedValue:
+  case LookupResult::Ambiguous:
+    return IER_Exists;
+    
+  case LookupResult::NotFound:
+    return IER_DoesNotExist;
+    
+  case LookupResult::NotFoundInCurrentInstantiation:
+    return IER_Dependent;
+  }
+
+  llvm_unreachable("Invalid LookupResult Kind!");
+}
+
+Sema::IfExistsResult 
+Sema::CheckMicrosoftIfExistsSymbol(Scope *S, SourceLocation KeywordLoc,
+                                   bool IsIfExists, CXXScopeSpec &SS,
+                                   UnqualifiedId &Name) {
+  DeclarationNameInfo TargetNameInfo = GetNameFromUnqualifiedId(Name);
+  
+  // Check for unexpanded parameter packs.
+  SmallVector<UnexpandedParameterPack, 4> Unexpanded;
+  collectUnexpandedParameterPacks(SS, Unexpanded);
+  collectUnexpandedParameterPacks(TargetNameInfo, Unexpanded);
+  if (!Unexpanded.empty()) {
+    DiagnoseUnexpandedParameterPacks(KeywordLoc,
+                                     IsIfExists? UPPC_IfExists 
+                                               : UPPC_IfNotExists, 
+                                     Unexpanded);
+    return IER_Error;
+  }
+  
+  return CheckMicrosoftIfExistsSymbol(S, SS, TargetNameInfo);
+}
diff --git a/clang/lib/Sema/SemaExprMember.cpp b/clang/lib/Sema/SemaExprMember.cpp
new file mode 100644
index 0000000..6c84caa
--- /dev/null
+++ b/clang/lib/Sema/SemaExprMember.cpp
@@ -0,0 +1,1618 @@
+//===--- SemaExprMember.cpp - Semantic Analysis for Expressions -----------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+//  This file implements semantic analysis member access expressions.
+//
+//===----------------------------------------------------------------------===//
+#include "clang/Sema/SemaInternal.h"
+#include "clang/Sema/Lookup.h"
+#include "clang/Sema/Scope.h"
+#include "clang/AST/DeclCXX.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/AST/DeclTemplate.h"
+#include "clang/AST/ExprCXX.h"
+#include "clang/AST/ExprObjC.h"
+#include "clang/Lex/Preprocessor.h"
+
+using namespace clang;
+using namespace sema;
+
+/// Determines if the given class is provably not derived from all of
+/// the prospective base classes.
+static bool IsProvablyNotDerivedFrom(Sema &SemaRef,
+                                     CXXRecordDecl *Record,
+                            const llvm::SmallPtrSet<CXXRecordDecl*, 4> &Bases) {
+  if (Bases.count(Record->getCanonicalDecl()))
+    return false;
+
+  RecordDecl *RD = Record->getDefinition();
+  if (!RD) return false;
+  Record = cast<CXXRecordDecl>(RD);
+
+  for (CXXRecordDecl::base_class_iterator I = Record->bases_begin(),
+         E = Record->bases_end(); I != E; ++I) {
+    CanQualType BaseT = SemaRef.Context.getCanonicalType((*I).getType());
+    CanQual<RecordType> BaseRT = BaseT->getAs<RecordType>();
+    if (!BaseRT) return false;
+
+    CXXRecordDecl *BaseRecord = cast<CXXRecordDecl>(BaseRT->getDecl());
+    if (!IsProvablyNotDerivedFrom(SemaRef, BaseRecord, Bases))
+      return false;
+  }
+
+  return true;
+}
+
+enum IMAKind {
+  /// The reference is definitely not an instance member access.
+  IMA_Static,
+
+  /// The reference may be an implicit instance member access.
+  IMA_Mixed,
+
+  /// The reference may be to an instance member, but it might be invalid if
+  /// so, because the context is not an instance method.
+  IMA_Mixed_StaticContext,
+
+  /// The reference may be to an instance member, but it is invalid if
+  /// so, because the context is from an unrelated class.
+  IMA_Mixed_Unrelated,
+
+  /// The reference is definitely an implicit instance member access.
+  IMA_Instance,
+
+  /// The reference may be to an unresolved using declaration.
+  IMA_Unresolved,
+
+  /// The reference may be to an unresolved using declaration and the
+  /// context is not an instance method.
+  IMA_Unresolved_StaticContext,
+
+  // The reference refers to a field which is not a member of the containing
+  // class, which is allowed because we're in C++11 mode and the context is
+  // unevaluated.
+  IMA_Field_Uneval_Context,
+
+  /// All possible referrents are instance members and the current
+  /// context is not an instance method.
+  IMA_Error_StaticContext,
+
+  /// All possible referrents are instance members of an unrelated
+  /// class.
+  IMA_Error_Unrelated
+};
+
+/// The given lookup names class member(s) and is not being used for
+/// an address-of-member expression.  Classify the type of access
+/// according to whether it's possible that this reference names an
+/// instance member.  This is best-effort in dependent contexts; it is okay to
+/// conservatively answer "yes", in which case some errors will simply
+/// not be caught until template-instantiation.
+static IMAKind ClassifyImplicitMemberAccess(Sema &SemaRef,
+                                            Scope *CurScope,
+                                            const LookupResult &R) {
+  assert(!R.empty() && (*R.begin())->isCXXClassMember());
+
+  DeclContext *DC = SemaRef.getFunctionLevelDeclContext();
+
+  bool isStaticContext = SemaRef.CXXThisTypeOverride.isNull() &&
+    (!isa<CXXMethodDecl>(DC) || cast<CXXMethodDecl>(DC)->isStatic());
+
+  if (R.isUnresolvableResult())
+    return isStaticContext ? IMA_Unresolved_StaticContext : IMA_Unresolved;
+
+  // Collect all the declaring classes of instance members we find.
+  bool hasNonInstance = false;
+  bool isField = false;
+  llvm::SmallPtrSet<CXXRecordDecl*, 4> Classes;
+  for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I) {
+    NamedDecl *D = *I;
+
+    if (D->isCXXInstanceMember()) {
+      if (dyn_cast<FieldDecl>(D))
+        isField = true;
+
+      CXXRecordDecl *R = cast<CXXRecordDecl>(D->getDeclContext());
+      Classes.insert(R->getCanonicalDecl());
+    }
+    else
+      hasNonInstance = true;
+  }
+
+  // If we didn't find any instance members, it can't be an implicit
+  // member reference.
+  if (Classes.empty())
+    return IMA_Static;
+
+  bool IsCXX11UnevaluatedField = false;
+  if (SemaRef.getLangOpts().CPlusPlus0x && isField) {
+    // C++11 [expr.prim.general]p12:
+    //   An id-expression that denotes a non-static data member or non-static
+    //   member function of a class can only be used:
+    //   (...)
+    //   - if that id-expression denotes a non-static data member and it
+    //     appears in an unevaluated operand.
+    const Sema::ExpressionEvaluationContextRecord& record
+      = SemaRef.ExprEvalContexts.back();
+    if (record.Context == Sema::Unevaluated)
+      IsCXX11UnevaluatedField = true;
+  }
+
+  // If the current context is not an instance method, it can't be
+  // an implicit member reference.
+  if (isStaticContext) {
+    if (hasNonInstance)
+      return IMA_Mixed_StaticContext;
+
+    return IsCXX11UnevaluatedField ? IMA_Field_Uneval_Context
+                                   : IMA_Error_StaticContext;
+  }
+
+  CXXRecordDecl *contextClass;
+  if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(DC))
+    contextClass = MD->getParent()->getCanonicalDecl();
+  else
+    contextClass = cast<CXXRecordDecl>(DC);
+
+  // [class.mfct.non-static]p3: 
+  // ...is used in the body of a non-static member function of class X,
+  // if name lookup (3.4.1) resolves the name in the id-expression to a
+  // non-static non-type member of some class C [...]
+  // ...if C is not X or a base class of X, the class member access expression
+  // is ill-formed.
+  if (R.getNamingClass() &&
+      contextClass->getCanonicalDecl() !=
+        R.getNamingClass()->getCanonicalDecl() &&
+      contextClass->isProvablyNotDerivedFrom(R.getNamingClass()))
+    return hasNonInstance ? IMA_Mixed_Unrelated :
+           IsCXX11UnevaluatedField ? IMA_Field_Uneval_Context :
+                                     IMA_Error_Unrelated;
+
+  // If we can prove that the current context is unrelated to all the
+  // declaring classes, it can't be an implicit member reference (in
+  // which case it's an error if any of those members are selected).
+  if (IsProvablyNotDerivedFrom(SemaRef, contextClass, Classes))
+    return hasNonInstance ? IMA_Mixed_Unrelated :
+           IsCXX11UnevaluatedField ? IMA_Field_Uneval_Context :
+                                     IMA_Error_Unrelated;
+
+  return (hasNonInstance ? IMA_Mixed : IMA_Instance);
+}
+
+/// Diagnose a reference to a field with no object available.
+static void diagnoseInstanceReference(Sema &SemaRef,
+                                      const CXXScopeSpec &SS,
+                                      NamedDecl *Rep,
+                                      const DeclarationNameInfo &nameInfo) {
+  SourceLocation Loc = nameInfo.getLoc();
+  SourceRange Range(Loc);
+  if (SS.isSet()) Range.setBegin(SS.getRange().getBegin());
+
+  DeclContext *FunctionLevelDC = SemaRef.getFunctionLevelDeclContext();
+  CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(FunctionLevelDC);
+  CXXRecordDecl *ContextClass = Method ? Method->getParent() : 0;
+  CXXRecordDecl *RepClass = dyn_cast<CXXRecordDecl>(Rep->getDeclContext());
+
+  bool InStaticMethod = Method && Method->isStatic();
+  bool IsField = isa<FieldDecl>(Rep) || isa<IndirectFieldDecl>(Rep);
+
+  if (IsField && InStaticMethod)
+    // "invalid use of member 'x' in static member function"
+    SemaRef.Diag(Loc, diag::err_invalid_member_use_in_static_method)
+        << Range << nameInfo.getName();
+  else if (ContextClass && RepClass && SS.isEmpty() && !InStaticMethod &&
+           !RepClass->Equals(ContextClass) && RepClass->Encloses(ContextClass))
+    // Unqualified lookup in a non-static member function found a member of an
+    // enclosing class.
+    SemaRef.Diag(Loc, diag::err_nested_non_static_member_use)
+      << IsField << RepClass << nameInfo.getName() << ContextClass << Range;
+  else if (IsField)
+    SemaRef.Diag(Loc, diag::err_invalid_non_static_member_use)
+      << nameInfo.getName() << Range;
+  else
+    SemaRef.Diag(Loc, diag::err_member_call_without_object)
+      << Range;
+}
+
+/// Builds an expression which might be an implicit member expression.
+ExprResult
+Sema::BuildPossibleImplicitMemberExpr(const CXXScopeSpec &SS,
+                                      SourceLocation TemplateKWLoc,
+                                      LookupResult &R,
+                                const TemplateArgumentListInfo *TemplateArgs) {
+  switch (ClassifyImplicitMemberAccess(*this, CurScope, R)) {
+  case IMA_Instance:
+    return BuildImplicitMemberExpr(SS, TemplateKWLoc, R, TemplateArgs, true);
+
+  case IMA_Mixed:
+  case IMA_Mixed_Unrelated:
+  case IMA_Unresolved:
+    return BuildImplicitMemberExpr(SS, TemplateKWLoc, R, TemplateArgs, false);
+
+  case IMA_Field_Uneval_Context:
+    Diag(R.getNameLoc(), diag::warn_cxx98_compat_non_static_member_use)
+      << R.getLookupNameInfo().getName();
+    // Fall through.
+  case IMA_Static:
+  case IMA_Mixed_StaticContext:
+  case IMA_Unresolved_StaticContext:
+    if (TemplateArgs || TemplateKWLoc.isValid())
+      return BuildTemplateIdExpr(SS, TemplateKWLoc, R, false, TemplateArgs);
+    return BuildDeclarationNameExpr(SS, R, false);
+
+  case IMA_Error_StaticContext:
+  case IMA_Error_Unrelated:
+    diagnoseInstanceReference(*this, SS, R.getRepresentativeDecl(),
+                              R.getLookupNameInfo());
+    return ExprError();
+  }
+
+  llvm_unreachable("unexpected instance member access kind");
+}
+
+/// Check an ext-vector component access expression.
+///
+/// VK should be set in advance to the value kind of the base
+/// expression.
+static QualType
+CheckExtVectorComponent(Sema &S, QualType baseType, ExprValueKind &VK,
+                        SourceLocation OpLoc, const IdentifierInfo *CompName,
+                        SourceLocation CompLoc) {
+  // FIXME: Share logic with ExtVectorElementExpr::containsDuplicateElements,
+  // see FIXME there.
+  //
+  // FIXME: This logic can be greatly simplified by splitting it along
+  // halving/not halving and reworking the component checking.
+  const ExtVectorType *vecType = baseType->getAs<ExtVectorType>();
+
+  // The vector accessor can't exceed the number of elements.
+  const char *compStr = CompName->getNameStart();
+
+  // This flag determines whether or not the component is one of the four
+  // special names that indicate a subset of exactly half the elements are
+  // to be selected.
+  bool HalvingSwizzle = false;
+
+  // This flag determines whether or not CompName has an 's' char prefix,
+  // indicating that it is a string of hex values to be used as vector indices.
+  bool HexSwizzle = *compStr == 's' || *compStr == 'S';
+
+  bool HasRepeated = false;
+  bool HasIndex[16] = {};
+
+  int Idx;
+
+  // Check that we've found one of the special components, or that the component
+  // names must come from the same set.
+  if (!strcmp(compStr, "hi") || !strcmp(compStr, "lo") ||
+      !strcmp(compStr, "even") || !strcmp(compStr, "odd")) {
+    HalvingSwizzle = true;
+  } else if (!HexSwizzle &&
+             (Idx = vecType->getPointAccessorIdx(*compStr)) != -1) {
+    do {
+      if (HasIndex[Idx]) HasRepeated = true;
+      HasIndex[Idx] = true;
+      compStr++;
+    } while (*compStr && (Idx = vecType->getPointAccessorIdx(*compStr)) != -1);
+  } else {
+    if (HexSwizzle) compStr++;
+    while ((Idx = vecType->getNumericAccessorIdx(*compStr)) != -1) {
+      if (HasIndex[Idx]) HasRepeated = true;
+      HasIndex[Idx] = true;
+      compStr++;
+    }
+  }
+
+  if (!HalvingSwizzle && *compStr) {
+    // We didn't get to the end of the string. This means the component names
+    // didn't come from the same set *or* we encountered an illegal name.
+    S.Diag(OpLoc, diag::err_ext_vector_component_name_illegal)
+      << StringRef(compStr, 1) << SourceRange(CompLoc);
+    return QualType();
+  }
+
+  // Ensure no component accessor exceeds the width of the vector type it
+  // operates on.
+  if (!HalvingSwizzle) {
+    compStr = CompName->getNameStart();
+
+    if (HexSwizzle)
+      compStr++;
+
+    while (*compStr) {
+      if (!vecType->isAccessorWithinNumElements(*compStr++)) {
+        S.Diag(OpLoc, diag::err_ext_vector_component_exceeds_length)
+          << baseType << SourceRange(CompLoc);
+        return QualType();
+      }
+    }
+  }
+
+  // The component accessor looks fine - now we need to compute the actual type.
+  // The vector type is implied by the component accessor. For example,
+  // vec4.b is a float, vec4.xy is a vec2, vec4.rgb is a vec3, etc.
+  // vec4.s0 is a float, vec4.s23 is a vec3, etc.
+  // vec4.hi, vec4.lo, vec4.e, and vec4.o all return vec2.
+  unsigned CompSize = HalvingSwizzle ? (vecType->getNumElements() + 1) / 2
+                                     : CompName->getLength();
+  if (HexSwizzle)
+    CompSize--;
+
+  if (CompSize == 1)
+    return vecType->getElementType();
+
+  if (HasRepeated) VK = VK_RValue;
+
+  QualType VT = S.Context.getExtVectorType(vecType->getElementType(), CompSize);
+  // Now look up the TypeDefDecl from the vector type. Without this,
+  // diagostics look bad. We want extended vector types to appear built-in.
+  for (Sema::ExtVectorDeclsType::iterator 
+         I = S.ExtVectorDecls.begin(S.ExternalSource),
+         E = S.ExtVectorDecls.end(); 
+       I != E; ++I) {
+    if ((*I)->getUnderlyingType() == VT)
+      return S.Context.getTypedefType(*I);
+  }
+  
+  return VT; // should never get here (a typedef type should always be found).
+}
+
+static Decl *FindGetterSetterNameDeclFromProtocolList(const ObjCProtocolDecl*PDecl,
+                                                IdentifierInfo *Member,
+                                                const Selector &Sel,
+                                                ASTContext &Context) {
+  if (Member)
+    if (ObjCPropertyDecl *PD = PDecl->FindPropertyDeclaration(Member))
+      return PD;
+  if (ObjCMethodDecl *OMD = PDecl->getInstanceMethod(Sel))
+    return OMD;
+
+  for (ObjCProtocolDecl::protocol_iterator I = PDecl->protocol_begin(),
+       E = PDecl->protocol_end(); I != E; ++I) {
+    if (Decl *D = FindGetterSetterNameDeclFromProtocolList(*I, Member, Sel,
+                                                           Context))
+      return D;
+  }
+  return 0;
+}
+
+static Decl *FindGetterSetterNameDecl(const ObjCObjectPointerType *QIdTy,
+                                      IdentifierInfo *Member,
+                                      const Selector &Sel,
+                                      ASTContext &Context) {
+  // Check protocols on qualified interfaces.
+  Decl *GDecl = 0;
+  for (ObjCObjectPointerType::qual_iterator I = QIdTy->qual_begin(),
+       E = QIdTy->qual_end(); I != E; ++I) {
+    if (Member)
+      if (ObjCPropertyDecl *PD = (*I)->FindPropertyDeclaration(Member)) {
+        GDecl = PD;
+        break;
+      }
+    // Also must look for a getter or setter name which uses property syntax.
+    if (ObjCMethodDecl *OMD = (*I)->getInstanceMethod(Sel)) {
+      GDecl = OMD;
+      break;
+    }
+  }
+  if (!GDecl) {
+    for (ObjCObjectPointerType::qual_iterator I = QIdTy->qual_begin(),
+         E = QIdTy->qual_end(); I != E; ++I) {
+      // Search in the protocol-qualifier list of current protocol.
+      GDecl = FindGetterSetterNameDeclFromProtocolList(*I, Member, Sel, 
+                                                       Context);
+      if (GDecl)
+        return GDecl;
+    }
+  }
+  return GDecl;
+}
+
+ExprResult
+Sema::ActOnDependentMemberExpr(Expr *BaseExpr, QualType BaseType,
+                               bool IsArrow, SourceLocation OpLoc,
+                               const CXXScopeSpec &SS,
+                               SourceLocation TemplateKWLoc,
+                               NamedDecl *FirstQualifierInScope,
+                               const DeclarationNameInfo &NameInfo,
+                               const TemplateArgumentListInfo *TemplateArgs) {
+  // Even in dependent contexts, try to diagnose base expressions with
+  // obviously wrong types, e.g.:
+  //
+  // T* t;
+  // t.f;
+  //
+  // In Obj-C++, however, the above expression is valid, since it could be
+  // accessing the 'f' property if T is an Obj-C interface. The extra check
+  // allows this, while still reporting an error if T is a struct pointer.
+  if (!IsArrow) {
+    const PointerType *PT = BaseType->getAs<PointerType>();
+    if (PT && (!getLangOpts().ObjC1 ||
+               PT->getPointeeType()->isRecordType())) {
+      assert(BaseExpr && "cannot happen with implicit member accesses");
+      Diag(NameInfo.getLoc(), diag::err_typecheck_member_reference_struct_union)
+        << BaseType << BaseExpr->getSourceRange();
+      return ExprError();
+    }
+  }
+
+  assert(BaseType->isDependentType() ||
+         NameInfo.getName().isDependentName() ||
+         isDependentScopeSpecifier(SS));
+
+  // Get the type being accessed in BaseType.  If this is an arrow, the BaseExpr
+  // must have pointer type, and the accessed type is the pointee.
+  return Owned(CXXDependentScopeMemberExpr::Create(Context, BaseExpr, BaseType,
+                                                   IsArrow, OpLoc,
+                                               SS.getWithLocInContext(Context),
+                                                   TemplateKWLoc,
+                                                   FirstQualifierInScope,
+                                                   NameInfo, TemplateArgs));
+}
+
+/// We know that the given qualified member reference points only to
+/// declarations which do not belong to the static type of the base
+/// expression.  Diagnose the problem.
+static void DiagnoseQualifiedMemberReference(Sema &SemaRef,
+                                             Expr *BaseExpr,
+                                             QualType BaseType,
+                                             const CXXScopeSpec &SS,
+                                             NamedDecl *rep,
+                                       const DeclarationNameInfo &nameInfo) {
+  // If this is an implicit member access, use a different set of
+  // diagnostics.
+  if (!BaseExpr)
+    return diagnoseInstanceReference(SemaRef, SS, rep, nameInfo);
+
+  SemaRef.Diag(nameInfo.getLoc(), diag::err_qualified_member_of_unrelated)
+    << SS.getRange() << rep << BaseType;
+}
+
+// Check whether the declarations we found through a nested-name
+// specifier in a member expression are actually members of the base
+// type.  The restriction here is:
+//
+//   C++ [expr.ref]p2:
+//     ... In these cases, the id-expression shall name a
+//     member of the class or of one of its base classes.
+//
+// So it's perfectly legitimate for the nested-name specifier to name
+// an unrelated class, and for us to find an overload set including
+// decls from classes which are not superclasses, as long as the decl
+// we actually pick through overload resolution is from a superclass.
+bool Sema::CheckQualifiedMemberReference(Expr *BaseExpr,
+                                         QualType BaseType,
+                                         const CXXScopeSpec &SS,
+                                         const LookupResult &R) {
+  const RecordType *BaseRT = BaseType->getAs<RecordType>();
+  if (!BaseRT) {
+    // We can't check this yet because the base type is still
+    // dependent.
+    assert(BaseType->isDependentType());
+    return false;
+  }
+  CXXRecordDecl *BaseRecord = cast<CXXRecordDecl>(BaseRT->getDecl());
+
+  for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I) {
+    // If this is an implicit member reference and we find a
+    // non-instance member, it's not an error.
+    if (!BaseExpr && !(*I)->isCXXInstanceMember())
+      return false;
+
+    // Note that we use the DC of the decl, not the underlying decl.
+    DeclContext *DC = (*I)->getDeclContext();
+    while (DC->isTransparentContext())
+      DC = DC->getParent();
+
+    if (!DC->isRecord())
+      continue;
+    
+    llvm::SmallPtrSet<CXXRecordDecl*,4> MemberRecord;
+    MemberRecord.insert(cast<CXXRecordDecl>(DC)->getCanonicalDecl());
+
+    if (!IsProvablyNotDerivedFrom(*this, BaseRecord, MemberRecord))
+      return false;
+  }
+
+  DiagnoseQualifiedMemberReference(*this, BaseExpr, BaseType, SS,
+                                   R.getRepresentativeDecl(),
+                                   R.getLookupNameInfo());
+  return true;
+}
+
+namespace {
+
+// Callback to only accept typo corrections that are either a ValueDecl or a
+// FunctionTemplateDecl.
+class RecordMemberExprValidatorCCC : public CorrectionCandidateCallback {
+ public:
+  virtual bool ValidateCandidate(const TypoCorrection &candidate) {
+    NamedDecl *ND = candidate.getCorrectionDecl();
+    return ND && (isa<ValueDecl>(ND) || isa<FunctionTemplateDecl>(ND));
+  }
+};
+
+}
+
+static bool
+LookupMemberExprInRecord(Sema &SemaRef, LookupResult &R, 
+                         SourceRange BaseRange, const RecordType *RTy,
+                         SourceLocation OpLoc, CXXScopeSpec &SS,
+                         bool HasTemplateArgs) {
+  RecordDecl *RDecl = RTy->getDecl();
+  if (!SemaRef.isThisOutsideMemberFunctionBody(QualType(RTy, 0)) &&
+      SemaRef.RequireCompleteType(OpLoc, QualType(RTy, 0),
+                              SemaRef.PDiag(diag::err_typecheck_incomplete_tag)
+                                    << BaseRange))
+    return true;
+
+  if (HasTemplateArgs) {
+    // LookupTemplateName doesn't expect these both to exist simultaneously.
+    QualType ObjectType = SS.isSet() ? QualType() : QualType(RTy, 0);
+
+    bool MOUS;
+    SemaRef.LookupTemplateName(R, 0, SS, ObjectType, false, MOUS);
+    return false;
+  }
+
+  DeclContext *DC = RDecl;
+  if (SS.isSet()) {
+    // If the member name was a qualified-id, look into the
+    // nested-name-specifier.
+    DC = SemaRef.computeDeclContext(SS, false);
+
+    if (SemaRef.RequireCompleteDeclContext(SS, DC)) {
+      SemaRef.Diag(SS.getRange().getEnd(), diag::err_typecheck_incomplete_tag)
+        << SS.getRange() << DC;
+      return true;
+    }
+
+    assert(DC && "Cannot handle non-computable dependent contexts in lookup");
+
+    if (!isa<TypeDecl>(DC)) {
+      SemaRef.Diag(R.getNameLoc(), diag::err_qualified_member_nonclass)
+        << DC << SS.getRange();
+      return true;
+    }
+  }
+
+  // The record definition is complete, now look up the member.
+  SemaRef.LookupQualifiedName(R, DC);
+
+  if (!R.empty())
+    return false;
+
+  // We didn't find anything with the given name, so try to correct
+  // for typos.
+  DeclarationName Name = R.getLookupName();
+  RecordMemberExprValidatorCCC Validator;
+  TypoCorrection Corrected = SemaRef.CorrectTypo(R.getLookupNameInfo(),
+                                                 R.getLookupKind(), NULL,
+                                                 &SS, Validator, DC);
+  R.clear();
+  if (NamedDecl *ND = Corrected.getCorrectionDecl()) {
+    std::string CorrectedStr(
+        Corrected.getAsString(SemaRef.getLangOpts()));
+    std::string CorrectedQuotedStr(
+        Corrected.getQuoted(SemaRef.getLangOpts()));
+    R.setLookupName(Corrected.getCorrection());
+    R.addDecl(ND);
+    SemaRef.Diag(R.getNameLoc(), diag::err_no_member_suggest)
+      << Name << DC << CorrectedQuotedStr << SS.getRange()
+      << FixItHint::CreateReplacement(R.getNameLoc(), CorrectedStr);
+    SemaRef.Diag(ND->getLocation(), diag::note_previous_decl)
+      << ND->getDeclName();
+  }
+
+  return false;
+}
+
+ExprResult
+Sema::BuildMemberReferenceExpr(Expr *Base, QualType BaseType,
+                               SourceLocation OpLoc, bool IsArrow,
+                               CXXScopeSpec &SS,
+                               SourceLocation TemplateKWLoc,
+                               NamedDecl *FirstQualifierInScope,
+                               const DeclarationNameInfo &NameInfo,
+                               const TemplateArgumentListInfo *TemplateArgs) {
+  if (BaseType->isDependentType() ||
+      (SS.isSet() && isDependentScopeSpecifier(SS)))
+    return ActOnDependentMemberExpr(Base, BaseType,
+                                    IsArrow, OpLoc,
+                                    SS, TemplateKWLoc, FirstQualifierInScope,
+                                    NameInfo, TemplateArgs);
+
+  LookupResult R(*this, NameInfo, LookupMemberName);
+
+  // Implicit member accesses.
+  if (!Base) {
+    QualType RecordTy = BaseType;
+    if (IsArrow) RecordTy = RecordTy->getAs<PointerType>()->getPointeeType();
+    if (LookupMemberExprInRecord(*this, R, SourceRange(),
+                                 RecordTy->getAs<RecordType>(),
+                                 OpLoc, SS, TemplateArgs != 0))
+      return ExprError();
+
+  // Explicit member accesses.
+  } else {
+    ExprResult BaseResult = Owned(Base);
+    ExprResult Result =
+      LookupMemberExpr(R, BaseResult, IsArrow, OpLoc,
+                       SS, /*ObjCImpDecl*/ 0, TemplateArgs != 0);
+
+    if (BaseResult.isInvalid())
+      return ExprError();
+    Base = BaseResult.take();
+
+    if (Result.isInvalid()) {
+      Owned(Base);
+      return ExprError();
+    }
+
+    if (Result.get())
+      return move(Result);
+
+    // LookupMemberExpr can modify Base, and thus change BaseType
+    BaseType = Base->getType();
+  }
+
+  return BuildMemberReferenceExpr(Base, BaseType,
+                                  OpLoc, IsArrow, SS, TemplateKWLoc,
+                                  FirstQualifierInScope, R, TemplateArgs);
+}
+
+static ExprResult
+BuildFieldReferenceExpr(Sema &S, Expr *BaseExpr, bool IsArrow,
+                        const CXXScopeSpec &SS, FieldDecl *Field,
+                        DeclAccessPair FoundDecl,
+                        const DeclarationNameInfo &MemberNameInfo);
+
+ExprResult
+Sema::BuildAnonymousStructUnionMemberReference(const CXXScopeSpec &SS,
+                                               SourceLocation loc,
+                                               IndirectFieldDecl *indirectField,
+                                               Expr *baseObjectExpr,
+                                               SourceLocation opLoc) {
+  // First, build the expression that refers to the base object.
+  
+  bool baseObjectIsPointer = false;
+  Qualifiers baseQuals;
+  
+  // Case 1:  the base of the indirect field is not a field.
+  VarDecl *baseVariable = indirectField->getVarDecl();
+  CXXScopeSpec EmptySS;
+  if (baseVariable) {
+    assert(baseVariable->getType()->isRecordType());
+    
+    // In principle we could have a member access expression that
+    // accesses an anonymous struct/union that's a static member of
+    // the base object's class.  However, under the current standard,
+    // static data members cannot be anonymous structs or unions.
+    // Supporting this is as easy as building a MemberExpr here.
+    assert(!baseObjectExpr && "anonymous struct/union is static data member?");
+    
+    DeclarationNameInfo baseNameInfo(DeclarationName(), loc);
+    
+    ExprResult result 
+      = BuildDeclarationNameExpr(EmptySS, baseNameInfo, baseVariable);
+    if (result.isInvalid()) return ExprError();
+    
+    baseObjectExpr = result.take();    
+    baseObjectIsPointer = false;
+    baseQuals = baseObjectExpr->getType().getQualifiers();
+    
+    // Case 2: the base of the indirect field is a field and the user
+    // wrote a member expression.
+  } else if (baseObjectExpr) {
+    // The caller provided the base object expression. Determine
+    // whether its a pointer and whether it adds any qualifiers to the
+    // anonymous struct/union fields we're looking into.
+    QualType objectType = baseObjectExpr->getType();
+    
+    if (const PointerType *ptr = objectType->getAs<PointerType>()) {
+      baseObjectIsPointer = true;
+      objectType = ptr->getPointeeType();
+    } else {
+      baseObjectIsPointer = false;
+    }
+    baseQuals = objectType.getQualifiers();
+    
+    // Case 3: the base of the indirect field is a field and we should
+    // build an implicit member access.
+  } else {
+    // We've found a member of an anonymous struct/union that is
+    // inside a non-anonymous struct/union, so in a well-formed
+    // program our base object expression is "this".
+    QualType ThisTy = getCurrentThisType();
+    if (ThisTy.isNull()) {
+      Diag(loc, diag::err_invalid_member_use_in_static_method)
+        << indirectField->getDeclName();
+      return ExprError();
+    }
+    
+    // Our base object expression is "this".
+    CheckCXXThisCapture(loc);
+    baseObjectExpr 
+      = new (Context) CXXThisExpr(loc, ThisTy, /*isImplicit=*/ true);
+    baseObjectIsPointer = true;
+    baseQuals = ThisTy->castAs<PointerType>()->getPointeeType().getQualifiers();
+  }
+  
+  // Build the implicit member references to the field of the
+  // anonymous struct/union.
+  Expr *result = baseObjectExpr;
+  IndirectFieldDecl::chain_iterator
+  FI = indirectField->chain_begin(), FEnd = indirectField->chain_end();
+  
+  // Build the first member access in the chain with full information.
+  if (!baseVariable) {
+    FieldDecl *field = cast<FieldDecl>(*FI);
+    
+    // FIXME: use the real found-decl info!
+    DeclAccessPair foundDecl = DeclAccessPair::make(field, field->getAccess());
+    
+    // Make a nameInfo that properly uses the anonymous name.
+    DeclarationNameInfo memberNameInfo(field->getDeclName(), loc);
+    
+    result = BuildFieldReferenceExpr(*this, result, baseObjectIsPointer,
+                                     EmptySS, field, foundDecl,
+                                     memberNameInfo).take();
+    baseObjectIsPointer = false;
+    
+    // FIXME: check qualified member access
+  }
+  
+  // In all cases, we should now skip the first declaration in the chain.
+  ++FI;
+  
+  while (FI != FEnd) {
+    FieldDecl *field = cast<FieldDecl>(*FI++);
+    
+    // FIXME: these are somewhat meaningless
+    DeclarationNameInfo memberNameInfo(field->getDeclName(), loc);
+    DeclAccessPair foundDecl = DeclAccessPair::make(field, field->getAccess());
+    
+    result = BuildFieldReferenceExpr(*this, result, /*isarrow*/ false,
+                                     (FI == FEnd? SS : EmptySS), field, 
+                                     foundDecl, memberNameInfo).take();
+  }
+  
+  return Owned(result);
+}
+
+/// \brief Build a MemberExpr AST node.
+static MemberExpr *BuildMemberExpr(Sema &SemaRef,
+                                   ASTContext &C, Expr *Base, bool isArrow,
+                                   const CXXScopeSpec &SS,
+                                   SourceLocation TemplateKWLoc,
+                                   ValueDecl *Member,
+                                   DeclAccessPair FoundDecl,
+                                   const DeclarationNameInfo &MemberNameInfo,
+                                   QualType Ty,
+                                   ExprValueKind VK, ExprObjectKind OK,
+                                   const TemplateArgumentListInfo *TemplateArgs = 0) {
+  assert((!isArrow || Base->isRValue()) && "-> base must be a pointer rvalue");
+  MemberExpr *E =
+      MemberExpr::Create(C, Base, isArrow, SS.getWithLocInContext(C),
+                         TemplateKWLoc, Member, FoundDecl, MemberNameInfo,
+                         TemplateArgs, Ty, VK, OK);
+  SemaRef.MarkMemberReferenced(E);
+  return E;
+}
+
+ExprResult
+Sema::BuildMemberReferenceExpr(Expr *BaseExpr, QualType BaseExprType,
+                               SourceLocation OpLoc, bool IsArrow,
+                               const CXXScopeSpec &SS,
+                               SourceLocation TemplateKWLoc,
+                               NamedDecl *FirstQualifierInScope,
+                               LookupResult &R,
+                         const TemplateArgumentListInfo *TemplateArgs,
+                               bool SuppressQualifierCheck) {
+  QualType BaseType = BaseExprType;
+  if (IsArrow) {
+    assert(BaseType->isPointerType());
+    BaseType = BaseType->castAs<PointerType>()->getPointeeType();
+  }
+  R.setBaseObjectType(BaseType);
+
+  const DeclarationNameInfo &MemberNameInfo = R.getLookupNameInfo();
+  DeclarationName MemberName = MemberNameInfo.getName();
+  SourceLocation MemberLoc = MemberNameInfo.getLoc();
+
+  if (R.isAmbiguous())
+    return ExprError();
+
+  if (R.empty()) {
+    // Rederive where we looked up.
+    DeclContext *DC = (SS.isSet()
+                       ? computeDeclContext(SS, false)
+                       : BaseType->getAs<RecordType>()->getDecl());
+
+    Diag(R.getNameLoc(), diag::err_no_member)
+      << MemberName << DC
+      << (BaseExpr ? BaseExpr->getSourceRange() : SourceRange());
+    return ExprError();
+  }
+
+  // Diagnose lookups that find only declarations from a non-base
+  // type.  This is possible for either qualified lookups (which may
+  // have been qualified with an unrelated type) or implicit member
+  // expressions (which were found with unqualified lookup and thus
+  // may have come from an enclosing scope).  Note that it's okay for
+  // lookup to find declarations from a non-base type as long as those
+  // aren't the ones picked by overload resolution.
+  if ((SS.isSet() || !BaseExpr ||
+       (isa<CXXThisExpr>(BaseExpr) &&
+        cast<CXXThisExpr>(BaseExpr)->isImplicit())) &&
+      !SuppressQualifierCheck &&
+      CheckQualifiedMemberReference(BaseExpr, BaseType, SS, R))
+    return ExprError();
+  
+  // Construct an unresolved result if we in fact got an unresolved
+  // result.
+  if (R.isOverloadedResult() || R.isUnresolvableResult()) {
+    // Suppress any lookup-related diagnostics; we'll do these when we
+    // pick a member.
+    R.suppressDiagnostics();
+
+    UnresolvedMemberExpr *MemExpr
+      = UnresolvedMemberExpr::Create(Context, R.isUnresolvableResult(),
+                                     BaseExpr, BaseExprType,
+                                     IsArrow, OpLoc,
+                                     SS.getWithLocInContext(Context),
+                                     TemplateKWLoc, MemberNameInfo,
+                                     TemplateArgs, R.begin(), R.end());
+
+    return Owned(MemExpr);
+  }
+
+  assert(R.isSingleResult());
+  DeclAccessPair FoundDecl = R.begin().getPair();
+  NamedDecl *MemberDecl = R.getFoundDecl();
+
+  // FIXME: diagnose the presence of template arguments now.
+
+  // If the decl being referenced had an error, return an error for this
+  // sub-expr without emitting another error, in order to avoid cascading
+  // error cases.
+  if (MemberDecl->isInvalidDecl())
+    return ExprError();
+
+  // Handle the implicit-member-access case.
+  if (!BaseExpr) {
+    // If this is not an instance member, convert to a non-member access.
+    if (!MemberDecl->isCXXInstanceMember())
+      return BuildDeclarationNameExpr(SS, R.getLookupNameInfo(), MemberDecl);
+
+    SourceLocation Loc = R.getNameLoc();
+    if (SS.getRange().isValid())
+      Loc = SS.getRange().getBegin();
+    CheckCXXThisCapture(Loc);
+    BaseExpr = new (Context) CXXThisExpr(Loc, BaseExprType,/*isImplicit=*/true);
+  }
+
+  bool ShouldCheckUse = true;
+  if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(MemberDecl)) {
+    // Don't diagnose the use of a virtual member function unless it's
+    // explicitly qualified.
+    if (MD->isVirtual() && !SS.isSet())
+      ShouldCheckUse = false;
+  }
+
+  // Check the use of this member.
+  if (ShouldCheckUse && DiagnoseUseOfDecl(MemberDecl, MemberLoc)) {
+    Owned(BaseExpr);
+    return ExprError();
+  }
+
+  if (FieldDecl *FD = dyn_cast<FieldDecl>(MemberDecl))
+    return BuildFieldReferenceExpr(*this, BaseExpr, IsArrow,
+                                   SS, FD, FoundDecl, MemberNameInfo);
+
+  if (IndirectFieldDecl *FD = dyn_cast<IndirectFieldDecl>(MemberDecl))
+    // We may have found a field within an anonymous union or struct
+    // (C++ [class.union]).
+    return BuildAnonymousStructUnionMemberReference(SS, MemberLoc, FD,
+                                                    BaseExpr, OpLoc);
+
+  if (VarDecl *Var = dyn_cast<VarDecl>(MemberDecl)) {
+    return Owned(BuildMemberExpr(*this, Context, BaseExpr, IsArrow, SS,
+                                 TemplateKWLoc, Var, FoundDecl, MemberNameInfo,
+                                 Var->getType().getNonReferenceType(),
+                                 VK_LValue, OK_Ordinary));
+  }
+
+  if (CXXMethodDecl *MemberFn = dyn_cast<CXXMethodDecl>(MemberDecl)) {
+    ExprValueKind valueKind;
+    QualType type;
+    if (MemberFn->isInstance()) {
+      valueKind = VK_RValue;
+      type = Context.BoundMemberTy;
+    } else {
+      valueKind = VK_LValue;
+      type = MemberFn->getType();
+    }
+
+    return Owned(BuildMemberExpr(*this, Context, BaseExpr, IsArrow, SS, 
+                                 TemplateKWLoc, MemberFn, FoundDecl, 
+                                 MemberNameInfo, type, valueKind,
+                                 OK_Ordinary));
+  }
+  assert(!isa<FunctionDecl>(MemberDecl) && "member function not C++ method?");
+
+  if (EnumConstantDecl *Enum = dyn_cast<EnumConstantDecl>(MemberDecl)) {
+    return Owned(BuildMemberExpr(*this, Context, BaseExpr, IsArrow, SS,
+                                 TemplateKWLoc, Enum, FoundDecl, MemberNameInfo,
+                                 Enum->getType(), VK_RValue, OK_Ordinary));
+  }
+
+  Owned(BaseExpr);
+
+  // We found something that we didn't expect. Complain.
+  if (isa<TypeDecl>(MemberDecl))
+    Diag(MemberLoc, diag::err_typecheck_member_reference_type)
+      << MemberName << BaseType << int(IsArrow);
+  else
+    Diag(MemberLoc, diag::err_typecheck_member_reference_unknown)
+      << MemberName << BaseType << int(IsArrow);
+
+  Diag(MemberDecl->getLocation(), diag::note_member_declared_here)
+    << MemberName;
+  R.suppressDiagnostics();
+  return ExprError();
+}
+
+/// Given that normal member access failed on the given expression,
+/// and given that the expression's type involves builtin-id or
+/// builtin-Class, decide whether substituting in the redefinition
+/// types would be profitable.  The redefinition type is whatever
+/// this translation unit tried to typedef to id/Class;  we store
+/// it to the side and then re-use it in places like this.
+static bool ShouldTryAgainWithRedefinitionType(Sema &S, ExprResult &base) {
+  const ObjCObjectPointerType *opty
+    = base.get()->getType()->getAs<ObjCObjectPointerType>();
+  if (!opty) return false;
+
+  const ObjCObjectType *ty = opty->getObjectType();
+
+  QualType redef;
+  if (ty->isObjCId()) {
+    redef = S.Context.getObjCIdRedefinitionType();
+  } else if (ty->isObjCClass()) {
+    redef = S.Context.getObjCClassRedefinitionType();
+  } else {
+    return false;
+  }
+
+  // Do the substitution as long as the redefinition type isn't just a
+  // possibly-qualified pointer to builtin-id or builtin-Class again.
+  opty = redef->getAs<ObjCObjectPointerType>();
+  if (opty && !opty->getObjectType()->getInterface() != 0)
+    return false;
+
+  base = S.ImpCastExprToType(base.take(), redef, CK_BitCast);
+  return true;
+}
+
+static bool isRecordType(QualType T) {
+  return T->isRecordType();
+}
+static bool isPointerToRecordType(QualType T) {
+  if (const PointerType *PT = T->getAs<PointerType>())
+    return PT->getPointeeType()->isRecordType();
+  return false;
+}
+
+/// Perform conversions on the LHS of a member access expression.
+ExprResult
+Sema::PerformMemberExprBaseConversion(Expr *Base, bool IsArrow) {
+  if (IsArrow && !Base->getType()->isFunctionType())
+    return DefaultFunctionArrayLvalueConversion(Base);
+
+  return CheckPlaceholderExpr(Base);
+}
+
+/// Look up the given member of the given non-type-dependent
+/// expression.  This can return in one of two ways:
+///  * If it returns a sentinel null-but-valid result, the caller will
+///    assume that lookup was performed and the results written into
+///    the provided structure.  It will take over from there.
+///  * Otherwise, the returned expression will be produced in place of
+///    an ordinary member expression.
+///
+/// The ObjCImpDecl bit is a gross hack that will need to be properly
+/// fixed for ObjC++.
+ExprResult
+Sema::LookupMemberExpr(LookupResult &R, ExprResult &BaseExpr,
+                       bool &IsArrow, SourceLocation OpLoc,
+                       CXXScopeSpec &SS,
+                       Decl *ObjCImpDecl, bool HasTemplateArgs) {
+  assert(BaseExpr.get() && "no base expression");
+
+  // Perform default conversions.
+  BaseExpr = PerformMemberExprBaseConversion(BaseExpr.take(), IsArrow);
+  if (BaseExpr.isInvalid())
+    return ExprError();
+
+  QualType BaseType = BaseExpr.get()->getType();
+  assert(!BaseType->isDependentType());
+
+  DeclarationName MemberName = R.getLookupName();
+  SourceLocation MemberLoc = R.getNameLoc();
+
+  // For later type-checking purposes, turn arrow accesses into dot
+  // accesses.  The only access type we support that doesn't follow
+  // the C equivalence "a->b === (*a).b" is ObjC property accesses,
+  // and those never use arrows, so this is unaffected.
+  if (IsArrow) {
+    if (const PointerType *Ptr = BaseType->getAs<PointerType>())
+      BaseType = Ptr->getPointeeType();
+    else if (const ObjCObjectPointerType *Ptr
+               = BaseType->getAs<ObjCObjectPointerType>())
+      BaseType = Ptr->getPointeeType();
+    else if (BaseType->isRecordType()) {
+      // Recover from arrow accesses to records, e.g.:
+      //   struct MyRecord foo;
+      //   foo->bar
+      // This is actually well-formed in C++ if MyRecord has an
+      // overloaded operator->, but that should have been dealt with
+      // by now.
+      Diag(OpLoc, diag::err_typecheck_member_reference_suggestion)
+        << BaseType << int(IsArrow) << BaseExpr.get()->getSourceRange()
+        << FixItHint::CreateReplacement(OpLoc, ".");
+      IsArrow = false;
+    } else if (BaseType->isFunctionType()) {
+      goto fail;
+    } else {
+      Diag(MemberLoc, diag::err_typecheck_member_reference_arrow)
+        << BaseType << BaseExpr.get()->getSourceRange();
+      return ExprError();
+    }
+  }
+
+  // Handle field access to simple records.
+  if (const RecordType *RTy = BaseType->getAs<RecordType>()) {
+    if (LookupMemberExprInRecord(*this, R, BaseExpr.get()->getSourceRange(),
+                                 RTy, OpLoc, SS, HasTemplateArgs))
+      return ExprError();
+
+    // Returning valid-but-null is how we indicate to the caller that
+    // the lookup result was filled in.
+    return Owned((Expr*) 0);
+  }
+
+  // Handle ivar access to Objective-C objects.
+  if (const ObjCObjectType *OTy = BaseType->getAs<ObjCObjectType>()) {
+    if (!SS.isEmpty() && !SS.isInvalid()) {
+      Diag(SS.getRange().getBegin(), diag::err_qualified_objc_access)
+        << 1 << SS.getScopeRep()
+        << FixItHint::CreateRemoval(SS.getRange());
+      SS.clear();
+    }
+    
+    IdentifierInfo *Member = MemberName.getAsIdentifierInfo();
+
+    // There are three cases for the base type:
+    //   - builtin id (qualified or unqualified)
+    //   - builtin Class (qualified or unqualified)
+    //   - an interface
+    ObjCInterfaceDecl *IDecl = OTy->getInterface();
+    if (!IDecl) {
+      if (getLangOpts().ObjCAutoRefCount &&
+          (OTy->isObjCId() || OTy->isObjCClass()))
+        goto fail;
+      // There's an implicit 'isa' ivar on all objects.
+      // But we only actually find it this way on objects of type 'id',
+      // apparently.ghjg
+      if (OTy->isObjCId() && Member->isStr("isa")) {
+        Diag(MemberLoc, diag::warn_objc_isa_use);
+        return Owned(new (Context) ObjCIsaExpr(BaseExpr.take(), IsArrow, MemberLoc,
+                                               Context.getObjCClassType()));
+      }
+
+      if (ShouldTryAgainWithRedefinitionType(*this, BaseExpr))
+        return LookupMemberExpr(R, BaseExpr, IsArrow, OpLoc, SS,
+                                ObjCImpDecl, HasTemplateArgs);
+      goto fail;
+    }
+
+    if (RequireCompleteType(OpLoc, BaseType, 
+                            PDiag(diag::err_typecheck_incomplete_tag)
+                              << BaseExpr.get()->getSourceRange()))
+      return ExprError();
+    
+    ObjCInterfaceDecl *ClassDeclared = 0;
+    ObjCIvarDecl *IV = IDecl->lookupInstanceVariable(Member, ClassDeclared);
+
+    if (!IV) {
+      // Attempt to correct for typos in ivar names.
+      DeclFilterCCC<ObjCIvarDecl> Validator;
+      Validator.IsObjCIvarLookup = IsArrow;
+      if (TypoCorrection Corrected = CorrectTypo(R.getLookupNameInfo(),
+                                                 LookupMemberName, NULL, NULL,
+                                                 Validator, IDecl)) {
+        IV = Corrected.getCorrectionDeclAs<ObjCIvarDecl>();
+        Diag(R.getNameLoc(),
+             diag::err_typecheck_member_reference_ivar_suggest)
+          << IDecl->getDeclName() << MemberName << IV->getDeclName()
+          << FixItHint::CreateReplacement(R.getNameLoc(),
+                                          IV->getNameAsString());
+        Diag(IV->getLocation(), diag::note_previous_decl)
+          << IV->getDeclName();
+        
+        // Figure out the class that declares the ivar.
+        assert(!ClassDeclared);
+        Decl *D = cast<Decl>(IV->getDeclContext());
+        if (ObjCCategoryDecl *CAT = dyn_cast<ObjCCategoryDecl>(D))
+          D = CAT->getClassInterface();
+        ClassDeclared = cast<ObjCInterfaceDecl>(D);
+      } else {
+        if (IsArrow && IDecl->FindPropertyDeclaration(Member)) {
+          Diag(MemberLoc, 
+          diag::err_property_found_suggest)
+          << Member << BaseExpr.get()->getType()
+          << FixItHint::CreateReplacement(OpLoc, ".");
+          return ExprError();
+        }
+
+        Diag(MemberLoc, diag::err_typecheck_member_reference_ivar)
+          << IDecl->getDeclName() << MemberName
+          << BaseExpr.get()->getSourceRange();
+        return ExprError();
+      }
+    }
+    
+    assert(ClassDeclared);
+
+    // If the decl being referenced had an error, return an error for this
+    // sub-expr without emitting another error, in order to avoid cascading
+    // error cases.
+    if (IV->isInvalidDecl())
+      return ExprError();
+
+    // Check whether we can reference this field.
+    if (DiagnoseUseOfDecl(IV, MemberLoc))
+      return ExprError();
+    if (IV->getAccessControl() != ObjCIvarDecl::Public &&
+        IV->getAccessControl() != ObjCIvarDecl::Package) {
+      ObjCInterfaceDecl *ClassOfMethodDecl = 0;
+      if (ObjCMethodDecl *MD = getCurMethodDecl())
+        ClassOfMethodDecl =  MD->getClassInterface();
+      else if (ObjCImpDecl && getCurFunctionDecl()) {
+        // Case of a c-function declared inside an objc implementation.
+        // FIXME: For a c-style function nested inside an objc implementation
+        // class, there is no implementation context available, so we pass
+        // down the context as argument to this routine. Ideally, this context
+        // need be passed down in the AST node and somehow calculated from the
+        // AST for a function decl.
+        if (ObjCImplementationDecl *IMPD =
+              dyn_cast<ObjCImplementationDecl>(ObjCImpDecl))
+          ClassOfMethodDecl = IMPD->getClassInterface();
+        else if (ObjCCategoryImplDecl* CatImplClass =
+                   dyn_cast<ObjCCategoryImplDecl>(ObjCImpDecl))
+          ClassOfMethodDecl = CatImplClass->getClassInterface();
+      }
+      if (!getLangOpts().DebuggerSupport) {
+        if (IV->getAccessControl() == ObjCIvarDecl::Private) {
+          if (!declaresSameEntity(ClassDeclared, IDecl) ||
+              !declaresSameEntity(ClassOfMethodDecl, ClassDeclared))
+            Diag(MemberLoc, diag::error_private_ivar_access)
+              << IV->getDeclName();
+        } else if (!IDecl->isSuperClassOf(ClassOfMethodDecl))
+          // @protected
+          Diag(MemberLoc, diag::error_protected_ivar_access)
+            << IV->getDeclName();
+      }
+    }
+    if (getLangOpts().ObjCAutoRefCount) {
+      Expr *BaseExp = BaseExpr.get()->IgnoreParenImpCasts();
+      if (UnaryOperator *UO = dyn_cast<UnaryOperator>(BaseExp))
+        if (UO->getOpcode() == UO_Deref)
+          BaseExp = UO->getSubExpr()->IgnoreParenCasts();
+      
+      if (DeclRefExpr *DE = dyn_cast<DeclRefExpr>(BaseExp))
+        if (DE->getType().getObjCLifetime() == Qualifiers::OCL_Weak)
+          Diag(DE->getLocation(), diag::error_arc_weak_ivar_access);
+    }
+
+    return Owned(new (Context) ObjCIvarRefExpr(IV, IV->getType(),
+                                               MemberLoc, BaseExpr.take(),
+                                               IsArrow));
+  }
+
+  // Objective-C property access.
+  const ObjCObjectPointerType *OPT;
+  if (!IsArrow && (OPT = BaseType->getAs<ObjCObjectPointerType>())) {
+    if (!SS.isEmpty() && !SS.isInvalid()) {
+      Diag(SS.getRange().getBegin(), diag::err_qualified_objc_access)
+        << 0 << SS.getScopeRep()
+        << FixItHint::CreateRemoval(SS.getRange());
+      SS.clear();
+    }
+
+    // This actually uses the base as an r-value.
+    BaseExpr = DefaultLvalueConversion(BaseExpr.take());
+    if (BaseExpr.isInvalid())
+      return ExprError();
+
+    assert(Context.hasSameUnqualifiedType(BaseType, BaseExpr.get()->getType()));
+
+    IdentifierInfo *Member = MemberName.getAsIdentifierInfo();
+
+    const ObjCObjectType *OT = OPT->getObjectType();
+
+    // id, with and without qualifiers.
+    if (OT->isObjCId()) {
+      // Check protocols on qualified interfaces.
+      Selector Sel = PP.getSelectorTable().getNullarySelector(Member);
+      if (Decl *PMDecl = FindGetterSetterNameDecl(OPT, Member, Sel, Context)) {
+        if (ObjCPropertyDecl *PD = dyn_cast<ObjCPropertyDecl>(PMDecl)) {
+          // Check the use of this declaration
+          if (DiagnoseUseOfDecl(PD, MemberLoc))
+            return ExprError();
+
+          return Owned(new (Context) ObjCPropertyRefExpr(PD,
+                                                         Context.PseudoObjectTy,
+                                                         VK_LValue,
+                                                         OK_ObjCProperty,
+                                                         MemberLoc, 
+                                                         BaseExpr.take()));
+        }
+
+        if (ObjCMethodDecl *OMD = dyn_cast<ObjCMethodDecl>(PMDecl)) {
+          // Check the use of this method.
+          if (DiagnoseUseOfDecl(OMD, MemberLoc))
+            return ExprError();
+          Selector SetterSel =
+            SelectorTable::constructSetterName(PP.getIdentifierTable(),
+                                               PP.getSelectorTable(), Member);
+          ObjCMethodDecl *SMD = 0;
+          if (Decl *SDecl = FindGetterSetterNameDecl(OPT, /*Property id*/0, 
+                                                     SetterSel, Context))
+            SMD = dyn_cast<ObjCMethodDecl>(SDecl);
+          
+          return Owned(new (Context) ObjCPropertyRefExpr(OMD, SMD,
+                                                         Context.PseudoObjectTy,
+                                                         VK_LValue, OK_ObjCProperty,
+                                                         MemberLoc, BaseExpr.take()));
+        }
+      }
+      // Use of id.member can only be for a property reference. Do not
+      // use the 'id' redefinition in this case.
+      if (IsArrow && ShouldTryAgainWithRedefinitionType(*this, BaseExpr))
+        return LookupMemberExpr(R, BaseExpr, IsArrow, OpLoc, SS,
+                                ObjCImpDecl, HasTemplateArgs);
+
+      return ExprError(Diag(MemberLoc, diag::err_property_not_found)
+                         << MemberName << BaseType);
+    }
+
+    // 'Class', unqualified only.
+    if (OT->isObjCClass()) {
+      // Only works in a method declaration (??!).
+      ObjCMethodDecl *MD = getCurMethodDecl();
+      if (!MD) {
+        if (ShouldTryAgainWithRedefinitionType(*this, BaseExpr))
+          return LookupMemberExpr(R, BaseExpr, IsArrow, OpLoc, SS,
+                                  ObjCImpDecl, HasTemplateArgs);
+
+        goto fail;
+      }
+
+      // Also must look for a getter name which uses property syntax.
+      Selector Sel = PP.getSelectorTable().getNullarySelector(Member);
+      ObjCInterfaceDecl *IFace = MD->getClassInterface();
+      ObjCMethodDecl *Getter;
+      if ((Getter = IFace->lookupClassMethod(Sel))) {
+        // Check the use of this method.
+        if (DiagnoseUseOfDecl(Getter, MemberLoc))
+          return ExprError();
+      } else
+        Getter = IFace->lookupPrivateMethod(Sel, false);
+      // If we found a getter then this may be a valid dot-reference, we
+      // will look for the matching setter, in case it is needed.
+      Selector SetterSel =
+        SelectorTable::constructSetterName(PP.getIdentifierTable(),
+                                           PP.getSelectorTable(), Member);
+      ObjCMethodDecl *Setter = IFace->lookupClassMethod(SetterSel);
+      if (!Setter) {
+        // If this reference is in an @implementation, also check for 'private'
+        // methods.
+        Setter = IFace->lookupPrivateMethod(SetterSel, false);
+      }
+      // Look through local category implementations associated with the class.
+      if (!Setter)
+        Setter = IFace->getCategoryClassMethod(SetterSel);
+
+      if (Setter && DiagnoseUseOfDecl(Setter, MemberLoc))
+        return ExprError();
+
+      if (Getter || Setter) {
+        return Owned(new (Context) ObjCPropertyRefExpr(Getter, Setter,
+                                                       Context.PseudoObjectTy,
+                                                       VK_LValue, OK_ObjCProperty,
+                                                       MemberLoc, BaseExpr.take()));
+      }
+
+      if (ShouldTryAgainWithRedefinitionType(*this, BaseExpr))
+        return LookupMemberExpr(R, BaseExpr, IsArrow, OpLoc, SS,
+                                ObjCImpDecl, HasTemplateArgs);
+
+      return ExprError(Diag(MemberLoc, diag::err_property_not_found)
+                         << MemberName << BaseType);
+    }
+
+    // Normal property access.
+    return HandleExprPropertyRefExpr(OPT, BaseExpr.get(), OpLoc, 
+                                     MemberName, MemberLoc,
+                                     SourceLocation(), QualType(), false);
+  }
+
+  // Handle 'field access' to vectors, such as 'V.xx'.
+  if (BaseType->isExtVectorType()) {
+    // FIXME: this expr should store IsArrow.
+    IdentifierInfo *Member = MemberName.getAsIdentifierInfo();
+    ExprValueKind VK = (IsArrow ? VK_LValue : BaseExpr.get()->getValueKind());
+    QualType ret = CheckExtVectorComponent(*this, BaseType, VK, OpLoc,
+                                           Member, MemberLoc);
+    if (ret.isNull())
+      return ExprError();
+
+    return Owned(new (Context) ExtVectorElementExpr(ret, VK, BaseExpr.take(),
+                                                    *Member, MemberLoc));
+  }
+
+  // Adjust builtin-sel to the appropriate redefinition type if that's
+  // not just a pointer to builtin-sel again.
+  if (IsArrow &&
+      BaseType->isSpecificBuiltinType(BuiltinType::ObjCSel) &&
+      !Context.getObjCSelRedefinitionType()->isObjCSelType()) {
+    BaseExpr = ImpCastExprToType(BaseExpr.take(), 
+                                 Context.getObjCSelRedefinitionType(),
+                                 CK_BitCast);
+    return LookupMemberExpr(R, BaseExpr, IsArrow, OpLoc, SS,
+                            ObjCImpDecl, HasTemplateArgs);
+  }
+
+  // Failure cases.
+ fail:
+
+  // Recover from dot accesses to pointers, e.g.:
+  //   type *foo;
+  //   foo.bar
+  // This is actually well-formed in two cases:
+  //   - 'type' is an Objective C type
+  //   - 'bar' is a pseudo-destructor name which happens to refer to
+  //     the appropriate pointer type
+  if (const PointerType *Ptr = BaseType->getAs<PointerType>()) {
+    if (!IsArrow && Ptr->getPointeeType()->isRecordType() &&
+        MemberName.getNameKind() != DeclarationName::CXXDestructorName) {
+      Diag(OpLoc, diag::err_typecheck_member_reference_suggestion)
+        << BaseType << int(IsArrow) << BaseExpr.get()->getSourceRange()
+          << FixItHint::CreateReplacement(OpLoc, "->");
+
+      // Recurse as an -> access.
+      IsArrow = true;
+      return LookupMemberExpr(R, BaseExpr, IsArrow, OpLoc, SS,
+                              ObjCImpDecl, HasTemplateArgs);
+    }
+  }
+
+  // If the user is trying to apply -> or . to a function name, it's probably
+  // because they forgot parentheses to call that function.
+  if (tryToRecoverWithCall(BaseExpr,
+                           PDiag(diag::err_member_reference_needs_call),
+                           /*complain*/ false,
+                           IsArrow ? &isPointerToRecordType : &isRecordType)) {
+    if (BaseExpr.isInvalid())
+      return ExprError();
+    BaseExpr = DefaultFunctionArrayConversion(BaseExpr.take());
+    return LookupMemberExpr(R, BaseExpr, IsArrow, OpLoc, SS,
+                            ObjCImpDecl, HasTemplateArgs);
+  }
+
+  Diag(MemberLoc, diag::err_typecheck_member_reference_struct_union)
+    << BaseType << BaseExpr.get()->getSourceRange();
+
+  return ExprError();
+}
+
+/// The main callback when the parser finds something like
+///   expression . [nested-name-specifier] identifier
+///   expression -> [nested-name-specifier] identifier
+/// where 'identifier' encompasses a fairly broad spectrum of
+/// possibilities, including destructor and operator references.
+///
+/// \param OpKind either tok::arrow or tok::period
+/// \param HasTrailingLParen whether the next token is '(', which
+///   is used to diagnose mis-uses of special members that can
+///   only be called
+/// \param ObjCImpDecl the current ObjC @implementation decl;
+///   this is an ugly hack around the fact that ObjC @implementations
+///   aren't properly put in the context chain
+ExprResult Sema::ActOnMemberAccessExpr(Scope *S, Expr *Base,
+                                       SourceLocation OpLoc,
+                                       tok::TokenKind OpKind,
+                                       CXXScopeSpec &SS,
+                                       SourceLocation TemplateKWLoc,
+                                       UnqualifiedId &Id,
+                                       Decl *ObjCImpDecl,
+                                       bool HasTrailingLParen) {
+  if (SS.isSet() && SS.isInvalid())
+    return ExprError();
+
+  // Warn about the explicit constructor calls Microsoft extension.
+  if (getLangOpts().MicrosoftExt &&
+      Id.getKind() == UnqualifiedId::IK_ConstructorName)
+    Diag(Id.getSourceRange().getBegin(),
+         diag::ext_ms_explicit_constructor_call);
+
+  TemplateArgumentListInfo TemplateArgsBuffer;
+
+  // Decompose the name into its component parts.
+  DeclarationNameInfo NameInfo;
+  const TemplateArgumentListInfo *TemplateArgs;
+  DecomposeUnqualifiedId(Id, TemplateArgsBuffer,
+                         NameInfo, TemplateArgs);
+
+  DeclarationName Name = NameInfo.getName();
+  bool IsArrow = (OpKind == tok::arrow);
+
+  NamedDecl *FirstQualifierInScope
+    = (!SS.isSet() ? 0 : FindFirstQualifierInScope(S,
+                       static_cast<NestedNameSpecifier*>(SS.getScopeRep())));
+
+  // This is a postfix expression, so get rid of ParenListExprs.
+  ExprResult Result = MaybeConvertParenListExprToParenExpr(S, Base);
+  if (Result.isInvalid()) return ExprError();
+  Base = Result.take();
+
+  if (Base->getType()->isDependentType() || Name.isDependentName() ||
+      isDependentScopeSpecifier(SS)) {
+    Result = ActOnDependentMemberExpr(Base, Base->getType(),
+                                      IsArrow, OpLoc,
+                                      SS, TemplateKWLoc, FirstQualifierInScope,
+                                      NameInfo, TemplateArgs);
+  } else {
+    LookupResult R(*this, NameInfo, LookupMemberName);
+    ExprResult BaseResult = Owned(Base);
+    Result = LookupMemberExpr(R, BaseResult, IsArrow, OpLoc,
+                              SS, ObjCImpDecl, TemplateArgs != 0);
+    if (BaseResult.isInvalid())
+      return ExprError();
+    Base = BaseResult.take();
+
+    if (Result.isInvalid()) {
+      Owned(Base);
+      return ExprError();
+    }
+
+    if (Result.get()) {
+      // The only way a reference to a destructor can be used is to
+      // immediately call it, which falls into this case.  If the
+      // next token is not a '(', produce a diagnostic and build the
+      // call now.
+      if (!HasTrailingLParen &&
+          Id.getKind() == UnqualifiedId::IK_DestructorName)
+        return DiagnoseDtorReference(NameInfo.getLoc(), Result.get());
+
+      return move(Result);
+    }
+
+    Result = BuildMemberReferenceExpr(Base, Base->getType(),
+                                      OpLoc, IsArrow, SS, TemplateKWLoc,
+                                      FirstQualifierInScope, R, TemplateArgs);
+  }
+
+  return move(Result);
+}
+
+static ExprResult
+BuildFieldReferenceExpr(Sema &S, Expr *BaseExpr, bool IsArrow,
+                        const CXXScopeSpec &SS, FieldDecl *Field,
+                        DeclAccessPair FoundDecl,
+                        const DeclarationNameInfo &MemberNameInfo) {
+  // x.a is an l-value if 'a' has a reference type. Otherwise:
+  // x.a is an l-value/x-value/pr-value if the base is (and note
+  //   that *x is always an l-value), except that if the base isn't
+  //   an ordinary object then we must have an rvalue.
+  ExprValueKind VK = VK_LValue;
+  ExprObjectKind OK = OK_Ordinary;
+  if (!IsArrow) {
+    if (BaseExpr->getObjectKind() == OK_Ordinary)
+      VK = BaseExpr->getValueKind();
+    else
+      VK = VK_RValue;
+  }
+  if (VK != VK_RValue && Field->isBitField())
+    OK = OK_BitField;
+  
+  // Figure out the type of the member; see C99 6.5.2.3p3, C++ [expr.ref]
+  QualType MemberType = Field->getType();
+  if (const ReferenceType *Ref = MemberType->getAs<ReferenceType>()) {
+    MemberType = Ref->getPointeeType();
+    VK = VK_LValue;
+  } else {
+    QualType BaseType = BaseExpr->getType();
+    if (IsArrow) BaseType = BaseType->getAs<PointerType>()->getPointeeType();
+    
+    Qualifiers BaseQuals = BaseType.getQualifiers();
+    
+    // GC attributes are never picked up by members.
+    BaseQuals.removeObjCGCAttr();
+    
+    // CVR attributes from the base are picked up by members,
+    // except that 'mutable' members don't pick up 'const'.
+    if (Field->isMutable()) BaseQuals.removeConst();
+    
+    Qualifiers MemberQuals
+    = S.Context.getCanonicalType(MemberType).getQualifiers();
+    
+    // TR 18037 does not allow fields to be declared with address spaces.
+    assert(!MemberQuals.hasAddressSpace());
+    
+    Qualifiers Combined = BaseQuals + MemberQuals;
+    if (Combined != MemberQuals)
+      MemberType = S.Context.getQualifiedType(MemberType, Combined);
+  }
+  
+  ExprResult Base =
+  S.PerformObjectMemberConversion(BaseExpr, SS.getScopeRep(),
+                                  FoundDecl, Field);
+  if (Base.isInvalid())
+    return ExprError();
+  return S.Owned(BuildMemberExpr(S, S.Context, Base.take(), IsArrow, SS,
+                                 /*TemplateKWLoc=*/SourceLocation(),
+                                 Field, FoundDecl, MemberNameInfo,
+                                 MemberType, VK, OK));
+}
+
+/// Builds an implicit member access expression.  The current context
+/// is known to be an instance method, and the given unqualified lookup
+/// set is known to contain only instance members, at least one of which
+/// is from an appropriate type.
+ExprResult
+Sema::BuildImplicitMemberExpr(const CXXScopeSpec &SS,
+                              SourceLocation TemplateKWLoc,
+                              LookupResult &R,
+                              const TemplateArgumentListInfo *TemplateArgs,
+                              bool IsKnownInstance) {
+  assert(!R.empty() && !R.isAmbiguous());
+  
+  SourceLocation loc = R.getNameLoc();
+  
+  // We may have found a field within an anonymous union or struct
+  // (C++ [class.union]).
+  // FIXME: template-ids inside anonymous structs?
+  if (IndirectFieldDecl *FD = R.getAsSingle<IndirectFieldDecl>())
+    return BuildAnonymousStructUnionMemberReference(SS, R.getNameLoc(), FD);
+  
+  // If this is known to be an instance access, go ahead and build an
+  // implicit 'this' expression now.
+  // 'this' expression now.
+  QualType ThisTy = getCurrentThisType();
+  assert(!ThisTy.isNull() && "didn't correctly pre-flight capture of 'this'");
+  
+  Expr *baseExpr = 0; // null signifies implicit access
+  if (IsKnownInstance) {
+    SourceLocation Loc = R.getNameLoc();
+    if (SS.getRange().isValid())
+      Loc = SS.getRange().getBegin();
+    CheckCXXThisCapture(Loc);
+    baseExpr = new (Context) CXXThisExpr(loc, ThisTy, /*isImplicit=*/true);
+  }
+  
+  return BuildMemberReferenceExpr(baseExpr, ThisTy,
+                                  /*OpLoc*/ SourceLocation(),
+                                  /*IsArrow*/ true,
+                                  SS, TemplateKWLoc,
+                                  /*FirstQualifierInScope*/ 0,
+                                  R, TemplateArgs);
+}
diff --git a/clang/lib/Sema/SemaExprObjC.cpp b/clang/lib/Sema/SemaExprObjC.cpp
new file mode 100644
index 0000000..b62d56e
--- /dev/null
+++ b/clang/lib/Sema/SemaExprObjC.cpp
@@ -0,0 +1,3049 @@
+//===--- SemaExprObjC.cpp - Semantic Analysis for ObjC Expressions --------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+//  This file implements semantic analysis for Objective-C expressions.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Sema/SemaInternal.h"
+#include "clang/Sema/Lookup.h"
+#include "clang/Sema/Scope.h"
+#include "clang/Sema/ScopeInfo.h"
+#include "clang/Sema/Initialization.h"
+#include "clang/Analysis/DomainSpecific/CocoaConventions.h"
+#include "clang/Edit/Rewriters.h"
+#include "clang/Edit/Commit.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/AST/ExprObjC.h"
+#include "clang/AST/StmtVisitor.h"
+#include "clang/AST/TypeLoc.h"
+#include "llvm/ADT/SmallString.h"
+#include "clang/Lex/Preprocessor.h"
+
+using namespace clang;
+using namespace sema;
+using llvm::makeArrayRef;
+
+ExprResult Sema::ParseObjCStringLiteral(SourceLocation *AtLocs,
+                                        Expr **strings,
+                                        unsigned NumStrings) {
+  StringLiteral **Strings = reinterpret_cast<StringLiteral**>(strings);
+
+  // Most ObjC strings are formed out of a single piece.  However, we *can*
+  // have strings formed out of multiple @ strings with multiple pptokens in
+  // each one, e.g. @"foo" "bar" @"baz" "qux"   which need to be turned into one
+  // StringLiteral for ObjCStringLiteral to hold onto.
+  StringLiteral *S = Strings[0];
+
+  // If we have a multi-part string, merge it all together.
+  if (NumStrings != 1) {
+    // Concatenate objc strings.
+    SmallString<128> StrBuf;
+    SmallVector<SourceLocation, 8> StrLocs;
+
+    for (unsigned i = 0; i != NumStrings; ++i) {
+      S = Strings[i];
+
+      // ObjC strings can't be wide or UTF.
+      if (!S->isAscii()) {
+        Diag(S->getLocStart(), diag::err_cfstring_literal_not_string_constant)
+          << S->getSourceRange();
+        return true;
+      }
+
+      // Append the string.
+      StrBuf += S->getString();
+
+      // Get the locations of the string tokens.
+      StrLocs.append(S->tokloc_begin(), S->tokloc_end());
+    }
+
+    // Create the aggregate string with the appropriate content and location
+    // information.
+    S = StringLiteral::Create(Context, StrBuf,
+                              StringLiteral::Ascii, /*Pascal=*/false,
+                              Context.getPointerType(Context.CharTy),
+                              &StrLocs[0], StrLocs.size());
+  }
+  
+  return BuildObjCStringLiteral(AtLocs[0], S);
+}
+
+ExprResult Sema::BuildObjCStringLiteral(SourceLocation AtLoc, StringLiteral *S){
+  // Verify that this composite string is acceptable for ObjC strings.
+  if (CheckObjCString(S))
+    return true;
+
+  // Initialize the constant string interface lazily. This assumes
+  // the NSString interface is seen in this translation unit. Note: We
+  // don't use NSConstantString, since the runtime team considers this
+  // interface private (even though it appears in the header files).
+  QualType Ty = Context.getObjCConstantStringInterface();
+  if (!Ty.isNull()) {
+    Ty = Context.getObjCObjectPointerType(Ty);
+  } else if (getLangOpts().NoConstantCFStrings) {
+    IdentifierInfo *NSIdent=0;
+    std::string StringClass(getLangOpts().ObjCConstantStringClass);
+    
+    if (StringClass.empty())
+      NSIdent = &Context.Idents.get("NSConstantString");
+    else
+      NSIdent = &Context.Idents.get(StringClass);
+    
+    NamedDecl *IF = LookupSingleName(TUScope, NSIdent, AtLoc,
+                                     LookupOrdinaryName);
+    if (ObjCInterfaceDecl *StrIF = dyn_cast_or_null<ObjCInterfaceDecl>(IF)) {
+      Context.setObjCConstantStringInterface(StrIF);
+      Ty = Context.getObjCConstantStringInterface();
+      Ty = Context.getObjCObjectPointerType(Ty);
+    } else {
+      // If there is no NSConstantString interface defined then treat this
+      // as error and recover from it.
+      Diag(S->getLocStart(), diag::err_no_nsconstant_string_class) << NSIdent
+        << S->getSourceRange();
+      Ty = Context.getObjCIdType();
+    }
+  } else {
+    IdentifierInfo *NSIdent = &Context.Idents.get("NSString");
+    NamedDecl *IF = LookupSingleName(TUScope, NSIdent, AtLoc,
+                                     LookupOrdinaryName);
+    if (ObjCInterfaceDecl *StrIF = dyn_cast_or_null<ObjCInterfaceDecl>(IF)) {
+      Context.setObjCConstantStringInterface(StrIF);
+      Ty = Context.getObjCConstantStringInterface();
+      Ty = Context.getObjCObjectPointerType(Ty);
+    } else {
+      // If there is no NSString interface defined, implicitly declare
+      // a @class NSString; and use that instead. This is to make sure
+      // type of an NSString literal is represented correctly, instead of
+      // being an 'id' type.
+      Ty = Context.getObjCNSStringType();
+      if (Ty.isNull()) {
+        ObjCInterfaceDecl *NSStringIDecl = 
+          ObjCInterfaceDecl::Create (Context, 
+                                     Context.getTranslationUnitDecl(), 
+                                     SourceLocation(), NSIdent, 
+                                     0, SourceLocation());
+        Ty = Context.getObjCInterfaceType(NSStringIDecl);
+        Context.setObjCNSStringType(Ty);
+      }
+      Ty = Context.getObjCObjectPointerType(Ty);
+    }
+  }
+
+  return new (Context) ObjCStringLiteral(S, Ty, AtLoc);
+}
+
+/// \brief Retrieve the NSNumber factory method that should be used to create
+/// an Objective-C literal for the given type.
+static ObjCMethodDecl *getNSNumberFactoryMethod(Sema &S, SourceLocation Loc,
+                                                QualType T, QualType ReturnType,
+                                                SourceRange Range) {
+  llvm::Optional<NSAPI::NSNumberLiteralMethodKind> Kind 
+    = S.NSAPIObj->getNSNumberFactoryMethodKind(T);
+  
+  if (!Kind) {
+    S.Diag(Loc, diag::err_invalid_nsnumber_type)
+      << T << Range;
+    return 0;
+  }
+    
+  // If we already looked up this method, we're done.
+  if (S.NSNumberLiteralMethods[*Kind])
+    return S.NSNumberLiteralMethods[*Kind];
+  
+  Selector Sel = S.NSAPIObj->getNSNumberLiteralSelector(*Kind,
+                                                        /*Instance=*/false);
+  
+  // Look for the appropriate method within NSNumber.
+  ObjCMethodDecl *Method = S.NSNumberDecl->lookupClassMethod(Sel);;
+  if (!Method && S.getLangOpts().DebuggerObjCLiteral) {
+    TypeSourceInfo *ResultTInfo = 0;
+    Method = ObjCMethodDecl::Create(S.Context, SourceLocation(), SourceLocation(), Sel,
+                           ReturnType,
+                           ResultTInfo,
+                           S.Context.getTranslationUnitDecl(),
+                           false /*Instance*/, false/*isVariadic*/,
+                           /*isSynthesized=*/false,
+                           /*isImplicitlyDeclared=*/true, /*isDefined=*/false,
+                           ObjCMethodDecl::Required,
+                           false);
+    ParmVarDecl *value = ParmVarDecl::Create(S.Context, Method,
+                                             SourceLocation(), SourceLocation(),
+                                             &S.Context.Idents.get("value"),
+                                             T, /*TInfo=*/0, SC_None, SC_None, 0);
+    Method->setMethodParams(S.Context, value, ArrayRef<SourceLocation>());
+  }
+
+  if (!Method) {
+    S.Diag(Loc, diag::err_undeclared_nsnumber_method) << Sel;
+    return 0;
+  }
+  
+  // Make sure the return type is reasonable.
+  if (!Method->getResultType()->isObjCObjectPointerType()) {
+    S.Diag(Loc, diag::err_objc_literal_method_sig)
+      << Sel;
+    S.Diag(Method->getLocation(), diag::note_objc_literal_method_return)
+      << Method->getResultType();
+    return 0;
+  }
+
+  // Note: if the parameter type is out-of-line, we'll catch it later in the
+  // implicit conversion.
+  
+  S.NSNumberLiteralMethods[*Kind] = Method;
+  return Method;
+}
+
+/// BuildObjCNumericLiteral - builds an ObjCNumericLiteral AST node for the
+/// numeric literal expression. Type of the expression will be "NSNumber *"
+/// or "id" if NSNumber is unavailable.
+ExprResult Sema::BuildObjCNumericLiteral(SourceLocation AtLoc, Expr *Number) {
+  // Look up the NSNumber class, if we haven't done so already.
+  if (!NSNumberDecl) {
+    NamedDecl *IF = LookupSingleName(TUScope,
+                                NSAPIObj->getNSClassId(NSAPI::ClassId_NSNumber),
+                                AtLoc, LookupOrdinaryName);
+    NSNumberDecl = dyn_cast_or_null<ObjCInterfaceDecl>(IF);
+    
+    if (!NSNumberDecl && getLangOpts().DebuggerObjCLiteral)
+      NSNumberDecl =  ObjCInterfaceDecl::Create (Context,
+                        Context.getTranslationUnitDecl(),
+                        SourceLocation(), 
+                        NSAPIObj->getNSClassId(NSAPI::ClassId_NSNumber),
+                        0, SourceLocation());
+    if (!NSNumberDecl) {
+      Diag(AtLoc, diag::err_undeclared_nsnumber);
+      return ExprError();
+    }
+  }
+  
+  // Determine the type of the literal.
+  QualType NumberType = Number->getType();
+  if (CharacterLiteral *Char = dyn_cast<CharacterLiteral>(Number)) {
+    // In C, character literals have type 'int'. That's not the type we want
+    // to use to determine the Objective-c literal kind.
+    switch (Char->getKind()) {
+    case CharacterLiteral::Ascii:
+      NumberType = Context.CharTy;
+      break;
+      
+    case CharacterLiteral::Wide:
+      NumberType = Context.getWCharType();
+      break;
+      
+    case CharacterLiteral::UTF16:
+      NumberType = Context.Char16Ty;
+      break;
+      
+    case CharacterLiteral::UTF32:
+      NumberType = Context.Char32Ty;
+      break;
+    }
+  }
+  
+  ObjCMethodDecl *Method = 0;
+  // Look for the appropriate method within NSNumber.
+  // Construct the literal.
+  QualType Ty
+    = Context.getObjCObjectPointerType(
+                                    Context.getObjCInterfaceType(NSNumberDecl));
+  Method  = getNSNumberFactoryMethod(*this, AtLoc, 
+                                     NumberType, Ty, 
+                                     Number->getSourceRange());
+
+  if (!Method)
+    return ExprError();
+
+  // Convert the number to the type that the parameter expects.
+  QualType ElementT = Method->param_begin()[0]->getType();
+  ExprResult ConvertedNumber = PerformImplicitConversion(Number, ElementT,
+                                                         AA_Sending);
+  if (ConvertedNumber.isInvalid())
+    return ExprError();
+  Number = ConvertedNumber.get();
+  
+  return MaybeBindToTemporary(
+           new (Context) ObjCNumericLiteral(Number, Ty, Method, AtLoc));
+}
+
+ExprResult Sema::ActOnObjCBoolLiteral(SourceLocation AtLoc, 
+                                      SourceLocation ValueLoc,
+                                      bool Value) {
+  ExprResult Inner;
+  if (getLangOpts().CPlusPlus) {
+    Inner = ActOnCXXBoolLiteral(ValueLoc, Value? tok::kw_true : tok::kw_false);
+  } else {
+    // C doesn't actually have a way to represent literal values of type 
+    // _Bool. So, we'll use 0/1 and implicit cast to _Bool.
+    Inner = ActOnIntegerConstant(ValueLoc, Value? 1 : 0);
+    Inner = ImpCastExprToType(Inner.get(), Context.BoolTy, 
+                              CK_IntegralToBoolean);
+  }
+  
+  return BuildObjCNumericLiteral(AtLoc, Inner.get());
+}
+
+/// \brief Check that the given expression is a valid element of an Objective-C
+/// collection literal.
+static ExprResult CheckObjCCollectionLiteralElement(Sema &S, Expr *Element, 
+                                                    QualType T) {  
+  // If the expression is type-dependent, there's nothing for us to do.
+  if (Element->isTypeDependent())
+    return Element;
+
+  ExprResult Result = S.CheckPlaceholderExpr(Element);
+  if (Result.isInvalid())
+    return ExprError();
+  Element = Result.get();
+
+  // In C++, check for an implicit conversion to an Objective-C object pointer 
+  // type.
+  if (S.getLangOpts().CPlusPlus && Element->getType()->isRecordType()) {
+    InitializedEntity Entity
+      = InitializedEntity::InitializeParameter(S.Context, T, /*Consumed=*/false);
+    InitializationKind Kind
+      = InitializationKind::CreateCopy(Element->getLocStart(), SourceLocation());
+    InitializationSequence Seq(S, Entity, Kind, &Element, 1);
+    if (!Seq.Failed())
+      return Seq.Perform(S, Entity, Kind, MultiExprArg(S, &Element, 1));
+  }
+
+  Expr *OrigElement = Element;
+
+  // Perform lvalue-to-rvalue conversion.
+  Result = S.DefaultLvalueConversion(Element);
+  if (Result.isInvalid())
+    return ExprError();
+  Element = Result.get();  
+
+  // Make sure that we have an Objective-C pointer type or block.
+  if (!Element->getType()->isObjCObjectPointerType() &&
+      !Element->getType()->isBlockPointerType()) {
+    bool Recovered = false;
+    
+    // If this is potentially an Objective-C numeric literal, add the '@'.
+    if (isa<IntegerLiteral>(OrigElement) || 
+        isa<CharacterLiteral>(OrigElement) ||
+        isa<FloatingLiteral>(OrigElement) ||
+        isa<ObjCBoolLiteralExpr>(OrigElement) ||
+        isa<CXXBoolLiteralExpr>(OrigElement)) {
+      if (S.NSAPIObj->getNSNumberFactoryMethodKind(OrigElement->getType())) {
+        int Which = isa<CharacterLiteral>(OrigElement) ? 1
+                  : (isa<CXXBoolLiteralExpr>(OrigElement) ||
+                     isa<ObjCBoolLiteralExpr>(OrigElement)) ? 2
+                  : 3;
+        
+        S.Diag(OrigElement->getLocStart(), diag::err_box_literal_collection)
+          << Which << OrigElement->getSourceRange()
+          << FixItHint::CreateInsertion(OrigElement->getLocStart(), "@");
+        
+        Result = S.BuildObjCNumericLiteral(OrigElement->getLocStart(),
+                                           OrigElement);
+        if (Result.isInvalid())
+          return ExprError();
+        
+        Element = Result.get();
+        Recovered = true;
+      }
+    }
+    // If this is potentially an Objective-C string literal, add the '@'.
+    else if (StringLiteral *String = dyn_cast<StringLiteral>(OrigElement)) {
+      if (String->isAscii()) {
+        S.Diag(OrigElement->getLocStart(), diag::err_box_literal_collection)
+          << 0 << OrigElement->getSourceRange()
+          << FixItHint::CreateInsertion(OrigElement->getLocStart(), "@");
+
+        Result = S.BuildObjCStringLiteral(OrigElement->getLocStart(), String);
+        if (Result.isInvalid())
+          return ExprError();
+        
+        Element = Result.get();
+        Recovered = true;
+      }
+    }
+    
+    if (!Recovered) {
+      S.Diag(Element->getLocStart(), diag::err_invalid_collection_element)
+        << Element->getType();
+      return ExprError();
+    }
+  }
+  
+  // Make sure that the element has the type that the container factory 
+  // function expects. 
+  return S.PerformCopyInitialization(
+           InitializedEntity::InitializeParameter(S.Context, T, 
+                                                  /*Consumed=*/false),
+           Element->getLocStart(), Element);
+}
+
+ExprResult Sema::BuildObjCSubscriptExpression(SourceLocation RB, Expr *BaseExpr,
+                                        Expr *IndexExpr,
+                                        ObjCMethodDecl *getterMethod,
+                                        ObjCMethodDecl *setterMethod) {
+  // Feature support is for modern abi.
+  if (!LangOpts.ObjCNonFragileABI)
+    return ExprError();
+  // If the expression is type-dependent, there's nothing for us to do.
+  assert ((!BaseExpr->isTypeDependent() && !IndexExpr->isTypeDependent()) &&
+          "base or index cannot have dependent type here");
+  ExprResult Result = CheckPlaceholderExpr(IndexExpr);
+  if (Result.isInvalid())
+    return ExprError();
+  IndexExpr = Result.get();
+  
+  // Perform lvalue-to-rvalue conversion.
+  Result = DefaultLvalueConversion(BaseExpr);
+  if (Result.isInvalid())
+    return ExprError();
+  BaseExpr = Result.get();
+  return Owned(ObjCSubscriptRefExpr::Create(Context, 
+                                            BaseExpr,
+                                            IndexExpr,
+                                            Context.PseudoObjectTy,
+                                            getterMethod,
+                                            setterMethod, RB));
+  
+}
+
+ExprResult Sema::BuildObjCArrayLiteral(SourceRange SR, MultiExprArg Elements) {
+  // Look up the NSArray class, if we haven't done so already.
+  if (!NSArrayDecl) {
+    NamedDecl *IF = LookupSingleName(TUScope,
+                                 NSAPIObj->getNSClassId(NSAPI::ClassId_NSArray),
+                                 SR.getBegin(),
+                                 LookupOrdinaryName);
+    NSArrayDecl = dyn_cast_or_null<ObjCInterfaceDecl>(IF);
+    if (!NSArrayDecl && getLangOpts().DebuggerObjCLiteral)
+      NSArrayDecl =  ObjCInterfaceDecl::Create (Context,
+                            Context.getTranslationUnitDecl(),
+                            SourceLocation(),
+                            NSAPIObj->getNSClassId(NSAPI::ClassId_NSArray),
+                            0, SourceLocation());
+
+    if (!NSArrayDecl) {
+      Diag(SR.getBegin(), diag::err_undeclared_nsarray);
+      return ExprError();
+    }
+  }
+  
+  // Find the arrayWithObjects:count: method, if we haven't done so already.
+  QualType IdT = Context.getObjCIdType();
+  if (!ArrayWithObjectsMethod) {
+    Selector
+      Sel = NSAPIObj->getNSArraySelector(NSAPI::NSArr_arrayWithObjectsCount);
+    ArrayWithObjectsMethod = NSArrayDecl->lookupClassMethod(Sel);
+    if (!ArrayWithObjectsMethod && getLangOpts().DebuggerObjCLiteral) {
+      TypeSourceInfo *ResultTInfo = 0;
+      ArrayWithObjectsMethod =
+                         ObjCMethodDecl::Create(Context,
+                           SourceLocation(), SourceLocation(), Sel,
+                           IdT,
+                           ResultTInfo,
+                           Context.getTranslationUnitDecl(),
+                           false /*Instance*/, false/*isVariadic*/,
+                           /*isSynthesized=*/false,
+                           /*isImplicitlyDeclared=*/true, /*isDefined=*/false,
+                           ObjCMethodDecl::Required,
+                           false);
+      SmallVector<ParmVarDecl *, 2> Params;
+      ParmVarDecl *objects = ParmVarDecl::Create(Context, ArrayWithObjectsMethod,
+                                                SourceLocation(), SourceLocation(),
+                                                &Context.Idents.get("objects"),
+                                                Context.getPointerType(IdT),
+                                                /*TInfo=*/0,
+                                                SC_None,
+                                                SC_None,
+                                                0);
+      Params.push_back(objects);
+      ParmVarDecl *cnt = ParmVarDecl::Create(Context, ArrayWithObjectsMethod,
+                                                SourceLocation(), SourceLocation(),
+                                                &Context.Idents.get("cnt"),
+                                                Context.UnsignedLongTy,
+                                                /*TInfo=*/0,
+                                                SC_None,
+                                                SC_None,
+                                                0);
+      Params.push_back(cnt);
+      ArrayWithObjectsMethod->setMethodParams(Context, Params,
+                                              ArrayRef<SourceLocation>());
+
+
+    }
+
+    if (!ArrayWithObjectsMethod) {
+      Diag(SR.getBegin(), diag::err_undeclared_arraywithobjects) << Sel;
+      return ExprError();
+    }
+  }
+  
+  // Make sure the return type is reasonable.
+  if (!ArrayWithObjectsMethod->getResultType()->isObjCObjectPointerType()) {
+    Diag(SR.getBegin(), diag::err_objc_literal_method_sig)
+      << ArrayWithObjectsMethod->getSelector();
+    Diag(ArrayWithObjectsMethod->getLocation(),
+         diag::note_objc_literal_method_return)
+      << ArrayWithObjectsMethod->getResultType();
+    return ExprError();
+  }
+
+  // Dig out the type that all elements should be converted to.
+  QualType T = ArrayWithObjectsMethod->param_begin()[0]->getType();
+  const PointerType *PtrT = T->getAs<PointerType>();
+  if (!PtrT || 
+      !Context.hasSameUnqualifiedType(PtrT->getPointeeType(), IdT)) {
+    Diag(SR.getBegin(), diag::err_objc_literal_method_sig)
+      << ArrayWithObjectsMethod->getSelector();
+    Diag(ArrayWithObjectsMethod->param_begin()[0]->getLocation(),
+         diag::note_objc_literal_method_param)
+      << 0 << T 
+      << Context.getPointerType(IdT.withConst());
+    return ExprError();
+  }
+  T = PtrT->getPointeeType();
+  
+  // Check that the 'count' parameter is integral.
+  if (!ArrayWithObjectsMethod->param_begin()[1]->getType()->isIntegerType()) {
+    Diag(SR.getBegin(), diag::err_objc_literal_method_sig)
+      << ArrayWithObjectsMethod->getSelector();
+    Diag(ArrayWithObjectsMethod->param_begin()[1]->getLocation(),
+         diag::note_objc_literal_method_param)
+      << 1 
+      << ArrayWithObjectsMethod->param_begin()[1]->getType()
+      << "integral";
+    return ExprError();
+  }
+
+  // Check that each of the elements provided is valid in a collection literal,
+  // performing conversions as necessary.
+  Expr **ElementsBuffer = Elements.get();
+  for (unsigned I = 0, N = Elements.size(); I != N; ++I) {
+    ExprResult Converted = CheckObjCCollectionLiteralElement(*this,
+                                                             ElementsBuffer[I],
+                                                             T);
+    if (Converted.isInvalid())
+      return ExprError();
+    
+    ElementsBuffer[I] = Converted.get();
+  }
+    
+  QualType Ty 
+    = Context.getObjCObjectPointerType(
+                                    Context.getObjCInterfaceType(NSArrayDecl));
+
+  return MaybeBindToTemporary(
+           ObjCArrayLiteral::Create(Context, 
+                                    llvm::makeArrayRef(Elements.get(), 
+                                                       Elements.size()), 
+                                    Ty, ArrayWithObjectsMethod, SR));
+}
+
+ExprResult Sema::BuildObjCDictionaryLiteral(SourceRange SR, 
+                                            ObjCDictionaryElement *Elements,
+                                            unsigned NumElements) {
+  // Look up the NSDictionary class, if we haven't done so already.
+  if (!NSDictionaryDecl) {
+    NamedDecl *IF = LookupSingleName(TUScope,
+                            NSAPIObj->getNSClassId(NSAPI::ClassId_NSDictionary),
+                            SR.getBegin(), LookupOrdinaryName);
+    NSDictionaryDecl = dyn_cast_or_null<ObjCInterfaceDecl>(IF);
+    if (!NSDictionaryDecl && getLangOpts().DebuggerObjCLiteral)
+      NSDictionaryDecl =  ObjCInterfaceDecl::Create (Context,
+                            Context.getTranslationUnitDecl(),
+                            SourceLocation(),
+                            NSAPIObj->getNSClassId(NSAPI::ClassId_NSDictionary),
+                            0, SourceLocation());
+
+    if (!NSDictionaryDecl) {
+      Diag(SR.getBegin(), diag::err_undeclared_nsdictionary);
+      return ExprError();    
+    }
+  }
+  
+  // Find the dictionaryWithObjects:forKeys:count: method, if we haven't done
+  // so already.
+  QualType IdT = Context.getObjCIdType();
+  if (!DictionaryWithObjectsMethod) {
+    Selector Sel = NSAPIObj->getNSDictionarySelector(
+                                    NSAPI::NSDict_dictionaryWithObjectsForKeysCount);
+    DictionaryWithObjectsMethod = NSDictionaryDecl->lookupClassMethod(Sel);
+    if (!DictionaryWithObjectsMethod && getLangOpts().DebuggerObjCLiteral) {
+      DictionaryWithObjectsMethod = 
+                         ObjCMethodDecl::Create(Context,  
+                           SourceLocation(), SourceLocation(), Sel,
+                           IdT,
+                           0 /*TypeSourceInfo */,
+                           Context.getTranslationUnitDecl(),
+                           false /*Instance*/, false/*isVariadic*/,
+                           /*isSynthesized=*/false,
+                           /*isImplicitlyDeclared=*/true, /*isDefined=*/false,
+                           ObjCMethodDecl::Required,
+                           false);
+      SmallVector<ParmVarDecl *, 3> Params;
+      ParmVarDecl *objects = ParmVarDecl::Create(Context, DictionaryWithObjectsMethod,
+                                                SourceLocation(), SourceLocation(),
+                                                &Context.Idents.get("objects"),
+                                                Context.getPointerType(IdT),
+                                                /*TInfo=*/0,
+                                                SC_None,
+                                                SC_None,
+                                                0);
+      Params.push_back(objects);
+      ParmVarDecl *keys = ParmVarDecl::Create(Context, DictionaryWithObjectsMethod,
+                                                SourceLocation(), SourceLocation(),
+                                                &Context.Idents.get("keys"),
+                                                Context.getPointerType(IdT),
+                                                /*TInfo=*/0,
+                                                SC_None,
+                                                SC_None,
+                                                0);
+      Params.push_back(keys);
+      ParmVarDecl *cnt = ParmVarDecl::Create(Context, DictionaryWithObjectsMethod,
+                                                SourceLocation(), SourceLocation(),
+                                                &Context.Idents.get("cnt"),
+                                                Context.UnsignedLongTy,
+                                                /*TInfo=*/0,
+                                                SC_None,
+                                                SC_None,
+                                                0);
+      Params.push_back(cnt);
+      DictionaryWithObjectsMethod->setMethodParams(Context, Params, 
+                                                   ArrayRef<SourceLocation>());
+    }
+
+    if (!DictionaryWithObjectsMethod) {
+      Diag(SR.getBegin(), diag::err_undeclared_dictwithobjects) << Sel;
+      return ExprError();    
+    }
+  }
+  
+  // Make sure the return type is reasonable.
+  if (!DictionaryWithObjectsMethod->getResultType()->isObjCObjectPointerType()){
+    Diag(SR.getBegin(), diag::err_objc_literal_method_sig)
+    << DictionaryWithObjectsMethod->getSelector();
+    Diag(DictionaryWithObjectsMethod->getLocation(),
+         diag::note_objc_literal_method_return)
+    << DictionaryWithObjectsMethod->getResultType();
+    return ExprError();
+  }
+
+  // Dig out the type that all values should be converted to.
+  QualType ValueT =  DictionaryWithObjectsMethod->param_begin()[0]->getType();
+  const PointerType *PtrValue = ValueT->getAs<PointerType>();
+  if (!PtrValue || 
+      !Context.hasSameUnqualifiedType(PtrValue->getPointeeType(), IdT)) {
+    Diag(SR.getBegin(), diag::err_objc_literal_method_sig)
+      << DictionaryWithObjectsMethod->getSelector();
+    Diag(DictionaryWithObjectsMethod->param_begin()[0]->getLocation(),
+         diag::note_objc_literal_method_param)
+      << 0 << ValueT
+      << Context.getPointerType(IdT.withConst());
+    return ExprError();
+  }
+  ValueT = PtrValue->getPointeeType();
+
+  // Dig out the type that all keys should be converted to.
+  QualType KeyT = DictionaryWithObjectsMethod->param_begin()[1]->getType();
+  const PointerType *PtrKey = KeyT->getAs<PointerType>();
+  if (!PtrKey || 
+      !Context.hasSameUnqualifiedType(PtrKey->getPointeeType(),
+                                      IdT)) {
+    bool err = true;
+    if (PtrKey) {
+      if (QIDNSCopying.isNull()) {
+        // key argument of selector is id<NSCopying>?
+        if (ObjCProtocolDecl *NSCopyingPDecl =
+            LookupProtocol(&Context.Idents.get("NSCopying"), SR.getBegin())) {
+          ObjCProtocolDecl *PQ[] = {NSCopyingPDecl};
+          QIDNSCopying = 
+            Context.getObjCObjectType(Context.ObjCBuiltinIdTy,
+                                      (ObjCProtocolDecl**) PQ,1);
+          QIDNSCopying = Context.getObjCObjectPointerType(QIDNSCopying);
+        }
+      }
+      if (!QIDNSCopying.isNull())
+        err = !Context.hasSameUnqualifiedType(PtrKey->getPointeeType(),
+                                              QIDNSCopying);
+    }
+    
+    if (err) {
+      Diag(SR.getBegin(), diag::err_objc_literal_method_sig)
+        << DictionaryWithObjectsMethod->getSelector();
+      Diag(DictionaryWithObjectsMethod->param_begin()[1]->getLocation(),
+           diag::note_objc_literal_method_param)
+        << 1 << KeyT
+        << Context.getPointerType(IdT.withConst());
+      return ExprError();
+    }
+  }
+  KeyT = PtrKey->getPointeeType();
+
+  // Check that the 'count' parameter is integral.
+  if (!DictionaryWithObjectsMethod->param_begin()[2]->getType()
+                                                            ->isIntegerType()) {
+    Diag(SR.getBegin(), diag::err_objc_literal_method_sig)
+      << DictionaryWithObjectsMethod->getSelector();
+    Diag(DictionaryWithObjectsMethod->param_begin()[2]->getLocation(),
+         diag::note_objc_literal_method_param)
+      << 2
+      << DictionaryWithObjectsMethod->param_begin()[2]->getType()
+      << "integral";
+    return ExprError();
+  }
+
+  // Check that each of the keys and values provided is valid in a collection 
+  // literal, performing conversions as necessary.
+  bool HasPackExpansions = false;
+  for (unsigned I = 0, N = NumElements; I != N; ++I) {
+    // Check the key.
+    ExprResult Key = CheckObjCCollectionLiteralElement(*this, Elements[I].Key, 
+                                                       KeyT);
+    if (Key.isInvalid())
+      return ExprError();
+    
+    // Check the value.
+    ExprResult Value
+      = CheckObjCCollectionLiteralElement(*this, Elements[I].Value, ValueT);
+    if (Value.isInvalid())
+      return ExprError();
+    
+    Elements[I].Key = Key.get();
+    Elements[I].Value = Value.get();
+    
+    if (Elements[I].EllipsisLoc.isInvalid())
+      continue;
+    
+    if (!Elements[I].Key->containsUnexpandedParameterPack() &&
+        !Elements[I].Value->containsUnexpandedParameterPack()) {
+      Diag(Elements[I].EllipsisLoc, 
+           diag::err_pack_expansion_without_parameter_packs)
+        << SourceRange(Elements[I].Key->getLocStart(),
+                       Elements[I].Value->getLocEnd());
+      return ExprError();
+    }
+    
+    HasPackExpansions = true;
+  }
+
+  
+  QualType Ty
+    = Context.getObjCObjectPointerType(
+                                Context.getObjCInterfaceType(NSDictionaryDecl));  
+  return MaybeBindToTemporary(
+           ObjCDictionaryLiteral::Create(Context, 
+                                         llvm::makeArrayRef(Elements, 
+                                                            NumElements),
+                                         HasPackExpansions,
+                                         Ty, 
+                                         DictionaryWithObjectsMethod, SR));
+}
+
+ExprResult Sema::BuildObjCEncodeExpression(SourceLocation AtLoc,
+                                      TypeSourceInfo *EncodedTypeInfo,
+                                      SourceLocation RParenLoc) {
+  QualType EncodedType = EncodedTypeInfo->getType();
+  QualType StrTy;
+  if (EncodedType->isDependentType())
+    StrTy = Context.DependentTy;
+  else {
+    if (!EncodedType->getAsArrayTypeUnsafe() && //// Incomplete array is handled.
+        !EncodedType->isVoidType()) // void is handled too.
+      if (RequireCompleteType(AtLoc, EncodedType,
+                         PDiag(diag::err_incomplete_type_objc_at_encode)
+                             << EncodedTypeInfo->getTypeLoc().getSourceRange()))
+        return ExprError();
+
+    std::string Str;
+    Context.getObjCEncodingForType(EncodedType, Str);
+
+    // The type of @encode is the same as the type of the corresponding string,
+    // which is an array type.
+    StrTy = Context.CharTy;
+    // A C++ string literal has a const-qualified element type (C++ 2.13.4p1).
+    if (getLangOpts().CPlusPlus || getLangOpts().ConstStrings)
+      StrTy.addConst();
+    StrTy = Context.getConstantArrayType(StrTy, llvm::APInt(32, Str.size()+1),
+                                         ArrayType::Normal, 0);
+  }
+
+  return new (Context) ObjCEncodeExpr(StrTy, EncodedTypeInfo, AtLoc, RParenLoc);
+}
+
+ExprResult Sema::ParseObjCEncodeExpression(SourceLocation AtLoc,
+                                           SourceLocation EncodeLoc,
+                                           SourceLocation LParenLoc,
+                                           ParsedType ty,
+                                           SourceLocation RParenLoc) {
+  // FIXME: Preserve type source info ?
+  TypeSourceInfo *TInfo;
+  QualType EncodedType = GetTypeFromParser(ty, &TInfo);
+  if (!TInfo)
+    TInfo = Context.getTrivialTypeSourceInfo(EncodedType,
+                                             PP.getLocForEndOfToken(LParenLoc));
+
+  return BuildObjCEncodeExpression(AtLoc, TInfo, RParenLoc);
+}
+
+ExprResult Sema::ParseObjCSelectorExpression(Selector Sel,
+                                             SourceLocation AtLoc,
+                                             SourceLocation SelLoc,
+                                             SourceLocation LParenLoc,
+                                             SourceLocation RParenLoc) {
+  ObjCMethodDecl *Method = LookupInstanceMethodInGlobalPool(Sel,
+                             SourceRange(LParenLoc, RParenLoc), false, false);
+  if (!Method)
+    Method = LookupFactoryMethodInGlobalPool(Sel,
+                                          SourceRange(LParenLoc, RParenLoc));
+  if (!Method)
+    Diag(SelLoc, diag::warn_undeclared_selector) << Sel;
+  
+  if (!Method ||
+      Method->getImplementationControl() != ObjCMethodDecl::Optional) {
+    llvm::DenseMap<Selector, SourceLocation>::iterator Pos
+      = ReferencedSelectors.find(Sel);
+    if (Pos == ReferencedSelectors.end())
+      ReferencedSelectors.insert(std::make_pair(Sel, SelLoc));
+  }
+
+  // In ARC, forbid the user from using @selector for 
+  // retain/release/autorelease/dealloc/retainCount.
+  if (getLangOpts().ObjCAutoRefCount) {
+    switch (Sel.getMethodFamily()) {
+    case OMF_retain:
+    case OMF_release:
+    case OMF_autorelease:
+    case OMF_retainCount:
+    case OMF_dealloc:
+      Diag(AtLoc, diag::err_arc_illegal_selector) << 
+        Sel << SourceRange(LParenLoc, RParenLoc);
+      break;
+
+    case OMF_None:
+    case OMF_alloc:
+    case OMF_copy:
+    case OMF_finalize:
+    case OMF_init:
+    case OMF_mutableCopy:
+    case OMF_new:
+    case OMF_self:
+    case OMF_performSelector:
+      break;
+    }
+  }
+  QualType Ty = Context.getObjCSelType();
+  return new (Context) ObjCSelectorExpr(Ty, Sel, AtLoc, RParenLoc);
+}
+
+ExprResult Sema::ParseObjCProtocolExpression(IdentifierInfo *ProtocolId,
+                                             SourceLocation AtLoc,
+                                             SourceLocation ProtoLoc,
+                                             SourceLocation LParenLoc,
+                                             SourceLocation RParenLoc) {
+  ObjCProtocolDecl* PDecl = LookupProtocol(ProtocolId, ProtoLoc);
+  if (!PDecl) {
+    Diag(ProtoLoc, diag::err_undeclared_protocol) << ProtocolId;
+    return true;
+  }
+
+  QualType Ty = Context.getObjCProtoType();
+  if (Ty.isNull())
+    return true;
+  Ty = Context.getObjCObjectPointerType(Ty);
+  return new (Context) ObjCProtocolExpr(Ty, PDecl, AtLoc, RParenLoc);
+}
+
+/// Try to capture an implicit reference to 'self'.
+ObjCMethodDecl *Sema::tryCaptureObjCSelf(SourceLocation Loc) {
+  DeclContext *DC = getFunctionLevelDeclContext();
+
+  // If we're not in an ObjC method, error out.  Note that, unlike the
+  // C++ case, we don't require an instance method --- class methods
+  // still have a 'self', and we really do still need to capture it!
+  ObjCMethodDecl *method = dyn_cast<ObjCMethodDecl>(DC);
+  if (!method)
+    return 0;
+
+  tryCaptureVariable(method->getSelfDecl(), Loc);
+
+  return method;
+}
+
+static QualType stripObjCInstanceType(ASTContext &Context, QualType T) {
+  if (T == Context.getObjCInstanceType())
+    return Context.getObjCIdType();
+  
+  return T;
+}
+
+QualType Sema::getMessageSendResultType(QualType ReceiverType,
+                                        ObjCMethodDecl *Method,
+                                    bool isClassMessage, bool isSuperMessage) {
+  assert(Method && "Must have a method");
+  if (!Method->hasRelatedResultType())
+    return Method->getSendResultType();
+  
+  // If a method has a related return type:
+  //   - if the method found is an instance method, but the message send
+  //     was a class message send, T is the declared return type of the method
+  //     found
+  if (Method->isInstanceMethod() && isClassMessage)
+    return stripObjCInstanceType(Context, Method->getSendResultType());
+  
+  //   - if the receiver is super, T is a pointer to the class of the 
+  //     enclosing method definition
+  if (isSuperMessage) {
+    if (ObjCMethodDecl *CurMethod = getCurMethodDecl())
+      if (ObjCInterfaceDecl *Class = CurMethod->getClassInterface())
+        return Context.getObjCObjectPointerType(
+                                        Context.getObjCInterfaceType(Class));
+  }
+    
+  //   - if the receiver is the name of a class U, T is a pointer to U
+  if (ReceiverType->getAs<ObjCInterfaceType>() ||
+      ReceiverType->isObjCQualifiedInterfaceType())
+    return Context.getObjCObjectPointerType(ReceiverType);
+  //   - if the receiver is of type Class or qualified Class type, 
+  //     T is the declared return type of the method.
+  if (ReceiverType->isObjCClassType() ||
+      ReceiverType->isObjCQualifiedClassType())
+    return stripObjCInstanceType(Context, Method->getSendResultType());
+  
+  //   - if the receiver is id, qualified id, Class, or qualified Class, T
+  //     is the receiver type, otherwise
+  //   - T is the type of the receiver expression.
+  return ReceiverType;
+}
+
+void Sema::EmitRelatedResultTypeNote(const Expr *E) {
+  E = E->IgnoreParenImpCasts();
+  const ObjCMessageExpr *MsgSend = dyn_cast<ObjCMessageExpr>(E);
+  if (!MsgSend)
+    return;
+  
+  const ObjCMethodDecl *Method = MsgSend->getMethodDecl();
+  if (!Method)
+    return;
+  
+  if (!Method->hasRelatedResultType())
+    return;
+  
+  if (Context.hasSameUnqualifiedType(Method->getResultType()
+                                                        .getNonReferenceType(),
+                                     MsgSend->getType()))
+    return;
+  
+  if (!Context.hasSameUnqualifiedType(Method->getResultType(), 
+                                      Context.getObjCInstanceType()))
+    return;
+  
+  Diag(Method->getLocation(), diag::note_related_result_type_inferred)
+    << Method->isInstanceMethod() << Method->getSelector()
+    << MsgSend->getType();
+}
+
+bool Sema::CheckMessageArgumentTypes(QualType ReceiverType,
+                                     Expr **Args, unsigned NumArgs,
+                                     Selector Sel, ObjCMethodDecl *Method,
+                                     bool isClassMessage, bool isSuperMessage,
+                                     SourceLocation lbrac, SourceLocation rbrac,
+                                     QualType &ReturnType, ExprValueKind &VK) {
+  if (!Method) {
+    // Apply default argument promotion as for (C99 6.5.2.2p6).
+    for (unsigned i = 0; i != NumArgs; i++) {
+      if (Args[i]->isTypeDependent())
+        continue;
+
+      ExprResult Result = DefaultArgumentPromotion(Args[i]);
+      if (Result.isInvalid())
+        return true;
+      Args[i] = Result.take();
+    }
+
+    unsigned DiagID;
+    if (getLangOpts().ObjCAutoRefCount)
+      DiagID = diag::err_arc_method_not_found;
+    else
+      DiagID = isClassMessage ? diag::warn_class_method_not_found
+                              : diag::warn_inst_method_not_found;
+    if (!getLangOpts().DebuggerSupport)
+      Diag(lbrac, DiagID)
+        << Sel << isClassMessage << SourceRange(lbrac, rbrac);
+
+    // In debuggers, we want to use __unknown_anytype for these
+    // results so that clients can cast them.
+    if (getLangOpts().DebuggerSupport) {
+      ReturnType = Context.UnknownAnyTy;
+    } else {
+      ReturnType = Context.getObjCIdType();
+    }
+    VK = VK_RValue;
+    return false;
+  }
+
+  ReturnType = getMessageSendResultType(ReceiverType, Method, isClassMessage, 
+                                        isSuperMessage);
+  VK = Expr::getValueKindForType(Method->getResultType());
+
+  unsigned NumNamedArgs = Sel.getNumArgs();
+  // Method might have more arguments than selector indicates. This is due
+  // to addition of c-style arguments in method.
+  if (Method->param_size() > Sel.getNumArgs())
+    NumNamedArgs = Method->param_size();
+  // FIXME. This need be cleaned up.
+  if (NumArgs < NumNamedArgs) {
+    Diag(lbrac, diag::err_typecheck_call_too_few_args)
+      << 2 << NumNamedArgs << NumArgs;
+    return false;
+  }
+
+  bool IsError = false;
+  for (unsigned i = 0; i < NumNamedArgs; i++) {
+    // We can't do any type-checking on a type-dependent argument.
+    if (Args[i]->isTypeDependent())
+      continue;
+
+    Expr *argExpr = Args[i];
+
+    ParmVarDecl *param = Method->param_begin()[i];
+    assert(argExpr && "CheckMessageArgumentTypes(): missing expression");
+
+    // Strip the unbridged-cast placeholder expression off unless it's
+    // a consumed argument.
+    if (argExpr->hasPlaceholderType(BuiltinType::ARCUnbridgedCast) &&
+        !param->hasAttr<CFConsumedAttr>())
+      argExpr = stripARCUnbridgedCast(argExpr);
+
+    if (RequireCompleteType(argExpr->getSourceRange().getBegin(),
+                            param->getType(),
+                            PDiag(diag::err_call_incomplete_argument)
+                              << argExpr->getSourceRange()))
+      return true;
+
+    InitializedEntity Entity = InitializedEntity::InitializeParameter(Context,
+                                                                      param);
+    ExprResult ArgE = PerformCopyInitialization(Entity, lbrac, Owned(argExpr));
+    if (ArgE.isInvalid())
+      IsError = true;
+    else
+      Args[i] = ArgE.takeAs<Expr>();
+  }
+
+  // Promote additional arguments to variadic methods.
+  if (Method->isVariadic()) {
+    for (unsigned i = NumNamedArgs; i < NumArgs; ++i) {
+      if (Args[i]->isTypeDependent())
+        continue;
+
+      ExprResult Arg = DefaultVariadicArgumentPromotion(Args[i], VariadicMethod, 0);
+      IsError |= Arg.isInvalid();
+      Args[i] = Arg.take();
+    }
+  } else {
+    // Check for extra arguments to non-variadic methods.
+    if (NumArgs != NumNamedArgs) {
+      Diag(Args[NumNamedArgs]->getLocStart(),
+           diag::err_typecheck_call_too_many_args)
+        << 2 /*method*/ << NumNamedArgs << NumArgs
+        << Method->getSourceRange()
+        << SourceRange(Args[NumNamedArgs]->getLocStart(),
+                       Args[NumArgs-1]->getLocEnd());
+    }
+  }
+
+  DiagnoseSentinelCalls(Method, lbrac, Args, NumArgs);
+
+  // Do additional checkings on method.
+  IsError |= CheckObjCMethodCall(Method, lbrac, Args, NumArgs);
+
+  return IsError;
+}
+
+bool Sema::isSelfExpr(Expr *receiver) {
+  // 'self' is objc 'self' in an objc method only.
+  ObjCMethodDecl *method =
+    dyn_cast<ObjCMethodDecl>(CurContext->getNonClosureAncestor());
+  if (!method) return false;
+
+  receiver = receiver->IgnoreParenLValueCasts();
+  if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(receiver))
+    if (DRE->getDecl() == method->getSelfDecl())
+      return true;
+  return false;
+}
+
+// Helper method for ActOnClassMethod/ActOnInstanceMethod.
+// Will search "local" class/category implementations for a method decl.
+// If failed, then we search in class's root for an instance method.
+// Returns 0 if no method is found.
+ObjCMethodDecl *Sema::LookupPrivateClassMethod(Selector Sel,
+                                          ObjCInterfaceDecl *ClassDecl) {
+  ObjCMethodDecl *Method = 0;
+  // lookup in class and all superclasses
+  while (ClassDecl && !Method) {
+    if (ObjCImplementationDecl *ImpDecl = ClassDecl->getImplementation())
+      Method = ImpDecl->getClassMethod(Sel);
+
+    // Look through local category implementations associated with the class.
+    if (!Method)
+      Method = ClassDecl->getCategoryClassMethod(Sel);
+
+    // Before we give up, check if the selector is an instance method.
+    // But only in the root. This matches gcc's behaviour and what the
+    // runtime expects.
+    if (!Method && !ClassDecl->getSuperClass()) {
+      Method = ClassDecl->lookupInstanceMethod(Sel);
+      // Look through local category implementations associated
+      // with the root class.
+      if (!Method)
+        Method = LookupPrivateInstanceMethod(Sel, ClassDecl);
+    }
+
+    ClassDecl = ClassDecl->getSuperClass();
+  }
+  return Method;
+}
+
+ObjCMethodDecl *Sema::LookupPrivateInstanceMethod(Selector Sel,
+                                              ObjCInterfaceDecl *ClassDecl) {
+  if (!ClassDecl->hasDefinition())
+    return 0;
+
+  ObjCMethodDecl *Method = 0;
+  while (ClassDecl && !Method) {
+    // If we have implementations in scope, check "private" methods.
+    if (ObjCImplementationDecl *ImpDecl = ClassDecl->getImplementation())
+      Method = ImpDecl->getInstanceMethod(Sel);
+
+    // Look through local category implementations associated with the class.
+    if (!Method)
+      Method = ClassDecl->getCategoryInstanceMethod(Sel);
+    ClassDecl = ClassDecl->getSuperClass();
+  }
+  return Method;
+}
+
+/// LookupMethodInType - Look up a method in an ObjCObjectType.
+ObjCMethodDecl *Sema::LookupMethodInObjectType(Selector sel, QualType type,
+                                               bool isInstance) {
+  const ObjCObjectType *objType = type->castAs<ObjCObjectType>();
+  if (ObjCInterfaceDecl *iface = objType->getInterface()) {
+    // Look it up in the main interface (and categories, etc.)
+    if (ObjCMethodDecl *method = iface->lookupMethod(sel, isInstance))
+      return method;
+
+    // Okay, look for "private" methods declared in any
+    // @implementations we've seen.
+    if (isInstance) {
+      if (ObjCMethodDecl *method = LookupPrivateInstanceMethod(sel, iface))
+        return method;
+    } else {
+      if (ObjCMethodDecl *method = LookupPrivateClassMethod(sel, iface))
+        return method;
+    }
+  }
+
+  // Check qualifiers.
+  for (ObjCObjectType::qual_iterator
+         i = objType->qual_begin(), e = objType->qual_end(); i != e; ++i)
+    if (ObjCMethodDecl *method = (*i)->lookupMethod(sel, isInstance))
+      return method;
+
+  return 0;
+}
+
+/// LookupMethodInQualifiedType - Lookups up a method in protocol qualifier 
+/// list of a qualified objective pointer type.
+ObjCMethodDecl *Sema::LookupMethodInQualifiedType(Selector Sel,
+                                              const ObjCObjectPointerType *OPT,
+                                              bool Instance)
+{
+  ObjCMethodDecl *MD = 0;
+  for (ObjCObjectPointerType::qual_iterator I = OPT->qual_begin(),
+       E = OPT->qual_end(); I != E; ++I) {
+    ObjCProtocolDecl *PROTO = (*I);
+    if ((MD = PROTO->lookupMethod(Sel, Instance))) {
+      return MD;
+    }
+  }
+  return 0;
+}
+
+/// HandleExprPropertyRefExpr - Handle foo.bar where foo is a pointer to an
+/// objective C interface.  This is a property reference expression.
+ExprResult Sema::
+HandleExprPropertyRefExpr(const ObjCObjectPointerType *OPT,
+                          Expr *BaseExpr, SourceLocation OpLoc,
+                          DeclarationName MemberName,
+                          SourceLocation MemberLoc,
+                          SourceLocation SuperLoc, QualType SuperType,
+                          bool Super) {
+  const ObjCInterfaceType *IFaceT = OPT->getInterfaceType();
+  ObjCInterfaceDecl *IFace = IFaceT->getDecl();
+  
+  if (MemberName.getNameKind() != DeclarationName::Identifier) {
+    Diag(MemberLoc, diag::err_invalid_property_name)
+      << MemberName << QualType(OPT, 0);
+    return ExprError();
+  }
+  
+  IdentifierInfo *Member = MemberName.getAsIdentifierInfo();
+  SourceRange BaseRange = Super? SourceRange(SuperLoc)
+                               : BaseExpr->getSourceRange();
+  if (RequireCompleteType(MemberLoc, OPT->getPointeeType(), 
+                          PDiag(diag::err_property_not_found_forward_class)
+                            << MemberName << BaseRange))
+    return ExprError();
+  
+  // Search for a declared property first.
+  if (ObjCPropertyDecl *PD = IFace->FindPropertyDeclaration(Member)) {
+    // Check whether we can reference this property.
+    if (DiagnoseUseOfDecl(PD, MemberLoc))
+      return ExprError();
+             
+    if (Super)
+      return Owned(new (Context) ObjCPropertyRefExpr(PD, Context.PseudoObjectTy,
+                                                     VK_LValue, OK_ObjCProperty,
+                                                     MemberLoc, 
+                                                     SuperLoc, SuperType));
+    else
+      return Owned(new (Context) ObjCPropertyRefExpr(PD, Context.PseudoObjectTy,
+                                                     VK_LValue, OK_ObjCProperty,
+                                                     MemberLoc, BaseExpr));
+  }
+  // Check protocols on qualified interfaces.
+  for (ObjCObjectPointerType::qual_iterator I = OPT->qual_begin(),
+       E = OPT->qual_end(); I != E; ++I)
+    if (ObjCPropertyDecl *PD = (*I)->FindPropertyDeclaration(Member)) {
+      // Check whether we can reference this property.
+      if (DiagnoseUseOfDecl(PD, MemberLoc))
+        return ExprError();
+      
+      if (Super)
+        return Owned(new (Context) ObjCPropertyRefExpr(PD,
+                                                       Context.PseudoObjectTy,
+                                                       VK_LValue,
+                                                       OK_ObjCProperty,
+                                                       MemberLoc, 
+                                                       SuperLoc, SuperType));
+      else
+        return Owned(new (Context) ObjCPropertyRefExpr(PD,
+                                                       Context.PseudoObjectTy,
+                                                       VK_LValue,
+                                                       OK_ObjCProperty,
+                                                       MemberLoc,
+                                                       BaseExpr));
+    }
+  // If that failed, look for an "implicit" property by seeing if the nullary
+  // selector is implemented.
+
+  // FIXME: The logic for looking up nullary and unary selectors should be
+  // shared with the code in ActOnInstanceMessage.
+
+  Selector Sel = PP.getSelectorTable().getNullarySelector(Member);
+  ObjCMethodDecl *Getter = IFace->lookupInstanceMethod(Sel);
+  
+  // May be founf in property's qualified list.
+  if (!Getter)
+    Getter = LookupMethodInQualifiedType(Sel, OPT, true);
+
+  // If this reference is in an @implementation, check for 'private' methods.
+  if (!Getter)
+    Getter = IFace->lookupPrivateMethod(Sel);
+
+  // Look through local category implementations associated with the class.
+  if (!Getter)
+    Getter = IFace->getCategoryInstanceMethod(Sel);
+  if (Getter) {
+    // Check if we can reference this property.
+    if (DiagnoseUseOfDecl(Getter, MemberLoc))
+      return ExprError();
+  }
+  // If we found a getter then this may be a valid dot-reference, we
+  // will look for the matching setter, in case it is needed.
+  Selector SetterSel =
+    SelectorTable::constructSetterName(PP.getIdentifierTable(),
+                                       PP.getSelectorTable(), Member);
+  ObjCMethodDecl *Setter = IFace->lookupInstanceMethod(SetterSel);
+  
+  // May be founf in property's qualified list.
+  if (!Setter)
+    Setter = LookupMethodInQualifiedType(SetterSel, OPT, true);
+  
+  if (!Setter) {
+    // If this reference is in an @implementation, also check for 'private'
+    // methods.
+    Setter = IFace->lookupPrivateMethod(SetterSel);
+  }
+  // Look through local category implementations associated with the class.
+  if (!Setter)
+    Setter = IFace->getCategoryInstanceMethod(SetterSel);
+    
+  if (Setter && DiagnoseUseOfDecl(Setter, MemberLoc))
+    return ExprError();
+
+  if (Getter || Setter) {
+    if (Super)
+      return Owned(new (Context) ObjCPropertyRefExpr(Getter, Setter,
+                                                     Context.PseudoObjectTy,
+                                                     VK_LValue, OK_ObjCProperty,
+                                                     MemberLoc,
+                                                     SuperLoc, SuperType));
+    else
+      return Owned(new (Context) ObjCPropertyRefExpr(Getter, Setter,
+                                                     Context.PseudoObjectTy,
+                                                     VK_LValue, OK_ObjCProperty,
+                                                     MemberLoc, BaseExpr));
+
+  }
+
+  // Attempt to correct for typos in property names.
+  DeclFilterCCC<ObjCPropertyDecl> Validator;
+  if (TypoCorrection Corrected = CorrectTypo(
+      DeclarationNameInfo(MemberName, MemberLoc), LookupOrdinaryName, NULL,
+      NULL, Validator, IFace, false, OPT)) {
+    ObjCPropertyDecl *Property =
+        Corrected.getCorrectionDeclAs<ObjCPropertyDecl>();
+    DeclarationName TypoResult = Corrected.getCorrection();
+    Diag(MemberLoc, diag::err_property_not_found_suggest)
+      << MemberName << QualType(OPT, 0) << TypoResult
+      << FixItHint::CreateReplacement(MemberLoc, TypoResult.getAsString());
+    Diag(Property->getLocation(), diag::note_previous_decl)
+      << Property->getDeclName();
+    return HandleExprPropertyRefExpr(OPT, BaseExpr, OpLoc,
+                                     TypoResult, MemberLoc,
+                                     SuperLoc, SuperType, Super);
+  }
+  ObjCInterfaceDecl *ClassDeclared;
+  if (ObjCIvarDecl *Ivar = 
+      IFace->lookupInstanceVariable(Member, ClassDeclared)) {
+    QualType T = Ivar->getType();
+    if (const ObjCObjectPointerType * OBJPT = 
+        T->getAsObjCInterfacePointerType()) {
+      if (RequireCompleteType(MemberLoc, OBJPT->getPointeeType(), 
+                              PDiag(diag::err_property_not_as_forward_class)
+                                << MemberName << BaseExpr->getSourceRange()))
+        return ExprError();
+    }
+    Diag(MemberLoc, 
+         diag::err_ivar_access_using_property_syntax_suggest)
+    << MemberName << QualType(OPT, 0) << Ivar->getDeclName()
+    << FixItHint::CreateReplacement(OpLoc, "->");
+    return ExprError();
+  }
+  
+  Diag(MemberLoc, diag::err_property_not_found)
+    << MemberName << QualType(OPT, 0);
+  if (Setter)
+    Diag(Setter->getLocation(), diag::note_getter_unavailable)
+          << MemberName << BaseExpr->getSourceRange();
+  return ExprError();
+}
+
+
+
+ExprResult Sema::
+ActOnClassPropertyRefExpr(IdentifierInfo &receiverName,
+                          IdentifierInfo &propertyName,
+                          SourceLocation receiverNameLoc,
+                          SourceLocation propertyNameLoc) {
+
+  IdentifierInfo *receiverNamePtr = &receiverName;
+  ObjCInterfaceDecl *IFace = getObjCInterfaceDecl(receiverNamePtr,
+                                                  receiverNameLoc);
+
+  bool IsSuper = false;
+  if (IFace == 0) {
+    // If the "receiver" is 'super' in a method, handle it as an expression-like
+    // property reference.
+    if (receiverNamePtr->isStr("super")) {
+      IsSuper = true;
+
+      if (ObjCMethodDecl *CurMethod = tryCaptureObjCSelf(receiverNameLoc)) {
+        if (CurMethod->isInstanceMethod()) {
+          QualType T = 
+            Context.getObjCInterfaceType(CurMethod->getClassInterface());
+          T = Context.getObjCObjectPointerType(T);
+        
+          return HandleExprPropertyRefExpr(T->getAsObjCInterfacePointerType(),
+                                           /*BaseExpr*/0, 
+                                           SourceLocation()/*OpLoc*/, 
+                                           &propertyName,
+                                           propertyNameLoc,
+                                           receiverNameLoc, T, true);
+        }
+
+        // Otherwise, if this is a class method, try dispatching to our
+        // superclass.
+        IFace = CurMethod->getClassInterface()->getSuperClass();
+      }
+    }
+    
+    if (IFace == 0) {
+      Diag(receiverNameLoc, diag::err_expected_ident_or_lparen);
+      return ExprError();
+    }
+  }
+
+  // Search for a declared property first.
+  Selector Sel = PP.getSelectorTable().getNullarySelector(&propertyName);
+  ObjCMethodDecl *Getter = IFace->lookupClassMethod(Sel);
+
+  // If this reference is in an @implementation, check for 'private' methods.
+  if (!Getter)
+    if (ObjCMethodDecl *CurMeth = getCurMethodDecl())
+      if (ObjCInterfaceDecl *ClassDecl = CurMeth->getClassInterface())
+        if (ObjCImplementationDecl *ImpDecl = ClassDecl->getImplementation())
+          Getter = ImpDecl->getClassMethod(Sel);
+
+  if (Getter) {
+    // FIXME: refactor/share with ActOnMemberReference().
+    // Check if we can reference this property.
+    if (DiagnoseUseOfDecl(Getter, propertyNameLoc))
+      return ExprError();
+  }
+
+  // Look for the matching setter, in case it is needed.
+  Selector SetterSel =
+    SelectorTable::constructSetterName(PP.getIdentifierTable(),
+                                       PP.getSelectorTable(), &propertyName);
+
+  ObjCMethodDecl *Setter = IFace->lookupClassMethod(SetterSel);
+  if (!Setter) {
+    // If this reference is in an @implementation, also check for 'private'
+    // methods.
+    if (ObjCMethodDecl *CurMeth = getCurMethodDecl())
+      if (ObjCInterfaceDecl *ClassDecl = CurMeth->getClassInterface())
+        if (ObjCImplementationDecl *ImpDecl = ClassDecl->getImplementation())
+          Setter = ImpDecl->getClassMethod(SetterSel);
+  }
+  // Look through local category implementations associated with the class.
+  if (!Setter)
+    Setter = IFace->getCategoryClassMethod(SetterSel);
+
+  if (Setter && DiagnoseUseOfDecl(Setter, propertyNameLoc))
+    return ExprError();
+
+  if (Getter || Setter) {
+    if (IsSuper)
+    return Owned(new (Context) ObjCPropertyRefExpr(Getter, Setter,
+                                                   Context.PseudoObjectTy,
+                                                   VK_LValue, OK_ObjCProperty,
+                                                   propertyNameLoc,
+                                                   receiverNameLoc, 
+                                          Context.getObjCInterfaceType(IFace)));
+
+    return Owned(new (Context) ObjCPropertyRefExpr(Getter, Setter,
+                                                   Context.PseudoObjectTy,
+                                                   VK_LValue, OK_ObjCProperty,
+                                                   propertyNameLoc,
+                                                   receiverNameLoc, IFace));
+  }
+  return ExprError(Diag(propertyNameLoc, diag::err_property_not_found)
+                     << &propertyName << Context.getObjCInterfaceType(IFace));
+}
+
+namespace {
+
+class ObjCInterfaceOrSuperCCC : public CorrectionCandidateCallback {
+ public:
+  ObjCInterfaceOrSuperCCC(ObjCMethodDecl *Method) {
+    // Determine whether "super" is acceptable in the current context.
+    if (Method && Method->getClassInterface())
+      WantObjCSuper = Method->getClassInterface()->getSuperClass();
+  }
+
+  virtual bool ValidateCandidate(const TypoCorrection &candidate) {
+    return candidate.getCorrectionDeclAs<ObjCInterfaceDecl>() ||
+        candidate.isKeyword("super");
+  }
+};
+
+}
+
+Sema::ObjCMessageKind Sema::getObjCMessageKind(Scope *S,
+                                               IdentifierInfo *Name,
+                                               SourceLocation NameLoc,
+                                               bool IsSuper,
+                                               bool HasTrailingDot,
+                                               ParsedType &ReceiverType) {
+  ReceiverType = ParsedType();
+
+  // If the identifier is "super" and there is no trailing dot, we're
+  // messaging super. If the identifier is "super" and there is a
+  // trailing dot, it's an instance message.
+  if (IsSuper && S->isInObjcMethodScope())
+    return HasTrailingDot? ObjCInstanceMessage : ObjCSuperMessage;
+  
+  LookupResult Result(*this, Name, NameLoc, LookupOrdinaryName);
+  LookupName(Result, S);
+  
+  switch (Result.getResultKind()) {
+  case LookupResult::NotFound:
+    // Normal name lookup didn't find anything. If we're in an
+    // Objective-C method, look for ivars. If we find one, we're done!
+    // FIXME: This is a hack. Ivar lookup should be part of normal
+    // lookup.
+    if (ObjCMethodDecl *Method = getCurMethodDecl()) {
+      if (!Method->getClassInterface()) {
+        // Fall back: let the parser try to parse it as an instance message.
+        return ObjCInstanceMessage;
+      }
+
+      ObjCInterfaceDecl *ClassDeclared;
+      if (Method->getClassInterface()->lookupInstanceVariable(Name, 
+                                                              ClassDeclared))
+        return ObjCInstanceMessage;
+    }
+  
+    // Break out; we'll perform typo correction below.
+    break;
+
+  case LookupResult::NotFoundInCurrentInstantiation:
+  case LookupResult::FoundOverloaded:
+  case LookupResult::FoundUnresolvedValue:
+  case LookupResult::Ambiguous:
+    Result.suppressDiagnostics();
+    return ObjCInstanceMessage;
+
+  case LookupResult::Found: {
+    // If the identifier is a class or not, and there is a trailing dot,
+    // it's an instance message.
+    if (HasTrailingDot)
+      return ObjCInstanceMessage;
+    // We found something. If it's a type, then we have a class
+    // message. Otherwise, it's an instance message.
+    NamedDecl *ND = Result.getFoundDecl();
+    QualType T;
+    if (ObjCInterfaceDecl *Class = dyn_cast<ObjCInterfaceDecl>(ND))
+      T = Context.getObjCInterfaceType(Class);
+    else if (TypeDecl *Type = dyn_cast<TypeDecl>(ND))
+      T = Context.getTypeDeclType(Type);
+    else 
+      return ObjCInstanceMessage;
+
+    //  We have a class message, and T is the type we're
+    //  messaging. Build source-location information for it.
+    TypeSourceInfo *TSInfo = Context.getTrivialTypeSourceInfo(T, NameLoc);
+    ReceiverType = CreateParsedType(T, TSInfo);
+    return ObjCClassMessage;
+  }
+  }
+
+  ObjCInterfaceOrSuperCCC Validator(getCurMethodDecl());
+  if (TypoCorrection Corrected = CorrectTypo(Result.getLookupNameInfo(),
+                                             Result.getLookupKind(), S, NULL,
+                                             Validator)) {
+    if (Corrected.isKeyword()) {
+      // If we've found the keyword "super" (the only keyword that would be
+      // returned by CorrectTypo), this is a send to super.
+      Diag(NameLoc, diag::err_unknown_receiver_suggest)
+        << Name << Corrected.getCorrection()
+        << FixItHint::CreateReplacement(SourceRange(NameLoc), "super");
+      return ObjCSuperMessage;
+    } else if (ObjCInterfaceDecl *Class =
+               Corrected.getCorrectionDeclAs<ObjCInterfaceDecl>()) {
+      // If we found a declaration, correct when it refers to an Objective-C
+      // class.
+      Diag(NameLoc, diag::err_unknown_receiver_suggest)
+        << Name << Corrected.getCorrection()
+        << FixItHint::CreateReplacement(SourceRange(NameLoc),
+                                        Class->getNameAsString());
+      Diag(Class->getLocation(), diag::note_previous_decl)
+        << Corrected.getCorrection();
+
+      QualType T = Context.getObjCInterfaceType(Class);
+      TypeSourceInfo *TSInfo = Context.getTrivialTypeSourceInfo(T, NameLoc);
+      ReceiverType = CreateParsedType(T, TSInfo);
+      return ObjCClassMessage;
+    }
+  }
+  
+  // Fall back: let the parser try to parse it as an instance message.
+  return ObjCInstanceMessage;
+}
+
+ExprResult Sema::ActOnSuperMessage(Scope *S, 
+                                   SourceLocation SuperLoc,
+                                   Selector Sel,
+                                   SourceLocation LBracLoc,
+                                   ArrayRef<SourceLocation> SelectorLocs,
+                                   SourceLocation RBracLoc,
+                                   MultiExprArg Args) {
+  // Determine whether we are inside a method or not.
+  ObjCMethodDecl *Method = tryCaptureObjCSelf(SuperLoc);
+  if (!Method) {
+    Diag(SuperLoc, diag::err_invalid_receiver_to_message_super);
+    return ExprError();
+  }
+
+  ObjCInterfaceDecl *Class = Method->getClassInterface();
+  if (!Class) {
+    Diag(SuperLoc, diag::error_no_super_class_message)
+      << Method->getDeclName();
+    return ExprError();
+  }
+
+  ObjCInterfaceDecl *Super = Class->getSuperClass();
+  if (!Super) {
+    // The current class does not have a superclass.
+    Diag(SuperLoc, diag::error_root_class_cannot_use_super)
+      << Class->getIdentifier();
+    return ExprError();
+  }
+
+  // We are in a method whose class has a superclass, so 'super'
+  // is acting as a keyword.
+  if (Method->isInstanceMethod()) {
+    if (Sel.getMethodFamily() == OMF_dealloc)
+      ObjCShouldCallSuperDealloc = false;
+    if (Sel.getMethodFamily() == OMF_finalize)
+      ObjCShouldCallSuperFinalize = false;
+
+    // Since we are in an instance method, this is an instance
+    // message to the superclass instance.
+    QualType SuperTy = Context.getObjCInterfaceType(Super);
+    SuperTy = Context.getObjCObjectPointerType(SuperTy);
+    return BuildInstanceMessage(0, SuperTy, SuperLoc,
+                                Sel, /*Method=*/0,
+                                LBracLoc, SelectorLocs, RBracLoc, move(Args));
+  }
+  
+  // Since we are in a class method, this is a class message to
+  // the superclass.
+  return BuildClassMessage(/*ReceiverTypeInfo=*/0,
+                           Context.getObjCInterfaceType(Super),
+                           SuperLoc, Sel, /*Method=*/0,
+                           LBracLoc, SelectorLocs, RBracLoc, move(Args));
+}
+
+
+ExprResult Sema::BuildClassMessageImplicit(QualType ReceiverType,
+                                           bool isSuperReceiver,
+                                           SourceLocation Loc,
+                                           Selector Sel,
+                                           ObjCMethodDecl *Method,
+                                           MultiExprArg Args) {
+  TypeSourceInfo *receiverTypeInfo = 0;
+  if (!ReceiverType.isNull())
+    receiverTypeInfo = Context.getTrivialTypeSourceInfo(ReceiverType);
+
+  return BuildClassMessage(receiverTypeInfo, ReceiverType,
+                          /*SuperLoc=*/isSuperReceiver ? Loc : SourceLocation(),
+                           Sel, Method, Loc, Loc, Loc, Args,
+                           /*isImplicit=*/true);
+
+}
+
+static void applyCocoaAPICheck(Sema &S, const ObjCMessageExpr *Msg,
+                               unsigned DiagID,
+                               bool (*refactor)(const ObjCMessageExpr *,
+                                              const NSAPI &, edit::Commit &)) {
+  SourceLocation MsgLoc = Msg->getExprLoc();
+  if (S.Diags.getDiagnosticLevel(DiagID, MsgLoc) == DiagnosticsEngine::Ignored)
+    return;
+
+  SourceManager &SM = S.SourceMgr;
+  edit::Commit ECommit(SM, S.LangOpts);
+  if (refactor(Msg,*S.NSAPIObj, ECommit)) {
+    DiagnosticBuilder Builder = S.Diag(MsgLoc, DiagID)
+                        << Msg->getSelector() << Msg->getSourceRange();
+    // FIXME: Don't emit diagnostic at all if fixits are non-commitable.
+    if (!ECommit.isCommitable())
+      return;
+    for (edit::Commit::edit_iterator
+           I = ECommit.edit_begin(), E = ECommit.edit_end(); I != E; ++I) {
+      const edit::Commit::Edit &Edit = *I;
+      switch (Edit.Kind) {
+      case edit::Commit::Act_Insert:
+        Builder.AddFixItHint(FixItHint::CreateInsertion(Edit.OrigLoc,
+                                                        Edit.Text,
+                                                        Edit.BeforePrev));
+        break;
+      case edit::Commit::Act_InsertFromRange:
+        Builder.AddFixItHint(
+            FixItHint::CreateInsertionFromRange(Edit.OrigLoc,
+                                                Edit.getInsertFromRange(SM),
+                                                Edit.BeforePrev));
+        break;
+      case edit::Commit::Act_Remove:
+        Builder.AddFixItHint(FixItHint::CreateRemoval(Edit.getFileRange(SM)));
+        break;
+      }
+    }
+  }
+}
+
+static void checkCocoaAPI(Sema &S, const ObjCMessageExpr *Msg) {
+  applyCocoaAPICheck(S, Msg, diag::warn_objc_redundant_literal_use,
+                     edit::rewriteObjCRedundantCallWithLiteral);
+}
+
+/// \brief Build an Objective-C class message expression.
+///
+/// This routine takes care of both normal class messages and
+/// class messages to the superclass.
+///
+/// \param ReceiverTypeInfo Type source information that describes the
+/// receiver of this message. This may be NULL, in which case we are
+/// sending to the superclass and \p SuperLoc must be a valid source
+/// location.
+
+/// \param ReceiverType The type of the object receiving the
+/// message. When \p ReceiverTypeInfo is non-NULL, this is the same
+/// type as that refers to. For a superclass send, this is the type of
+/// the superclass.
+///
+/// \param SuperLoc The location of the "super" keyword in a
+/// superclass message.
+///
+/// \param Sel The selector to which the message is being sent.
+///
+/// \param Method The method that this class message is invoking, if
+/// already known.
+///
+/// \param LBracLoc The location of the opening square bracket ']'.
+///
+/// \param RBrac The location of the closing square bracket ']'.
+///
+/// \param Args The message arguments.
+ExprResult Sema::BuildClassMessage(TypeSourceInfo *ReceiverTypeInfo,
+                                   QualType ReceiverType,
+                                   SourceLocation SuperLoc,
+                                   Selector Sel,
+                                   ObjCMethodDecl *Method,
+                                   SourceLocation LBracLoc, 
+                                   ArrayRef<SourceLocation> SelectorLocs,
+                                   SourceLocation RBracLoc,
+                                   MultiExprArg ArgsIn,
+                                   bool isImplicit) {
+  SourceLocation Loc = SuperLoc.isValid()? SuperLoc
+    : ReceiverTypeInfo->getTypeLoc().getSourceRange().getBegin();
+  if (LBracLoc.isInvalid()) {
+    Diag(Loc, diag::err_missing_open_square_message_send)
+      << FixItHint::CreateInsertion(Loc, "[");
+    LBracLoc = Loc;
+  }
+  
+  if (ReceiverType->isDependentType()) {
+    // If the receiver type is dependent, we can't type-check anything
+    // at this point. Build a dependent expression.
+    unsigned NumArgs = ArgsIn.size();
+    Expr **Args = reinterpret_cast<Expr **>(ArgsIn.release());
+    assert(SuperLoc.isInvalid() && "Message to super with dependent type");
+    return Owned(ObjCMessageExpr::Create(Context, ReceiverType,
+                                         VK_RValue, LBracLoc, ReceiverTypeInfo,
+                                         Sel, SelectorLocs, /*Method=*/0,
+                                         makeArrayRef(Args, NumArgs),RBracLoc,
+                                         isImplicit));
+  }
+  
+  // Find the class to which we are sending this message.
+  ObjCInterfaceDecl *Class = 0;
+  const ObjCObjectType *ClassType = ReceiverType->getAs<ObjCObjectType>();
+  if (!ClassType || !(Class = ClassType->getInterface())) {
+    Diag(Loc, diag::err_invalid_receiver_class_message)
+      << ReceiverType;
+    return ExprError();
+  }
+  assert(Class && "We don't know which class we're messaging?");
+  // objc++ diagnoses during typename annotation.
+  if (!getLangOpts().CPlusPlus)
+    (void)DiagnoseUseOfDecl(Class, Loc);
+  // Find the method we are messaging.
+  if (!Method) {
+    SourceRange TypeRange 
+      = SuperLoc.isValid()? SourceRange(SuperLoc)
+                          : ReceiverTypeInfo->getTypeLoc().getSourceRange();
+    if (RequireCompleteType(Loc, Context.getObjCInterfaceType(Class), 
+                            (getLangOpts().ObjCAutoRefCount
+                               ? PDiag(diag::err_arc_receiver_forward_class)
+                               : PDiag(diag::warn_receiver_forward_class))
+                                   << TypeRange)) {
+      // A forward class used in messaging is treated as a 'Class'
+      Method = LookupFactoryMethodInGlobalPool(Sel, 
+                                               SourceRange(LBracLoc, RBracLoc));
+      if (Method && !getLangOpts().ObjCAutoRefCount)
+        Diag(Method->getLocation(), diag::note_method_sent_forward_class)
+          << Method->getDeclName();
+    }
+    if (!Method)
+      Method = Class->lookupClassMethod(Sel);
+
+    // If we have an implementation in scope, check "private" methods.
+    if (!Method)
+      Method = LookupPrivateClassMethod(Sel, Class);
+
+    if (Method && DiagnoseUseOfDecl(Method, Loc))
+      return ExprError();
+  }
+
+  // Check the argument types and determine the result type.
+  QualType ReturnType;
+  ExprValueKind VK = VK_RValue;
+
+  unsigned NumArgs = ArgsIn.size();
+  Expr **Args = reinterpret_cast<Expr **>(ArgsIn.release());
+  if (CheckMessageArgumentTypes(ReceiverType, Args, NumArgs, Sel, Method, true,
+                                SuperLoc.isValid(), LBracLoc, RBracLoc, 
+                                ReturnType, VK))
+    return ExprError();
+
+  if (Method && !Method->getResultType()->isVoidType() &&
+      RequireCompleteType(LBracLoc, Method->getResultType(), 
+                          diag::err_illegal_message_expr_incomplete_type))
+    return ExprError();
+
+  // Construct the appropriate ObjCMessageExpr.
+  ObjCMessageExpr *Result;
+  if (SuperLoc.isValid())
+    Result = ObjCMessageExpr::Create(Context, ReturnType, VK, LBracLoc, 
+                                     SuperLoc, /*IsInstanceSuper=*/false, 
+                                     ReceiverType, Sel, SelectorLocs,
+                                     Method, makeArrayRef(Args, NumArgs),
+                                     RBracLoc, isImplicit);
+  else {
+    Result = ObjCMessageExpr::Create(Context, ReturnType, VK, LBracLoc, 
+                                     ReceiverTypeInfo, Sel, SelectorLocs,
+                                     Method, makeArrayRef(Args, NumArgs),
+                                     RBracLoc, isImplicit);
+    if (!isImplicit)
+      checkCocoaAPI(*this, Result);
+  }
+  return MaybeBindToTemporary(Result);
+}
+
+// ActOnClassMessage - used for both unary and keyword messages.
+// ArgExprs is optional - if it is present, the number of expressions
+// is obtained from Sel.getNumArgs().
+ExprResult Sema::ActOnClassMessage(Scope *S, 
+                                   ParsedType Receiver,
+                                   Selector Sel,
+                                   SourceLocation LBracLoc,
+                                   ArrayRef<SourceLocation> SelectorLocs,
+                                   SourceLocation RBracLoc,
+                                   MultiExprArg Args) {
+  TypeSourceInfo *ReceiverTypeInfo;
+  QualType ReceiverType = GetTypeFromParser(Receiver, &ReceiverTypeInfo);
+  if (ReceiverType.isNull())
+    return ExprError();
+
+
+  if (!ReceiverTypeInfo)
+    ReceiverTypeInfo = Context.getTrivialTypeSourceInfo(ReceiverType, LBracLoc);
+
+  return BuildClassMessage(ReceiverTypeInfo, ReceiverType, 
+                           /*SuperLoc=*/SourceLocation(), Sel, /*Method=*/0,
+                           LBracLoc, SelectorLocs, RBracLoc, move(Args));
+}
+
+ExprResult Sema::BuildInstanceMessageImplicit(Expr *Receiver,
+                                              QualType ReceiverType,
+                                              SourceLocation Loc,
+                                              Selector Sel,
+                                              ObjCMethodDecl *Method,
+                                              MultiExprArg Args) {
+  return BuildInstanceMessage(Receiver, ReceiverType,
+                              /*SuperLoc=*/!Receiver ? Loc : SourceLocation(),
+                              Sel, Method, Loc, Loc, Loc, Args,
+                              /*isImplicit=*/true);
+}
+
+/// \brief Build an Objective-C instance message expression.
+///
+/// This routine takes care of both normal instance messages and
+/// instance messages to the superclass instance.
+///
+/// \param Receiver The expression that computes the object that will
+/// receive this message. This may be empty, in which case we are
+/// sending to the superclass instance and \p SuperLoc must be a valid
+/// source location.
+///
+/// \param ReceiverType The (static) type of the object receiving the
+/// message. When a \p Receiver expression is provided, this is the
+/// same type as that expression. For a superclass instance send, this
+/// is a pointer to the type of the superclass.
+///
+/// \param SuperLoc The location of the "super" keyword in a
+/// superclass instance message.
+///
+/// \param Sel The selector to which the message is being sent.
+///
+/// \param Method The method that this instance message is invoking, if
+/// already known.
+///
+/// \param LBracLoc The location of the opening square bracket ']'.
+///
+/// \param RBrac The location of the closing square bracket ']'.
+///
+/// \param Args The message arguments.
+ExprResult Sema::BuildInstanceMessage(Expr *Receiver,
+                                      QualType ReceiverType,
+                                      SourceLocation SuperLoc,
+                                      Selector Sel,
+                                      ObjCMethodDecl *Method,
+                                      SourceLocation LBracLoc, 
+                                      ArrayRef<SourceLocation> SelectorLocs,
+                                      SourceLocation RBracLoc,
+                                      MultiExprArg ArgsIn,
+                                      bool isImplicit) {
+  // The location of the receiver.
+  SourceLocation Loc = SuperLoc.isValid()? SuperLoc : Receiver->getLocStart();
+  
+  if (LBracLoc.isInvalid()) {
+    Diag(Loc, diag::err_missing_open_square_message_send)
+      << FixItHint::CreateInsertion(Loc, "[");
+    LBracLoc = Loc;
+  }
+
+  // If we have a receiver expression, perform appropriate promotions
+  // and determine receiver type.
+  if (Receiver) {
+    if (Receiver->hasPlaceholderType()) {
+      ExprResult Result;
+      if (Receiver->getType() == Context.UnknownAnyTy)
+        Result = forceUnknownAnyToType(Receiver, Context.getObjCIdType());
+      else
+        Result = CheckPlaceholderExpr(Receiver);
+      if (Result.isInvalid()) return ExprError();
+      Receiver = Result.take();
+    }
+
+    if (Receiver->isTypeDependent()) {
+      // If the receiver is type-dependent, we can't type-check anything
+      // at this point. Build a dependent expression.
+      unsigned NumArgs = ArgsIn.size();
+      Expr **Args = reinterpret_cast<Expr **>(ArgsIn.release());
+      assert(SuperLoc.isInvalid() && "Message to super with dependent type");
+      return Owned(ObjCMessageExpr::Create(Context, Context.DependentTy,
+                                           VK_RValue, LBracLoc, Receiver, Sel, 
+                                           SelectorLocs, /*Method=*/0,
+                                           makeArrayRef(Args, NumArgs),
+                                           RBracLoc, isImplicit));
+    }
+
+    // If necessary, apply function/array conversion to the receiver.
+    // C99 6.7.5.3p[7,8].
+    ExprResult Result = DefaultFunctionArrayLvalueConversion(Receiver);
+    if (Result.isInvalid())
+      return ExprError();
+    Receiver = Result.take();
+    ReceiverType = Receiver->getType();
+  }
+
+  if (!Method) {
+    // Handle messages to id.
+    bool receiverIsId = ReceiverType->isObjCIdType();
+    if (receiverIsId || ReceiverType->isBlockPointerType() ||
+        (Receiver && Context.isObjCNSObjectType(Receiver->getType()))) {
+      Method = LookupInstanceMethodInGlobalPool(Sel, 
+                                                SourceRange(LBracLoc, RBracLoc),
+                                                receiverIsId);
+      if (!Method)
+        Method = LookupFactoryMethodInGlobalPool(Sel, 
+                                                 SourceRange(LBracLoc, RBracLoc),
+                                                 receiverIsId);
+    } else if (ReceiverType->isObjCClassType() ||
+               ReceiverType->isObjCQualifiedClassType()) {
+      // Handle messages to Class.
+      // We allow sending a message to a qualified Class ("Class<foo>"), which 
+      // is ok as long as one of the protocols implements the selector (if not, warn).
+      if (const ObjCObjectPointerType *QClassTy 
+            = ReceiverType->getAsObjCQualifiedClassType()) {
+        // Search protocols for class methods.
+        Method = LookupMethodInQualifiedType(Sel, QClassTy, false);
+        if (!Method) {
+          Method = LookupMethodInQualifiedType(Sel, QClassTy, true);
+          // warn if instance method found for a Class message.
+          if (Method) {
+            Diag(Loc, diag::warn_instance_method_on_class_found)
+              << Method->getSelector() << Sel;
+            Diag(Method->getLocation(), diag::note_method_declared_at)
+              << Method->getDeclName();
+          }
+        }
+      } else {
+        if (ObjCMethodDecl *CurMeth = getCurMethodDecl()) {
+          if (ObjCInterfaceDecl *ClassDecl = CurMeth->getClassInterface()) {
+            // First check the public methods in the class interface.
+            Method = ClassDecl->lookupClassMethod(Sel);
+
+            if (!Method)
+              Method = LookupPrivateClassMethod(Sel, ClassDecl);
+          }
+          if (Method && DiagnoseUseOfDecl(Method, Loc))
+            return ExprError();
+        }
+        if (!Method) {
+          // If not messaging 'self', look for any factory method named 'Sel'.
+          if (!Receiver || !isSelfExpr(Receiver)) {
+            Method = LookupFactoryMethodInGlobalPool(Sel, 
+                                                SourceRange(LBracLoc, RBracLoc),
+                                                     true);
+            if (!Method) {
+              // If no class (factory) method was found, check if an _instance_
+              // method of the same name exists in the root class only.
+              Method = LookupInstanceMethodInGlobalPool(Sel,
+                                               SourceRange(LBracLoc, RBracLoc),
+                                                        true);
+              if (Method)
+                  if (const ObjCInterfaceDecl *ID =
+                      dyn_cast<ObjCInterfaceDecl>(Method->getDeclContext())) {
+                    if (ID->getSuperClass())
+                      Diag(Loc, diag::warn_root_inst_method_not_found)
+                      << Sel << SourceRange(LBracLoc, RBracLoc);
+                  }
+            }
+          }
+        }
+      }
+    } else {
+      ObjCInterfaceDecl* ClassDecl = 0;
+
+      // We allow sending a message to a qualified ID ("id<foo>"), which is ok as
+      // long as one of the protocols implements the selector (if not, warn).
+      if (const ObjCObjectPointerType *QIdTy 
+                                   = ReceiverType->getAsObjCQualifiedIdType()) {
+        // Search protocols for instance methods.
+        Method = LookupMethodInQualifiedType(Sel, QIdTy, true);
+        if (!Method)
+          Method = LookupMethodInQualifiedType(Sel, QIdTy, false);
+      } else if (const ObjCObjectPointerType *OCIType
+                   = ReceiverType->getAsObjCInterfacePointerType()) {
+        // We allow sending a message to a pointer to an interface (an object).
+        ClassDecl = OCIType->getInterfaceDecl();
+
+        // Try to complete the type. Under ARC, this is a hard error from which
+        // we don't try to recover.
+        const ObjCInterfaceDecl *forwardClass = 0;
+        if (RequireCompleteType(Loc, OCIType->getPointeeType(),
+              getLangOpts().ObjCAutoRefCount
+                ? PDiag(diag::err_arc_receiver_forward_instance)
+                    << (Receiver ? Receiver->getSourceRange() 
+                                 : SourceRange(SuperLoc))
+                : PDiag(diag::warn_receiver_forward_instance)
+                    << (Receiver ? Receiver->getSourceRange() 
+                                 : SourceRange(SuperLoc)))) {
+          if (getLangOpts().ObjCAutoRefCount)
+            return ExprError();
+          
+          forwardClass = OCIType->getInterfaceDecl();
+          Diag(Receiver ? Receiver->getLocStart() 
+                        : SuperLoc, diag::note_receiver_is_id);
+          Method = 0;
+        } else {
+          Method = ClassDecl->lookupInstanceMethod(Sel);
+        }
+
+        if (!Method)
+          // Search protocol qualifiers.
+          Method = LookupMethodInQualifiedType(Sel, OCIType, true);
+        
+        if (!Method) {
+          // If we have implementations in scope, check "private" methods.
+          Method = LookupPrivateInstanceMethod(Sel, ClassDecl);
+
+          if (!Method && getLangOpts().ObjCAutoRefCount) {
+            Diag(Loc, diag::err_arc_may_not_respond)
+              << OCIType->getPointeeType() << Sel;
+            return ExprError();
+          }
+
+          if (!Method && (!Receiver || !isSelfExpr(Receiver))) {
+            // If we still haven't found a method, look in the global pool. This
+            // behavior isn't very desirable, however we need it for GCC
+            // compatibility. FIXME: should we deviate??
+            if (OCIType->qual_empty()) {
+              Method = LookupInstanceMethodInGlobalPool(Sel,
+                                                 SourceRange(LBracLoc, RBracLoc));
+              if (Method && !forwardClass)
+                Diag(Loc, diag::warn_maynot_respond)
+                  << OCIType->getInterfaceDecl()->getIdentifier() << Sel;
+            }
+          }
+        }
+        if (Method && DiagnoseUseOfDecl(Method, Loc, forwardClass))
+          return ExprError();
+      } else if (!getLangOpts().ObjCAutoRefCount &&
+                 !Context.getObjCIdType().isNull() &&
+                 (ReceiverType->isPointerType() || 
+                  ReceiverType->isIntegerType())) {
+        // Implicitly convert integers and pointers to 'id' but emit a warning.
+        // But not in ARC.
+        Diag(Loc, diag::warn_bad_receiver_type)
+          << ReceiverType 
+          << Receiver->getSourceRange();
+        if (ReceiverType->isPointerType())
+          Receiver = ImpCastExprToType(Receiver, Context.getObjCIdType(), 
+                            CK_CPointerToObjCPointerCast).take();
+        else {
+          // TODO: specialized warning on null receivers?
+          bool IsNull = Receiver->isNullPointerConstant(Context,
+                                              Expr::NPC_ValueDependentIsNull);
+          Receiver = ImpCastExprToType(Receiver, Context.getObjCIdType(),
+                            IsNull ? CK_NullToPointer : CK_IntegralToPointer).take();
+        }
+        ReceiverType = Receiver->getType();
+      } else {
+        ExprResult ReceiverRes;
+        if (getLangOpts().CPlusPlus)
+          ReceiverRes = PerformContextuallyConvertToObjCPointer(Receiver);
+        if (ReceiverRes.isUsable()) {
+          Receiver = ReceiverRes.take();
+          return BuildInstanceMessage(Receiver,
+                                      ReceiverType,
+                                      SuperLoc,
+                                      Sel,
+                                      Method,
+                                      LBracLoc,
+                                      SelectorLocs,
+                                      RBracLoc,
+                                      move(ArgsIn));
+        } else {
+          // Reject other random receiver types (e.g. structs).
+          Diag(Loc, diag::err_bad_receiver_type)
+            << ReceiverType << Receiver->getSourceRange();
+          return ExprError();
+        }
+      }
+    }
+  }
+
+  // Check the message arguments.
+  unsigned NumArgs = ArgsIn.size();
+  Expr **Args = reinterpret_cast<Expr **>(ArgsIn.release());
+  QualType ReturnType;
+  ExprValueKind VK = VK_RValue;
+  bool ClassMessage = (ReceiverType->isObjCClassType() ||
+                       ReceiverType->isObjCQualifiedClassType());
+  if (CheckMessageArgumentTypes(ReceiverType, Args, NumArgs, Sel, Method, 
+                                ClassMessage, SuperLoc.isValid(), 
+                                LBracLoc, RBracLoc, ReturnType, VK))
+    return ExprError();
+  
+  if (Method && !Method->getResultType()->isVoidType() &&
+      RequireCompleteType(LBracLoc, Method->getResultType(), 
+                          diag::err_illegal_message_expr_incomplete_type))
+    return ExprError();
+
+  SourceLocation SelLoc = SelectorLocs.front();
+
+  // In ARC, forbid the user from sending messages to 
+  // retain/release/autorelease/dealloc/retainCount explicitly.
+  if (getLangOpts().ObjCAutoRefCount) {
+    ObjCMethodFamily family =
+      (Method ? Method->getMethodFamily() : Sel.getMethodFamily());
+    switch (family) {
+    case OMF_init:
+      if (Method)
+        checkInitMethod(Method, ReceiverType);
+
+    case OMF_None:
+    case OMF_alloc:
+    case OMF_copy:
+    case OMF_finalize:
+    case OMF_mutableCopy:
+    case OMF_new:
+    case OMF_self:
+      break;
+
+    case OMF_dealloc:
+    case OMF_retain:
+    case OMF_release:
+    case OMF_autorelease:
+    case OMF_retainCount:
+      Diag(Loc, diag::err_arc_illegal_explicit_message)
+        << Sel << SelLoc;
+      break;
+    
+    case OMF_performSelector:
+      if (Method && NumArgs >= 1) {
+        if (ObjCSelectorExpr *SelExp = dyn_cast<ObjCSelectorExpr>(Args[0])) {
+          Selector ArgSel = SelExp->getSelector();
+          ObjCMethodDecl *SelMethod = 
+            LookupInstanceMethodInGlobalPool(ArgSel,
+                                             SelExp->getSourceRange());
+          if (!SelMethod)
+            SelMethod =
+              LookupFactoryMethodInGlobalPool(ArgSel,
+                                              SelExp->getSourceRange());
+          if (SelMethod) {
+            ObjCMethodFamily SelFamily = SelMethod->getMethodFamily();
+            switch (SelFamily) {
+              case OMF_alloc:
+              case OMF_copy:
+              case OMF_mutableCopy:
+              case OMF_new:
+              case OMF_self:
+              case OMF_init:
+                // Issue error, unless ns_returns_not_retained.
+                if (!SelMethod->hasAttr<NSReturnsNotRetainedAttr>()) {
+                  // selector names a +1 method 
+                  Diag(SelLoc, 
+                       diag::err_arc_perform_selector_retains);
+                  Diag(SelMethod->getLocation(), diag::note_method_declared_at)
+                    << SelMethod->getDeclName();
+                }
+                break;
+              default:
+                // +0 call. OK. unless ns_returns_retained.
+                if (SelMethod->hasAttr<NSReturnsRetainedAttr>()) {
+                  // selector names a +1 method
+                  Diag(SelLoc, 
+                       diag::err_arc_perform_selector_retains);
+                  Diag(SelMethod->getLocation(), diag::note_method_declared_at)
+                    << SelMethod->getDeclName();
+                }
+                break;
+            }
+          }
+        } else {
+          // error (may leak).
+          Diag(SelLoc, diag::warn_arc_perform_selector_leaks);
+          Diag(Args[0]->getExprLoc(), diag::note_used_here);
+        }
+      }
+      break;
+    }
+  }
+
+  // Construct the appropriate ObjCMessageExpr instance.
+  ObjCMessageExpr *Result;
+  if (SuperLoc.isValid())
+    Result = ObjCMessageExpr::Create(Context, ReturnType, VK, LBracLoc,
+                                     SuperLoc,  /*IsInstanceSuper=*/true,
+                                     ReceiverType, Sel, SelectorLocs, Method, 
+                                     makeArrayRef(Args, NumArgs), RBracLoc,
+                                     isImplicit);
+  else {
+    Result = ObjCMessageExpr::Create(Context, ReturnType, VK, LBracLoc,
+                                     Receiver, Sel, SelectorLocs, Method,
+                                     makeArrayRef(Args, NumArgs), RBracLoc,
+                                     isImplicit);
+    if (!isImplicit)
+      checkCocoaAPI(*this, Result);
+  }
+
+  if (getLangOpts().ObjCAutoRefCount) {
+    if (Receiver &&
+        (Receiver->IgnoreParenImpCasts()->getType().getObjCLifetime() 
+          == Qualifiers::OCL_Weak))
+      Diag(Receiver->getLocStart(), diag::warn_receiver_is_weak);
+    
+    // In ARC, annotate delegate init calls.
+    if (Result->getMethodFamily() == OMF_init &&
+        (SuperLoc.isValid() || isSelfExpr(Receiver))) {
+      // Only consider init calls *directly* in init implementations,
+      // not within blocks.
+      ObjCMethodDecl *method = dyn_cast<ObjCMethodDecl>(CurContext);
+      if (method && method->getMethodFamily() == OMF_init) {
+        // The implicit assignment to self means we also don't want to
+        // consume the result.
+        Result->setDelegateInitCall(true);
+        return Owned(Result);
+      }
+    }
+
+    // In ARC, check for message sends which are likely to introduce
+    // retain cycles.
+    checkRetainCycles(Result);
+  }
+      
+  return MaybeBindToTemporary(Result);
+}
+
+// ActOnInstanceMessage - used for both unary and keyword messages.
+// ArgExprs is optional - if it is present, the number of expressions
+// is obtained from Sel.getNumArgs().
+ExprResult Sema::ActOnInstanceMessage(Scope *S,
+                                      Expr *Receiver, 
+                                      Selector Sel,
+                                      SourceLocation LBracLoc,
+                                      ArrayRef<SourceLocation> SelectorLocs,
+                                      SourceLocation RBracLoc,
+                                      MultiExprArg Args) {
+  if (!Receiver)
+    return ExprError();
+
+  return BuildInstanceMessage(Receiver, Receiver->getType(),
+                              /*SuperLoc=*/SourceLocation(), Sel, /*Method=*/0, 
+                              LBracLoc, SelectorLocs, RBracLoc, move(Args));
+}
+
+enum ARCConversionTypeClass {
+  /// int, void, struct A
+  ACTC_none,
+
+  /// id, void (^)()
+  ACTC_retainable,
+
+  /// id*, id***, void (^*)(),
+  ACTC_indirectRetainable,
+
+  /// void* might be a normal C type, or it might a CF type.
+  ACTC_voidPtr,
+
+  /// struct A*
+  ACTC_coreFoundation
+};
+static bool isAnyRetainable(ARCConversionTypeClass ACTC) {
+  return (ACTC == ACTC_retainable ||
+          ACTC == ACTC_coreFoundation ||
+          ACTC == ACTC_voidPtr);
+}
+static bool isAnyCLike(ARCConversionTypeClass ACTC) {
+  return ACTC == ACTC_none ||
+         ACTC == ACTC_voidPtr ||
+         ACTC == ACTC_coreFoundation;
+}
+
+static ARCConversionTypeClass classifyTypeForARCConversion(QualType type) {
+  bool isIndirect = false;
+  
+  // Ignore an outermost reference type.
+  if (const ReferenceType *ref = type->getAs<ReferenceType>()) {
+    type = ref->getPointeeType();
+    isIndirect = true;
+  }
+  
+  // Drill through pointers and arrays recursively.
+  while (true) {
+    if (const PointerType *ptr = type->getAs<PointerType>()) {
+      type = ptr->getPointeeType();
+
+      // The first level of pointer may be the innermost pointer on a CF type.
+      if (!isIndirect) {
+        if (type->isVoidType()) return ACTC_voidPtr;
+        if (type->isRecordType()) return ACTC_coreFoundation;
+      }
+    } else if (const ArrayType *array = type->getAsArrayTypeUnsafe()) {
+      type = QualType(array->getElementType()->getBaseElementTypeUnsafe(), 0);
+    } else {
+      break;
+    }
+    isIndirect = true;
+  }
+  
+  if (isIndirect) {
+    if (type->isObjCARCBridgableType())
+      return ACTC_indirectRetainable;
+    return ACTC_none;
+  }
+
+  if (type->isObjCARCBridgableType())
+    return ACTC_retainable;
+
+  return ACTC_none;
+}
+
+namespace {
+  /// A result from the cast checker.
+  enum ACCResult {
+    /// Cannot be casted.
+    ACC_invalid,
+
+    /// Can be safely retained or not retained.
+    ACC_bottom,
+
+    /// Can be casted at +0.
+    ACC_plusZero,
+
+    /// Can be casted at +1.
+    ACC_plusOne
+  };
+  ACCResult merge(ACCResult left, ACCResult right) {
+    if (left == right) return left;
+    if (left == ACC_bottom) return right;
+    if (right == ACC_bottom) return left;
+    return ACC_invalid;
+  }
+
+  /// A checker which white-lists certain expressions whose conversion
+  /// to or from retainable type would otherwise be forbidden in ARC.
+  class ARCCastChecker : public StmtVisitor<ARCCastChecker, ACCResult> {
+    typedef StmtVisitor<ARCCastChecker, ACCResult> super;
+
+    ASTContext &Context;
+    ARCConversionTypeClass SourceClass;
+    ARCConversionTypeClass TargetClass;
+
+    static bool isCFType(QualType type) {
+      // Someday this can use ns_bridged.  For now, it has to do this.
+      return type->isCARCBridgableType();
+    }
+
+  public:
+    ARCCastChecker(ASTContext &Context, ARCConversionTypeClass source,
+                   ARCConversionTypeClass target)
+      : Context(Context), SourceClass(source), TargetClass(target) {}
+
+    using super::Visit;
+    ACCResult Visit(Expr *e) {
+      return super::Visit(e->IgnoreParens());
+    }
+
+    ACCResult VisitStmt(Stmt *s) {
+      return ACC_invalid;
+    }
+
+    /// Null pointer constants can be casted however you please.
+    ACCResult VisitExpr(Expr *e) {
+      if (e->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNotNull))
+        return ACC_bottom;
+      return ACC_invalid;
+    }
+
+    /// Objective-C string literals can be safely casted.
+    ACCResult VisitObjCStringLiteral(ObjCStringLiteral *e) {
+      // If we're casting to any retainable type, go ahead.  Global
+      // strings are immune to retains, so this is bottom.
+      if (isAnyRetainable(TargetClass)) return ACC_bottom;
+
+      return ACC_invalid;
+    }
+    
+    /// Look through certain implicit and explicit casts.
+    ACCResult VisitCastExpr(CastExpr *e) {
+      switch (e->getCastKind()) {
+        case CK_NullToPointer:
+          return ACC_bottom;
+
+        case CK_NoOp:
+        case CK_LValueToRValue:
+        case CK_BitCast:
+        case CK_CPointerToObjCPointerCast:
+        case CK_BlockPointerToObjCPointerCast:
+        case CK_AnyPointerToBlockPointerCast:
+          return Visit(e->getSubExpr());
+
+        default:
+          return ACC_invalid;
+      }
+    }
+
+    /// Look through unary extension.
+    ACCResult VisitUnaryExtension(UnaryOperator *e) {
+      return Visit(e->getSubExpr());
+    }
+
+    /// Ignore the LHS of a comma operator.
+    ACCResult VisitBinComma(BinaryOperator *e) {
+      return Visit(e->getRHS());
+    }
+
+    /// Conditional operators are okay if both sides are okay.
+    ACCResult VisitConditionalOperator(ConditionalOperator *e) {
+      ACCResult left = Visit(e->getTrueExpr());
+      if (left == ACC_invalid) return ACC_invalid;
+      return merge(left, Visit(e->getFalseExpr()));
+    }
+
+    /// Look through pseudo-objects.
+    ACCResult VisitPseudoObjectExpr(PseudoObjectExpr *e) {
+      // If we're getting here, we should always have a result.
+      return Visit(e->getResultExpr());
+    }
+
+    /// Statement expressions are okay if their result expression is okay.
+    ACCResult VisitStmtExpr(StmtExpr *e) {
+      return Visit(e->getSubStmt()->body_back());
+    }
+
+    /// Some declaration references are okay.
+    ACCResult VisitDeclRefExpr(DeclRefExpr *e) {
+      // References to global constants from system headers are okay.
+      // These are things like 'kCFStringTransformToLatin'.  They are
+      // can also be assumed to be immune to retains.
+      VarDecl *var = dyn_cast<VarDecl>(e->getDecl());
+      if (isAnyRetainable(TargetClass) &&
+          isAnyRetainable(SourceClass) &&
+          var &&
+          var->getStorageClass() == SC_Extern &&
+          var->getType().isConstQualified() &&
+          Context.getSourceManager().isInSystemHeader(var->getLocation())) {
+        return ACC_bottom;
+      }
+
+      // Nothing else.
+      return ACC_invalid;
+    }
+
+    /// Some calls are okay.
+    ACCResult VisitCallExpr(CallExpr *e) {
+      if (FunctionDecl *fn = e->getDirectCallee())
+        if (ACCResult result = checkCallToFunction(fn))
+          return result;
+
+      return super::VisitCallExpr(e);
+    }
+
+    ACCResult checkCallToFunction(FunctionDecl *fn) {
+      // Require a CF*Ref return type.
+      if (!isCFType(fn->getResultType()))
+        return ACC_invalid;
+
+      if (!isAnyRetainable(TargetClass))
+        return ACC_invalid;
+
+      // Honor an explicit 'not retained' attribute.
+      if (fn->hasAttr<CFReturnsNotRetainedAttr>())
+        return ACC_plusZero;
+
+      // Honor an explicit 'retained' attribute, except that for
+      // now we're not going to permit implicit handling of +1 results,
+      // because it's a bit frightening.
+      if (fn->hasAttr<CFReturnsRetainedAttr>())
+        return ACC_invalid; // ACC_plusOne if we start accepting this
+
+      // Recognize this specific builtin function, which is used by CFSTR.
+      unsigned builtinID = fn->getBuiltinID();
+      if (builtinID == Builtin::BI__builtin___CFStringMakeConstantString)
+        return ACC_bottom;
+
+      // Otherwise, don't do anything implicit with an unaudited function.
+      if (!fn->hasAttr<CFAuditedTransferAttr>())
+        return ACC_invalid;
+
+      // Otherwise, it's +0 unless it follows the create convention.
+      if (ento::coreFoundation::followsCreateRule(fn))
+        return ACC_invalid; // ACC_plusOne if we start accepting this
+
+      return ACC_plusZero;
+    }
+
+    ACCResult VisitObjCMessageExpr(ObjCMessageExpr *e) {
+      return checkCallToMethod(e->getMethodDecl());
+    }
+
+    ACCResult VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *e) {
+      ObjCMethodDecl *method;
+      if (e->isExplicitProperty())
+        method = e->getExplicitProperty()->getGetterMethodDecl();
+      else
+        method = e->getImplicitPropertyGetter();
+      return checkCallToMethod(method);
+    }
+
+    ACCResult checkCallToMethod(ObjCMethodDecl *method) {
+      if (!method) return ACC_invalid;
+
+      // Check for message sends to functions returning CF types.  We
+      // just obey the Cocoa conventions with these, even though the
+      // return type is CF.
+      if (!isAnyRetainable(TargetClass) || !isCFType(method->getResultType()))
+        return ACC_invalid;
+      
+      // If the method is explicitly marked not-retained, it's +0.
+      if (method->hasAttr<CFReturnsNotRetainedAttr>())
+        return ACC_plusZero;
+
+      // If the method is explicitly marked as returning retained, or its
+      // selector follows a +1 Cocoa convention, treat it as +1.
+      if (method->hasAttr<CFReturnsRetainedAttr>())
+        return ACC_plusOne;
+
+      switch (method->getSelector().getMethodFamily()) {
+      case OMF_alloc:
+      case OMF_copy:
+      case OMF_mutableCopy:
+      case OMF_new:
+        return ACC_plusOne;
+
+      default:
+        // Otherwise, treat it as +0.
+        return ACC_plusZero;
+      }
+    }
+  };
+}
+
+static bool
+KnownName(Sema &S, const char *name) {
+  LookupResult R(S, &S.Context.Idents.get(name), SourceLocation(),
+                 Sema::LookupOrdinaryName);
+  return S.LookupName(R, S.TUScope, false);
+}
+
+static void addFixitForObjCARCConversion(Sema &S,
+                                         DiagnosticBuilder &DiagB,
+                                         Sema::CheckedConversionKind CCK,
+                                         SourceLocation afterLParen,
+                                         QualType castType,
+                                         Expr *castExpr,
+                                         const char *bridgeKeyword,
+                                         const char *CFBridgeName) {
+  // We handle C-style and implicit casts here.
+  switch (CCK) {
+  case Sema::CCK_ImplicitConversion:
+  case Sema::CCK_CStyleCast:
+    break;
+  case Sema::CCK_FunctionalCast:
+  case Sema::CCK_OtherCast:
+    return;
+  }
+
+  if (CFBridgeName) {
+    Expr *castedE = castExpr;
+    if (CStyleCastExpr *CCE = dyn_cast<CStyleCastExpr>(castedE))
+      castedE = CCE->getSubExpr();
+    castedE = castedE->IgnoreImpCasts();
+    SourceRange range = castedE->getSourceRange();
+    if (isa<ParenExpr>(castedE)) {
+      DiagB.AddFixItHint(FixItHint::CreateInsertion(range.getBegin(),
+                         CFBridgeName));
+    } else {
+      std::string namePlusParen = CFBridgeName;
+      namePlusParen += "(";
+      DiagB.AddFixItHint(FixItHint::CreateInsertion(range.getBegin(),
+                                                    namePlusParen));
+      DiagB.AddFixItHint(FixItHint::CreateInsertion(
+                                       S.PP.getLocForEndOfToken(range.getEnd()),
+                                       ")"));
+    }
+    return;
+  }
+
+  if (CCK == Sema::CCK_CStyleCast) {
+    DiagB.AddFixItHint(FixItHint::CreateInsertion(afterLParen, bridgeKeyword));
+  } else {
+    std::string castCode = "(";
+    castCode += bridgeKeyword;
+    castCode += castType.getAsString();
+    castCode += ")";
+    Expr *castedE = castExpr->IgnoreImpCasts();
+    SourceRange range = castedE->getSourceRange();
+    if (isa<ParenExpr>(castedE)) {
+      DiagB.AddFixItHint(FixItHint::CreateInsertion(range.getBegin(),
+                         castCode));
+    } else {
+      castCode += "(";
+      DiagB.AddFixItHint(FixItHint::CreateInsertion(range.getBegin(),
+                                                    castCode));
+      DiagB.AddFixItHint(FixItHint::CreateInsertion(
+                                       S.PP.getLocForEndOfToken(range.getEnd()),
+                                       ")"));
+    }
+  }
+}
+
+static void
+diagnoseObjCARCConversion(Sema &S, SourceRange castRange,
+                          QualType castType, ARCConversionTypeClass castACTC,
+                          Expr *castExpr, ARCConversionTypeClass exprACTC,
+                          Sema::CheckedConversionKind CCK) {
+  SourceLocation loc =
+    (castRange.isValid() ? castRange.getBegin() : castExpr->getExprLoc());
+  
+  if (S.makeUnavailableInSystemHeader(loc,
+                "converts between Objective-C and C pointers in -fobjc-arc"))
+    return;
+
+  QualType castExprType = castExpr->getType();
+  
+  unsigned srcKind = 0;
+  switch (exprACTC) {
+  case ACTC_none:
+  case ACTC_coreFoundation:
+  case ACTC_voidPtr:
+    srcKind = (castExprType->isPointerType() ? 1 : 0);
+    break;
+  case ACTC_retainable:
+    srcKind = (castExprType->isBlockPointerType() ? 2 : 3);
+    break;
+  case ACTC_indirectRetainable:
+    srcKind = 4;
+    break;
+  }
+  
+  // Check whether this could be fixed with a bridge cast.
+  SourceLocation afterLParen = S.PP.getLocForEndOfToken(castRange.getBegin());
+  SourceLocation noteLoc = afterLParen.isValid() ? afterLParen : loc;
+
+  // Bridge from an ARC type to a CF type.
+  if (castACTC == ACTC_retainable && isAnyRetainable(exprACTC)) {
+
+    S.Diag(loc, diag::err_arc_cast_requires_bridge)
+      << unsigned(CCK == Sema::CCK_ImplicitConversion) // cast|implicit
+      << 2 // of C pointer type
+      << castExprType
+      << unsigned(castType->isBlockPointerType()) // to ObjC|block type
+      << castType
+      << castRange
+      << castExpr->getSourceRange();
+    bool br = KnownName(S, "CFBridgingRelease");
+    {
+      DiagnosticBuilder DiagB = S.Diag(noteLoc, diag::note_arc_bridge);
+      addFixitForObjCARCConversion(S, DiagB, CCK, afterLParen,
+                                   castType, castExpr, "__bridge ", 0);
+    }
+    {
+      DiagnosticBuilder DiagB = S.Diag(noteLoc, diag::note_arc_bridge_transfer)
+        << castExprType << br;
+      addFixitForObjCARCConversion(S, DiagB, CCK, afterLParen,
+                                   castType, castExpr, "__bridge_transfer ",
+                                   br ? "CFBridgingRelease" : 0);
+    }
+
+    return;
+  }
+    
+  // Bridge from a CF type to an ARC type.
+  if (exprACTC == ACTC_retainable && isAnyRetainable(castACTC)) {
+    bool br = KnownName(S, "CFBridgingRetain");
+    S.Diag(loc, diag::err_arc_cast_requires_bridge)
+      << unsigned(CCK == Sema::CCK_ImplicitConversion) // cast|implicit
+      << unsigned(castExprType->isBlockPointerType()) // of ObjC|block type
+      << castExprType
+      << 2 // to C pointer type
+      << castType
+      << castRange
+      << castExpr->getSourceRange();
+
+    {
+      DiagnosticBuilder DiagB = S.Diag(noteLoc, diag::note_arc_bridge);
+      addFixitForObjCARCConversion(S, DiagB, CCK, afterLParen,
+                                   castType, castExpr, "__bridge ", 0);
+    }
+    {
+      DiagnosticBuilder DiagB = S.Diag(noteLoc, diag::note_arc_bridge_retained)
+        << castType << br;
+      addFixitForObjCARCConversion(S, DiagB, CCK, afterLParen,
+                                   castType, castExpr, "__bridge_retained ",
+                                   br ? "CFBridgingRetain" : 0);
+    }
+
+    return;
+  }
+  
+  S.Diag(loc, diag::err_arc_mismatched_cast)
+    << (CCK != Sema::CCK_ImplicitConversion)
+    << srcKind << castExprType << castType
+    << castRange << castExpr->getSourceRange();
+}
+
+Sema::ARCConversionResult
+Sema::CheckObjCARCConversion(SourceRange castRange, QualType castType,
+                             Expr *&castExpr, CheckedConversionKind CCK) {
+  QualType castExprType = castExpr->getType();
+
+  // For the purposes of the classification, we assume reference types
+  // will bind to temporaries.
+  QualType effCastType = castType;
+  if (const ReferenceType *ref = castType->getAs<ReferenceType>())
+    effCastType = ref->getPointeeType();
+  
+  ARCConversionTypeClass exprACTC = classifyTypeForARCConversion(castExprType);
+  ARCConversionTypeClass castACTC = classifyTypeForARCConversion(effCastType);
+  if (exprACTC == castACTC) {
+    // check for viablity and report error if casting an rvalue to a
+    // life-time qualifier.
+    if ((castACTC == ACTC_retainable) &&
+        (CCK == CCK_CStyleCast || CCK == CCK_OtherCast) &&
+        (castType != castExprType)) {
+      const Type *DT = castType.getTypePtr();
+      QualType QDT = castType;
+      // We desugar some types but not others. We ignore those
+      // that cannot happen in a cast; i.e. auto, and those which
+      // should not be de-sugared; i.e typedef.
+      if (const ParenType *PT = dyn_cast<ParenType>(DT))
+        QDT = PT->desugar();
+      else if (const TypeOfType *TP = dyn_cast<TypeOfType>(DT))
+        QDT = TP->desugar();
+      else if (const AttributedType *AT = dyn_cast<AttributedType>(DT))
+        QDT = AT->desugar();
+      if (QDT != castType &&
+          QDT.getObjCLifetime() !=  Qualifiers::OCL_None) {
+        SourceLocation loc =
+          (castRange.isValid() ? castRange.getBegin() 
+                              : castExpr->getExprLoc());
+        Diag(loc, diag::err_arc_nolifetime_behavior);
+      }
+    }
+    return ACR_okay;
+  }
+  
+  if (isAnyCLike(exprACTC) && isAnyCLike(castACTC)) return ACR_okay;
+
+  // Allow all of these types to be cast to integer types (but not
+  // vice-versa).
+  if (castACTC == ACTC_none && castType->isIntegralType(Context))
+    return ACR_okay;
+  
+  // Allow casts between pointers to lifetime types (e.g., __strong id*)
+  // and pointers to void (e.g., cv void *). Casting from void* to lifetime*
+  // must be explicit.
+  if (exprACTC == ACTC_indirectRetainable && castACTC == ACTC_voidPtr)
+    return ACR_okay;
+  if (castACTC == ACTC_indirectRetainable && exprACTC == ACTC_voidPtr &&
+      CCK != CCK_ImplicitConversion)
+    return ACR_okay;
+
+  switch (ARCCastChecker(Context, exprACTC, castACTC).Visit(castExpr)) {
+  // For invalid casts, fall through.
+  case ACC_invalid:
+    break;
+
+  // Do nothing for both bottom and +0.
+  case ACC_bottom:
+  case ACC_plusZero:
+    return ACR_okay;
+
+  // If the result is +1, consume it here.
+  case ACC_plusOne:
+    castExpr = ImplicitCastExpr::Create(Context, castExpr->getType(),
+                                        CK_ARCConsumeObject, castExpr,
+                                        0, VK_RValue);
+    ExprNeedsCleanups = true;
+    return ACR_okay;
+  }
+
+  // If this is a non-implicit cast from id or block type to a
+  // CoreFoundation type, delay complaining in case the cast is used
+  // in an acceptable context.
+  if (exprACTC == ACTC_retainable && isAnyRetainable(castACTC) &&
+      CCK != CCK_ImplicitConversion)
+    return ACR_unbridged;
+
+  diagnoseObjCARCConversion(*this, castRange, castType, castACTC,
+                            castExpr, exprACTC, CCK);
+  return ACR_okay;
+}
+
+/// Given that we saw an expression with the ARCUnbridgedCastTy
+/// placeholder type, complain bitterly.
+void Sema::diagnoseARCUnbridgedCast(Expr *e) {
+  // We expect the spurious ImplicitCastExpr to already have been stripped.
+  assert(!e->hasPlaceholderType(BuiltinType::ARCUnbridgedCast));
+  CastExpr *realCast = cast<CastExpr>(e->IgnoreParens());
+
+  SourceRange castRange;
+  QualType castType;
+  CheckedConversionKind CCK;
+
+  if (CStyleCastExpr *cast = dyn_cast<CStyleCastExpr>(realCast)) {
+    castRange = SourceRange(cast->getLParenLoc(), cast->getRParenLoc());
+    castType = cast->getTypeAsWritten();
+    CCK = CCK_CStyleCast;
+  } else if (ExplicitCastExpr *cast = dyn_cast<ExplicitCastExpr>(realCast)) {
+    castRange = cast->getTypeInfoAsWritten()->getTypeLoc().getSourceRange();
+    castType = cast->getTypeAsWritten();
+    CCK = CCK_OtherCast;
+  } else {
+    castType = cast->getType();
+    CCK = CCK_ImplicitConversion;
+  }
+
+  ARCConversionTypeClass castACTC =
+    classifyTypeForARCConversion(castType.getNonReferenceType());
+
+  Expr *castExpr = realCast->getSubExpr();
+  assert(classifyTypeForARCConversion(castExpr->getType()) == ACTC_retainable);
+
+  diagnoseObjCARCConversion(*this, castRange, castType, castACTC,
+                            castExpr, ACTC_retainable, CCK);
+}
+
+/// stripARCUnbridgedCast - Given an expression of ARCUnbridgedCast
+/// type, remove the placeholder cast.
+Expr *Sema::stripARCUnbridgedCast(Expr *e) {
+  assert(e->hasPlaceholderType(BuiltinType::ARCUnbridgedCast));
+
+  if (ParenExpr *pe = dyn_cast<ParenExpr>(e)) {
+    Expr *sub = stripARCUnbridgedCast(pe->getSubExpr());
+    return new (Context) ParenExpr(pe->getLParen(), pe->getRParen(), sub);
+  } else if (UnaryOperator *uo = dyn_cast<UnaryOperator>(e)) {
+    assert(uo->getOpcode() == UO_Extension);
+    Expr *sub = stripARCUnbridgedCast(uo->getSubExpr());
+    return new (Context) UnaryOperator(sub, UO_Extension, sub->getType(),
+                                   sub->getValueKind(), sub->getObjectKind(),
+                                       uo->getOperatorLoc());
+  } else if (GenericSelectionExpr *gse = dyn_cast<GenericSelectionExpr>(e)) {
+    assert(!gse->isResultDependent());
+
+    unsigned n = gse->getNumAssocs();
+    SmallVector<Expr*, 4> subExprs(n);
+    SmallVector<TypeSourceInfo*, 4> subTypes(n);
+    for (unsigned i = 0; i != n; ++i) {
+      subTypes[i] = gse->getAssocTypeSourceInfo(i);
+      Expr *sub = gse->getAssocExpr(i);
+      if (i == gse->getResultIndex())
+        sub = stripARCUnbridgedCast(sub);
+      subExprs[i] = sub;
+    }
+
+    return new (Context) GenericSelectionExpr(Context, gse->getGenericLoc(),
+                                              gse->getControllingExpr(),
+                                              subTypes.data(), subExprs.data(),
+                                              n, gse->getDefaultLoc(),
+                                              gse->getRParenLoc(),
+                                       gse->containsUnexpandedParameterPack(),
+                                              gse->getResultIndex());
+  } else {
+    assert(isa<ImplicitCastExpr>(e) && "bad form of unbridged cast!");
+    return cast<ImplicitCastExpr>(e)->getSubExpr();
+  }
+}
+
+bool Sema::CheckObjCARCUnavailableWeakConversion(QualType castType,
+                                                 QualType exprType) {
+  QualType canCastType = 
+    Context.getCanonicalType(castType).getUnqualifiedType();
+  QualType canExprType = 
+    Context.getCanonicalType(exprType).getUnqualifiedType();
+  if (isa<ObjCObjectPointerType>(canCastType) &&
+      castType.getObjCLifetime() == Qualifiers::OCL_Weak &&
+      canExprType->isObjCObjectPointerType()) {
+    if (const ObjCObjectPointerType *ObjT =
+        canExprType->getAs<ObjCObjectPointerType>())
+      if (ObjT->getInterfaceDecl()->isArcWeakrefUnavailable())
+        return false;
+  }
+  return true;
+}
+
+/// Look for an ObjCReclaimReturnedObject cast and destroy it.
+static Expr *maybeUndoReclaimObject(Expr *e) {
+  // For now, we just undo operands that are *immediately* reclaim
+  // expressions, which prevents the vast majority of potential
+  // problems here.  To catch them all, we'd need to rebuild arbitrary
+  // value-propagating subexpressions --- we can't reliably rebuild
+  // in-place because of expression sharing.
+  if (ImplicitCastExpr *ice = dyn_cast<ImplicitCastExpr>(e))
+    if (ice->getCastKind() == CK_ARCReclaimReturnedObject)
+      return ice->getSubExpr();
+
+  return e;
+}
+
+ExprResult Sema::BuildObjCBridgedCast(SourceLocation LParenLoc,
+                                      ObjCBridgeCastKind Kind,
+                                      SourceLocation BridgeKeywordLoc,
+                                      TypeSourceInfo *TSInfo,
+                                      Expr *SubExpr) {
+  ExprResult SubResult = UsualUnaryConversions(SubExpr);
+  if (SubResult.isInvalid()) return ExprError();
+  SubExpr = SubResult.take();
+
+  QualType T = TSInfo->getType();
+  QualType FromType = SubExpr->getType();
+
+  CastKind CK;
+
+  bool MustConsume = false;
+  if (T->isDependentType() || SubExpr->isTypeDependent()) {
+    // Okay: we'll build a dependent expression type.
+    CK = CK_Dependent;
+  } else if (T->isObjCARCBridgableType() && FromType->isCARCBridgableType()) {
+    // Casting CF -> id
+    CK = (T->isBlockPointerType() ? CK_AnyPointerToBlockPointerCast
+                                  : CK_CPointerToObjCPointerCast);
+    switch (Kind) {
+    case OBC_Bridge:
+      break;
+      
+    case OBC_BridgeRetained: {
+      bool br = KnownName(*this, "CFBridgingRelease");
+      Diag(BridgeKeywordLoc, diag::err_arc_bridge_cast_wrong_kind)
+        << 2
+        << FromType
+        << (T->isBlockPointerType()? 1 : 0)
+        << T
+        << SubExpr->getSourceRange()
+        << Kind;
+      Diag(BridgeKeywordLoc, diag::note_arc_bridge)
+        << FixItHint::CreateReplacement(BridgeKeywordLoc, "__bridge");
+      Diag(BridgeKeywordLoc, diag::note_arc_bridge_transfer)
+        << FromType << br
+        << FixItHint::CreateReplacement(BridgeKeywordLoc, 
+                                        br ? "CFBridgingRelease " 
+                                           : "__bridge_transfer ");
+
+      Kind = OBC_Bridge;
+      break;
+    }
+      
+    case OBC_BridgeTransfer:
+      // We must consume the Objective-C object produced by the cast.
+      MustConsume = true;
+      break;
+    }
+  } else if (T->isCARCBridgableType() && FromType->isObjCARCBridgableType()) {
+    // Okay: id -> CF
+    CK = CK_BitCast;
+    switch (Kind) {
+    case OBC_Bridge:
+      // Reclaiming a value that's going to be __bridge-casted to CF
+      // is very dangerous, so we don't do it.
+      SubExpr = maybeUndoReclaimObject(SubExpr);
+      break;
+      
+    case OBC_BridgeRetained:        
+      // Produce the object before casting it.
+      SubExpr = ImplicitCastExpr::Create(Context, FromType,
+                                         CK_ARCProduceObject,
+                                         SubExpr, 0, VK_RValue);
+      break;
+      
+    case OBC_BridgeTransfer: {
+      bool br = KnownName(*this, "CFBridgingRetain");
+      Diag(BridgeKeywordLoc, diag::err_arc_bridge_cast_wrong_kind)
+        << (FromType->isBlockPointerType()? 1 : 0)
+        << FromType
+        << 2
+        << T
+        << SubExpr->getSourceRange()
+        << Kind;
+        
+      Diag(BridgeKeywordLoc, diag::note_arc_bridge)
+        << FixItHint::CreateReplacement(BridgeKeywordLoc, "__bridge ");
+      Diag(BridgeKeywordLoc, diag::note_arc_bridge_retained)
+        << T << br
+        << FixItHint::CreateReplacement(BridgeKeywordLoc, 
+                          br ? "CFBridgingRetain " : "__bridge_retained");
+        
+      Kind = OBC_Bridge;
+      break;
+    }
+    }
+  } else {
+    Diag(LParenLoc, diag::err_arc_bridge_cast_incompatible)
+      << FromType << T << Kind
+      << SubExpr->getSourceRange()
+      << TSInfo->getTypeLoc().getSourceRange();
+    return ExprError();
+  }
+
+  Expr *Result = new (Context) ObjCBridgedCastExpr(LParenLoc, Kind, CK,
+                                                   BridgeKeywordLoc,
+                                                   TSInfo, SubExpr);
+  
+  if (MustConsume) {
+    ExprNeedsCleanups = true;
+    Result = ImplicitCastExpr::Create(Context, T, CK_ARCConsumeObject, Result, 
+                                      0, VK_RValue);    
+  }
+  
+  return Result;
+}
+
+ExprResult Sema::ActOnObjCBridgedCast(Scope *S,
+                                      SourceLocation LParenLoc,
+                                      ObjCBridgeCastKind Kind,
+                                      SourceLocation BridgeKeywordLoc,
+                                      ParsedType Type,
+                                      SourceLocation RParenLoc,
+                                      Expr *SubExpr) {
+  TypeSourceInfo *TSInfo = 0;
+  QualType T = GetTypeFromParser(Type, &TSInfo);
+  if (!TSInfo)
+    TSInfo = Context.getTrivialTypeSourceInfo(T, LParenLoc);
+  return BuildObjCBridgedCast(LParenLoc, Kind, BridgeKeywordLoc, TSInfo, 
+                              SubExpr);
+}
diff --git a/clang/lib/Sema/SemaFixItUtils.cpp b/clang/lib/Sema/SemaFixItUtils.cpp
new file mode 100644
index 0000000..b78ea7d
--- /dev/null
+++ b/clang/lib/Sema/SemaFixItUtils.cpp
@@ -0,0 +1,204 @@
+//===--- SemaFixItUtils.cpp - Sema FixIts ---------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+//  This file defines helper classes for generation of Sema FixItHints.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/AST/ExprCXX.h"
+#include "clang/AST/ExprObjC.h"
+#include "clang/Lex/Preprocessor.h"
+#include "clang/Sema/Sema.h"
+#include "clang/Sema/SemaFixItUtils.h"
+
+using namespace clang;
+
+bool ConversionFixItGenerator::compareTypesSimple(CanQualType From,
+                                                  CanQualType To,
+                                                  Sema &S,
+                                                  SourceLocation Loc,
+                                                  ExprValueKind FromVK) {
+  if (!To.isAtLeastAsQualifiedAs(From))
+    return false;
+
+  From = From.getNonReferenceType();
+  To = To.getNonReferenceType();
+
+  // If both are pointer types, work with the pointee types.
+  if (isa<PointerType>(From) && isa<PointerType>(To)) {
+    From = S.Context.getCanonicalType(
+        (cast<PointerType>(From))->getPointeeType());
+    To = S.Context.getCanonicalType(
+        (cast<PointerType>(To))->getPointeeType());
+  }
+
+  const CanQualType FromUnq = From.getUnqualifiedType();
+  const CanQualType ToUnq = To.getUnqualifiedType();
+
+  if ((FromUnq == ToUnq || (S.IsDerivedFrom(FromUnq, ToUnq)) ) &&
+      To.isAtLeastAsQualifiedAs(From))
+    return true;
+  return false;
+}
+
+bool ConversionFixItGenerator::tryToFixConversion(const Expr *FullExpr,
+                                                  const QualType FromTy,
+                                                  const QualType ToTy,
+                                                  Sema &S) {
+  if (!FullExpr)
+    return false;
+
+  const CanQualType FromQTy = S.Context.getCanonicalType(FromTy);
+  const CanQualType ToQTy = S.Context.getCanonicalType(ToTy);
+  const SourceLocation Begin = FullExpr->getSourceRange().getBegin();
+  const SourceLocation End = S.PP.getLocForEndOfToken(FullExpr->getSourceRange()
+                                                      .getEnd());
+
+  // Strip the implicit casts - those are implied by the compiler, not the
+  // original source code.
+  const Expr* Expr = FullExpr->IgnoreImpCasts();
+
+  bool NeedParen = true;
+  if (isa<ArraySubscriptExpr>(Expr) ||
+      isa<CallExpr>(Expr) ||
+      isa<DeclRefExpr>(Expr) ||
+      isa<CastExpr>(Expr) ||
+      isa<CXXNewExpr>(Expr) ||
+      isa<CXXConstructExpr>(Expr) ||
+      isa<CXXDeleteExpr>(Expr) ||
+      isa<CXXNoexceptExpr>(Expr) ||
+      isa<CXXPseudoDestructorExpr>(Expr) ||
+      isa<CXXScalarValueInitExpr>(Expr) ||
+      isa<CXXThisExpr>(Expr) ||
+      isa<CXXTypeidExpr>(Expr) ||
+      isa<CXXUnresolvedConstructExpr>(Expr) ||
+      isa<ObjCMessageExpr>(Expr) ||
+      isa<ObjCPropertyRefExpr>(Expr) ||
+      isa<ObjCProtocolExpr>(Expr) ||
+      isa<MemberExpr>(Expr) ||
+      isa<ParenExpr>(FullExpr) ||
+      isa<ParenListExpr>(Expr) ||
+      isa<SizeOfPackExpr>(Expr) ||
+      isa<UnaryOperator>(Expr))
+    NeedParen = false;
+
+  // Check if the argument needs to be dereferenced:
+  //   (type * -> type) or (type * -> type &).
+  if (const PointerType *FromPtrTy = dyn_cast<PointerType>(FromQTy)) {
+    OverloadFixItKind FixKind = OFIK_Dereference;
+
+    bool CanConvert = CompareTypes(
+      S.Context.getCanonicalType(FromPtrTy->getPointeeType()), ToQTy,
+                                 S, Begin, VK_LValue);
+    if (CanConvert) {
+      // Do not suggest dereferencing a Null pointer.
+      if (Expr->IgnoreParenCasts()->
+          isNullPointerConstant(S.Context, Expr::NPC_ValueDependentIsNotNull))
+        return false;
+
+      if (const UnaryOperator *UO = dyn_cast<UnaryOperator>(Expr)) {
+        if (UO->getOpcode() == UO_AddrOf) {
+          FixKind = OFIK_RemoveTakeAddress;
+          Hints.push_back(FixItHint::CreateRemoval(
+                            CharSourceRange::getTokenRange(Begin, Begin)));
+        }
+      } else if (NeedParen) {
+        Hints.push_back(FixItHint::CreateInsertion(Begin, "*("));
+        Hints.push_back(FixItHint::CreateInsertion(End, ")"));
+      } else {
+        Hints.push_back(FixItHint::CreateInsertion(Begin, "*"));
+      }
+
+      NumConversionsFixed++;
+      if (NumConversionsFixed == 1)
+        Kind = FixKind;
+      return true;
+    }
+  }
+
+  // Check if the pointer to the argument needs to be passed:
+  //   (type -> type *) or (type & -> type *).
+  if (isa<PointerType>(ToQTy)) {
+    bool CanConvert = false;
+    OverloadFixItKind FixKind = OFIK_TakeAddress;
+
+    // Only suggest taking address of L-values.
+    if (!Expr->isLValue() || Expr->getObjectKind() != OK_Ordinary)
+      return false;
+
+    CanConvert = CompareTypes(S.Context.getPointerType(FromQTy), ToQTy,
+                              S, Begin, VK_RValue);
+    if (CanConvert) {
+
+      if (const UnaryOperator *UO = dyn_cast<UnaryOperator>(Expr)) {
+        if (UO->getOpcode() == UO_Deref) {
+          FixKind = OFIK_RemoveDereference;
+          Hints.push_back(FixItHint::CreateRemoval(
+                            CharSourceRange::getTokenRange(Begin, Begin)));
+        }
+      } else if (NeedParen) {
+        Hints.push_back(FixItHint::CreateInsertion(Begin, "&("));
+        Hints.push_back(FixItHint::CreateInsertion(End, ")"));
+      } else {
+        Hints.push_back(FixItHint::CreateInsertion(Begin, "&"));
+      }
+
+      NumConversionsFixed++;
+      if (NumConversionsFixed == 1)
+        Kind = FixKind;
+      return true;
+    }
+  }
+
+  return false;
+}
+
+static bool isMacroDefined(const Sema &S, StringRef Name) {
+  return S.PP.getMacroInfo(&S.getASTContext().Idents.get(Name));
+}
+
+const char *Sema::getFixItZeroInitializerForType(QualType T) const {
+  if (T->isScalarType()) {
+    // Suggest " = 0" for non-enumeration scalar types, unless we can find a
+    // better initializer.
+    if (T->isEnumeralType())
+      return 0;
+    if ((T->isObjCObjectPointerType() || T->isBlockPointerType()) &&
+        isMacroDefined(*this, "nil"))
+      return " = nil";
+    if (T->isRealFloatingType())
+      return " = 0.0";
+    if (T->isBooleanType() && LangOpts.CPlusPlus)
+      return " = false";
+    if (T->isPointerType() || T->isMemberPointerType()) {
+      if (LangOpts.CPlusPlus0x)
+        return " = nullptr";
+      else if (isMacroDefined(*this, "NULL"))
+        return " = NULL";
+    }
+    if (T->isCharType())
+      return " = '\\0'";
+    if (T->isWideCharType())
+      return " = L'\\0'";
+    if (T->isChar16Type())
+      return " = u'\\0'";
+    if (T->isChar32Type())
+      return " = U'\\0'";
+    return " = 0";
+  }
+
+  const CXXRecordDecl *RD = T->getAsCXXRecordDecl();
+  if (!RD || !RD->hasDefinition())
+    return 0;
+  if (LangOpts.CPlusPlus0x && !RD->hasUserProvidedDefaultConstructor())
+    return "{}";
+  if (RD->isAggregate())
+    return " = {}";
+  return 0;
+}
diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp
new file mode 100644
index 0000000..a65b41f
--- /dev/null
+++ b/clang/lib/Sema/SemaInit.cpp
@@ -0,0 +1,6167 @@
+//===--- SemaInit.cpp - Semantic Analysis for Initializers ----------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements semantic analysis for initializers.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Sema/Designator.h"
+#include "clang/Sema/Initialization.h"
+#include "clang/Sema/Lookup.h"
+#include "clang/Sema/SemaInternal.h"
+#include "clang/Lex/Preprocessor.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/AST/ExprCXX.h"
+#include "clang/AST/ExprObjC.h"
+#include "clang/AST/TypeLoc.h"
+#include "llvm/ADT/APInt.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/raw_ostream.h"
+#include <map>
+using namespace clang;
+
+//===----------------------------------------------------------------------===//
+// Sema Initialization Checking
+//===----------------------------------------------------------------------===//
+
+static Expr *IsStringInit(Expr *Init, const ArrayType *AT,
+                          ASTContext &Context) {
+  if (!isa<ConstantArrayType>(AT) && !isa<IncompleteArrayType>(AT))
+    return 0;
+
+  // See if this is a string literal or @encode.
+  Init = Init->IgnoreParens();
+
+  // Handle @encode, which is a narrow string.
+  if (isa<ObjCEncodeExpr>(Init) && AT->getElementType()->isCharType())
+    return Init;
+
+  // Otherwise we can only handle string literals.
+  StringLiteral *SL = dyn_cast<StringLiteral>(Init);
+  if (SL == 0) return 0;
+
+  QualType ElemTy = Context.getCanonicalType(AT->getElementType());
+
+  switch (SL->getKind()) {
+  case StringLiteral::Ascii:
+  case StringLiteral::UTF8:
+    // char array can be initialized with a narrow string.
+    // Only allow char x[] = "foo";  not char x[] = L"foo";
+    return ElemTy->isCharType() ? Init : 0;
+  case StringLiteral::UTF16:
+    return ElemTy->isChar16Type() ? Init : 0;
+  case StringLiteral::UTF32:
+    return ElemTy->isChar32Type() ? Init : 0;
+  case StringLiteral::Wide:
+    // wchar_t array can be initialized with a wide string: C99 6.7.8p15 (with
+    // correction from DR343): "An array with element type compatible with a
+    // qualified or unqualified version of wchar_t may be initialized by a wide
+    // string literal, optionally enclosed in braces."
+    if (Context.typesAreCompatible(Context.getWCharType(),
+                                   ElemTy.getUnqualifiedType()))
+      return Init;
+
+    return 0;
+  }
+
+  llvm_unreachable("missed a StringLiteral kind?");
+}
+
+static Expr *IsStringInit(Expr *init, QualType declType, ASTContext &Context) {
+  const ArrayType *arrayType = Context.getAsArrayType(declType);
+  if (!arrayType) return 0;
+
+  return IsStringInit(init, arrayType, Context);
+}
+
+static void CheckStringInit(Expr *Str, QualType &DeclT, const ArrayType *AT,
+                            Sema &S) {
+  // Get the length of the string as parsed.
+  uint64_t StrLength =
+    cast<ConstantArrayType>(Str->getType())->getSize().getZExtValue();
+
+
+  if (const IncompleteArrayType *IAT = dyn_cast<IncompleteArrayType>(AT)) {
+    // C99 6.7.8p14. We have an array of character type with unknown size
+    // being initialized to a string literal.
+    llvm::APSInt ConstVal(32);
+    ConstVal = StrLength;
+    // Return a new array type (C99 6.7.8p22).
+    DeclT = S.Context.getConstantArrayType(IAT->getElementType(),
+                                           ConstVal,
+                                           ArrayType::Normal, 0);
+    return;
+  }
+
+  const ConstantArrayType *CAT = cast<ConstantArrayType>(AT);
+
+  // We have an array of character type with known size.  However,
+  // the size may be smaller or larger than the string we are initializing.
+  // FIXME: Avoid truncation for 64-bit length strings.
+  if (S.getLangOpts().CPlusPlus) {
+    if (StringLiteral *SL = dyn_cast<StringLiteral>(Str)) {
+      // For Pascal strings it's OK to strip off the terminating null character,
+      // so the example below is valid:
+      //
+      // unsigned char a[2] = "\pa";
+      if (SL->isPascal())
+        StrLength--;
+    }
+  
+    // [dcl.init.string]p2
+    if (StrLength > CAT->getSize().getZExtValue())
+      S.Diag(Str->getLocStart(),
+             diag::err_initializer_string_for_char_array_too_long)
+        << Str->getSourceRange();
+  } else {
+    // C99 6.7.8p14.
+    if (StrLength-1 > CAT->getSize().getZExtValue())
+      S.Diag(Str->getLocStart(),
+             diag::warn_initializer_string_for_char_array_too_long)
+        << Str->getSourceRange();
+  }
+
+  // Set the type to the actual size that we are initializing.  If we have
+  // something like:
+  //   char x[1] = "foo";
+  // then this will set the string literal's type to char[1].
+  Str->setType(DeclT);
+}
+
+//===----------------------------------------------------------------------===//
+// Semantic checking for initializer lists.
+//===----------------------------------------------------------------------===//
+
+/// @brief Semantic checking for initializer lists.
+///
+/// The InitListChecker class contains a set of routines that each
+/// handle the initialization of a certain kind of entity, e.g.,
+/// arrays, vectors, struct/union types, scalars, etc. The
+/// InitListChecker itself performs a recursive walk of the subobject
+/// structure of the type to be initialized, while stepping through
+/// the initializer list one element at a time. The IList and Index
+/// parameters to each of the Check* routines contain the active
+/// (syntactic) initializer list and the index into that initializer
+/// list that represents the current initializer. Each routine is
+/// responsible for moving that Index forward as it consumes elements.
+///
+/// Each Check* routine also has a StructuredList/StructuredIndex
+/// arguments, which contains the current "structured" (semantic)
+/// initializer list and the index into that initializer list where we
+/// are copying initializers as we map them over to the semantic
+/// list. Once we have completed our recursive walk of the subobject
+/// structure, we will have constructed a full semantic initializer
+/// list.
+///
+/// C99 designators cause changes in the initializer list traversal,
+/// because they make the initialization "jump" into a specific
+/// subobject and then continue the initialization from that
+/// point. CheckDesignatedInitializer() recursively steps into the
+/// designated subobject and manages backing out the recursion to
+/// initialize the subobjects after the one designated.
+namespace {
+class InitListChecker {
+  Sema &SemaRef;
+  bool hadError;
+  bool VerifyOnly; // no diagnostics, no structure building
+  bool AllowBraceElision;
+  llvm::DenseMap<InitListExpr *, InitListExpr *> SyntacticToSemantic;
+  InitListExpr *FullyStructuredList;
+
+  void CheckImplicitInitList(const InitializedEntity &Entity,
+                             InitListExpr *ParentIList, QualType T,
+                             unsigned &Index, InitListExpr *StructuredList,
+                             unsigned &StructuredIndex);
+  void CheckExplicitInitList(const InitializedEntity &Entity,
+                             InitListExpr *IList, QualType &T,
+                             unsigned &Index, InitListExpr *StructuredList,
+                             unsigned &StructuredIndex,
+                             bool TopLevelObject = false);
+  void CheckListElementTypes(const InitializedEntity &Entity,
+                             InitListExpr *IList, QualType &DeclType,
+                             bool SubobjectIsDesignatorContext,
+                             unsigned &Index,
+                             InitListExpr *StructuredList,
+                             unsigned &StructuredIndex,
+                             bool TopLevelObject = false);
+  void CheckSubElementType(const InitializedEntity &Entity,
+                           InitListExpr *IList, QualType ElemType,
+                           unsigned &Index,
+                           InitListExpr *StructuredList,
+                           unsigned &StructuredIndex);
+  void CheckComplexType(const InitializedEntity &Entity,
+                        InitListExpr *IList, QualType DeclType,
+                        unsigned &Index,
+                        InitListExpr *StructuredList,
+                        unsigned &StructuredIndex);
+  void CheckScalarType(const InitializedEntity &Entity,
+                       InitListExpr *IList, QualType DeclType,
+                       unsigned &Index,
+                       InitListExpr *StructuredList,
+                       unsigned &StructuredIndex);
+  void CheckReferenceType(const InitializedEntity &Entity,
+                          InitListExpr *IList, QualType DeclType,
+                          unsigned &Index,
+                          InitListExpr *StructuredList,
+                          unsigned &StructuredIndex);
+  void CheckVectorType(const InitializedEntity &Entity,
+                       InitListExpr *IList, QualType DeclType, unsigned &Index,
+                       InitListExpr *StructuredList,
+                       unsigned &StructuredIndex);
+  void CheckStructUnionTypes(const InitializedEntity &Entity,
+                             InitListExpr *IList, QualType DeclType,
+                             RecordDecl::field_iterator Field,
+                             bool SubobjectIsDesignatorContext, unsigned &Index,
+                             InitListExpr *StructuredList,
+                             unsigned &StructuredIndex,
+                             bool TopLevelObject = false);
+  void CheckArrayType(const InitializedEntity &Entity,
+                      InitListExpr *IList, QualType &DeclType,
+                      llvm::APSInt elementIndex,
+                      bool SubobjectIsDesignatorContext, unsigned &Index,
+                      InitListExpr *StructuredList,
+                      unsigned &StructuredIndex);
+  bool CheckDesignatedInitializer(const InitializedEntity &Entity,
+                                  InitListExpr *IList, DesignatedInitExpr *DIE,
+                                  unsigned DesigIdx,
+                                  QualType &CurrentObjectType,
+                                  RecordDecl::field_iterator *NextField,
+                                  llvm::APSInt *NextElementIndex,
+                                  unsigned &Index,
+                                  InitListExpr *StructuredList,
+                                  unsigned &StructuredIndex,
+                                  bool FinishSubobjectInit,
+                                  bool TopLevelObject);
+  InitListExpr *getStructuredSubobjectInit(InitListExpr *IList, unsigned Index,
+                                           QualType CurrentObjectType,
+                                           InitListExpr *StructuredList,
+                                           unsigned StructuredIndex,
+                                           SourceRange InitRange);
+  void UpdateStructuredListElement(InitListExpr *StructuredList,
+                                   unsigned &StructuredIndex,
+                                   Expr *expr);
+  int numArrayElements(QualType DeclType);
+  int numStructUnionElements(QualType DeclType);
+
+  void FillInValueInitForField(unsigned Init, FieldDecl *Field,
+                               const InitializedEntity &ParentEntity,
+                               InitListExpr *ILE, bool &RequiresSecondPass);
+  void FillInValueInitializations(const InitializedEntity &Entity,
+                                  InitListExpr *ILE, bool &RequiresSecondPass);
+  bool CheckFlexibleArrayInit(const InitializedEntity &Entity,
+                              Expr *InitExpr, FieldDecl *Field,
+                              bool TopLevelObject);
+  void CheckValueInitializable(const InitializedEntity &Entity);
+
+public:
+  InitListChecker(Sema &S, const InitializedEntity &Entity,
+                  InitListExpr *IL, QualType &T, bool VerifyOnly,
+                  bool AllowBraceElision);
+  bool HadError() { return hadError; }
+
+  // @brief Retrieves the fully-structured initializer list used for
+  // semantic analysis and code generation.
+  InitListExpr *getFullyStructuredList() const { return FullyStructuredList; }
+};
+} // end anonymous namespace
+
+void InitListChecker::CheckValueInitializable(const InitializedEntity &Entity) {
+  assert(VerifyOnly &&
+         "CheckValueInitializable is only inteded for verification mode.");
+
+  SourceLocation Loc;
+  InitializationKind Kind = InitializationKind::CreateValue(Loc, Loc, Loc,
+                                                            true);
+  InitializationSequence InitSeq(SemaRef, Entity, Kind, 0, 0);
+  if (InitSeq.Failed())
+    hadError = true;
+}
+
+void InitListChecker::FillInValueInitForField(unsigned Init, FieldDecl *Field,
+                                        const InitializedEntity &ParentEntity,
+                                              InitListExpr *ILE,
+                                              bool &RequiresSecondPass) {
+  SourceLocation Loc = ILE->getLocStart();
+  unsigned NumInits = ILE->getNumInits();
+  InitializedEntity MemberEntity
+    = InitializedEntity::InitializeMember(Field, &ParentEntity);
+  if (Init >= NumInits || !ILE->getInit(Init)) {
+    // FIXME: We probably don't need to handle references
+    // specially here, since value-initialization of references is
+    // handled in InitializationSequence.
+    if (Field->getType()->isReferenceType()) {
+      // C++ [dcl.init.aggr]p9:
+      //   If an incomplete or empty initializer-list leaves a
+      //   member of reference type uninitialized, the program is
+      //   ill-formed.
+      SemaRef.Diag(Loc, diag::err_init_reference_member_uninitialized)
+        << Field->getType()
+        << ILE->getSyntacticForm()->getSourceRange();
+      SemaRef.Diag(Field->getLocation(),
+                   diag::note_uninit_reference_member);
+      hadError = true;
+      return;
+    }
+
+    InitializationKind Kind = InitializationKind::CreateValue(Loc, Loc, Loc,
+                                                              true);
+    InitializationSequence InitSeq(SemaRef, MemberEntity, Kind, 0, 0);
+    if (!InitSeq) {
+      InitSeq.Diagnose(SemaRef, MemberEntity, Kind, 0, 0);
+      hadError = true;
+      return;
+    }
+
+    ExprResult MemberInit
+      = InitSeq.Perform(SemaRef, MemberEntity, Kind, MultiExprArg());
+    if (MemberInit.isInvalid()) {
+      hadError = true;
+      return;
+    }
+
+    if (hadError) {
+      // Do nothing
+    } else if (Init < NumInits) {
+      ILE->setInit(Init, MemberInit.takeAs<Expr>());
+    } else if (InitSeq.isConstructorInitialization()) {
+      // Value-initialization requires a constructor call, so
+      // extend the initializer list to include the constructor
+      // call and make a note that we'll need to take another pass
+      // through the initializer list.
+      ILE->updateInit(SemaRef.Context, Init, MemberInit.takeAs<Expr>());
+      RequiresSecondPass = true;
+    }
+  } else if (InitListExpr *InnerILE
+               = dyn_cast<InitListExpr>(ILE->getInit(Init)))
+    FillInValueInitializations(MemberEntity, InnerILE,
+                               RequiresSecondPass);
+}
+
+/// Recursively replaces NULL values within the given initializer list
+/// with expressions that perform value-initialization of the
+/// appropriate type.
+void
+InitListChecker::FillInValueInitializations(const InitializedEntity &Entity,
+                                            InitListExpr *ILE,
+                                            bool &RequiresSecondPass) {
+  assert((ILE->getType() != SemaRef.Context.VoidTy) &&
+         "Should not have void type");
+  SourceLocation Loc = ILE->getLocStart();
+  if (ILE->getSyntacticForm())
+    Loc = ILE->getSyntacticForm()->getLocStart();
+
+  if (const RecordType *RType = ILE->getType()->getAs<RecordType>()) {
+    if (RType->getDecl()->isUnion() &&
+        ILE->getInitializedFieldInUnion())
+      FillInValueInitForField(0, ILE->getInitializedFieldInUnion(),
+                              Entity, ILE, RequiresSecondPass);
+    else {
+      unsigned Init = 0;
+      for (RecordDecl::field_iterator
+             Field = RType->getDecl()->field_begin(),
+             FieldEnd = RType->getDecl()->field_end();
+           Field != FieldEnd; ++Field) {
+        if (Field->isUnnamedBitfield())
+          continue;
+
+        if (hadError)
+          return;
+
+        FillInValueInitForField(Init, *Field, Entity, ILE, RequiresSecondPass);
+        if (hadError)
+          return;
+
+        ++Init;
+
+        // Only look at the first initialization of a union.
+        if (RType->getDecl()->isUnion())
+          break;
+      }
+    }
+
+    return;
+  }
+
+  QualType ElementType;
+
+  InitializedEntity ElementEntity = Entity;
+  unsigned NumInits = ILE->getNumInits();
+  unsigned NumElements = NumInits;
+  if (const ArrayType *AType = SemaRef.Context.getAsArrayType(ILE->getType())) {
+    ElementType = AType->getElementType();
+    if (const ConstantArrayType *CAType = dyn_cast<ConstantArrayType>(AType))
+      NumElements = CAType->getSize().getZExtValue();
+    ElementEntity = InitializedEntity::InitializeElement(SemaRef.Context,
+                                                         0, Entity);
+  } else if (const VectorType *VType = ILE->getType()->getAs<VectorType>()) {
+    ElementType = VType->getElementType();
+    NumElements = VType->getNumElements();
+    ElementEntity = InitializedEntity::InitializeElement(SemaRef.Context,
+                                                         0, Entity);
+  } else
+    ElementType = ILE->getType();
+
+
+  for (unsigned Init = 0; Init != NumElements; ++Init) {
+    if (hadError)
+      return;
+
+    if (ElementEntity.getKind() == InitializedEntity::EK_ArrayElement ||
+        ElementEntity.getKind() == InitializedEntity::EK_VectorElement)
+      ElementEntity.setElementIndex(Init);
+
+    Expr *InitExpr = (Init < NumInits ? ILE->getInit(Init) : 0);
+    if (!InitExpr && !ILE->hasArrayFiller()) {
+      InitializationKind Kind = InitializationKind::CreateValue(Loc, Loc, Loc,
+                                                                true);
+      InitializationSequence InitSeq(SemaRef, ElementEntity, Kind, 0, 0);
+      if (!InitSeq) {
+        InitSeq.Diagnose(SemaRef, ElementEntity, Kind, 0, 0);
+        hadError = true;
+        return;
+      }
+
+      ExprResult ElementInit
+        = InitSeq.Perform(SemaRef, ElementEntity, Kind, MultiExprArg());
+      if (ElementInit.isInvalid()) {
+        hadError = true;
+        return;
+      }
+
+      if (hadError) {
+        // Do nothing
+      } else if (Init < NumInits) {
+        // For arrays, just set the expression used for value-initialization
+        // of the "holes" in the array.
+        if (ElementEntity.getKind() == InitializedEntity::EK_ArrayElement)
+          ILE->setArrayFiller(ElementInit.takeAs<Expr>());
+        else
+          ILE->setInit(Init, ElementInit.takeAs<Expr>());
+      } else {
+        // For arrays, just set the expression used for value-initialization
+        // of the rest of elements and exit.
+        if (ElementEntity.getKind() == InitializedEntity::EK_ArrayElement) {
+          ILE->setArrayFiller(ElementInit.takeAs<Expr>());
+          return;
+        }
+
+        if (InitSeq.isConstructorInitialization()) {
+          // Value-initialization requires a constructor call, so
+          // extend the initializer list to include the constructor
+          // call and make a note that we'll need to take another pass
+          // through the initializer list.
+          ILE->updateInit(SemaRef.Context, Init, ElementInit.takeAs<Expr>());
+          RequiresSecondPass = true;
+        }
+      }
+    } else if (InitListExpr *InnerILE
+                 = dyn_cast_or_null<InitListExpr>(InitExpr))
+      FillInValueInitializations(ElementEntity, InnerILE, RequiresSecondPass);
+  }
+}
+
+
+InitListChecker::InitListChecker(Sema &S, const InitializedEntity &Entity,
+                                 InitListExpr *IL, QualType &T,
+                                 bool VerifyOnly, bool AllowBraceElision)
+  : SemaRef(S), VerifyOnly(VerifyOnly), AllowBraceElision(AllowBraceElision) {
+  hadError = false;
+
+  unsigned newIndex = 0;
+  unsigned newStructuredIndex = 0;
+  FullyStructuredList
+    = getStructuredSubobjectInit(IL, newIndex, T, 0, 0, IL->getSourceRange());
+  CheckExplicitInitList(Entity, IL, T, newIndex,
+                        FullyStructuredList, newStructuredIndex,
+                        /*TopLevelObject=*/true);
+
+  if (!hadError && !VerifyOnly) {
+    bool RequiresSecondPass = false;
+    FillInValueInitializations(Entity, FullyStructuredList, RequiresSecondPass);
+    if (RequiresSecondPass && !hadError)
+      FillInValueInitializations(Entity, FullyStructuredList,
+                                 RequiresSecondPass);
+  }
+}
+
+int InitListChecker::numArrayElements(QualType DeclType) {
+  // FIXME: use a proper constant
+  int maxElements = 0x7FFFFFFF;
+  if (const ConstantArrayType *CAT =
+        SemaRef.Context.getAsConstantArrayType(DeclType)) {
+    maxElements = static_cast<int>(CAT->getSize().getZExtValue());
+  }
+  return maxElements;
+}
+
+int InitListChecker::numStructUnionElements(QualType DeclType) {
+  RecordDecl *structDecl = DeclType->getAs<RecordType>()->getDecl();
+  int InitializableMembers = 0;
+  for (RecordDecl::field_iterator
+         Field = structDecl->field_begin(),
+         FieldEnd = structDecl->field_end();
+       Field != FieldEnd; ++Field) {
+    if (!Field->isUnnamedBitfield())
+      ++InitializableMembers;
+  }
+  if (structDecl->isUnion())
+    return std::min(InitializableMembers, 1);
+  return InitializableMembers - structDecl->hasFlexibleArrayMember();
+}
+
+void InitListChecker::CheckImplicitInitList(const InitializedEntity &Entity,
+                                            InitListExpr *ParentIList,
+                                            QualType T, unsigned &Index,
+                                            InitListExpr *StructuredList,
+                                            unsigned &StructuredIndex) {
+  int maxElements = 0;
+
+  if (T->isArrayType())
+    maxElements = numArrayElements(T);
+  else if (T->isRecordType())
+    maxElements = numStructUnionElements(T);
+  else if (T->isVectorType())
+    maxElements = T->getAs<VectorType>()->getNumElements();
+  else
+    llvm_unreachable("CheckImplicitInitList(): Illegal type");
+
+  if (maxElements == 0) {
+    if (!VerifyOnly)
+      SemaRef.Diag(ParentIList->getInit(Index)->getLocStart(),
+                   diag::err_implicit_empty_initializer);
+    ++Index;
+    hadError = true;
+    return;
+  }
+
+  // Build a structured initializer list corresponding to this subobject.
+  InitListExpr *StructuredSubobjectInitList
+    = getStructuredSubobjectInit(ParentIList, Index, T, StructuredList,
+                                 StructuredIndex,
+          SourceRange(ParentIList->getInit(Index)->getLocStart(),
+                      ParentIList->getSourceRange().getEnd()));
+  unsigned StructuredSubobjectInitIndex = 0;
+
+  // Check the element types and build the structural subobject.
+  unsigned StartIndex = Index;
+  CheckListElementTypes(Entity, ParentIList, T,
+                        /*SubobjectIsDesignatorContext=*/false, Index,
+                        StructuredSubobjectInitList,
+                        StructuredSubobjectInitIndex);
+
+  if (VerifyOnly) {
+    if (!AllowBraceElision && (T->isArrayType() || T->isRecordType()))
+      hadError = true;
+  } else {
+    StructuredSubobjectInitList->setType(T);
+
+    unsigned EndIndex = (Index == StartIndex? StartIndex : Index - 1);
+    // Update the structured sub-object initializer so that it's ending
+    // range corresponds with the end of the last initializer it used.
+    if (EndIndex < ParentIList->getNumInits()) {
+      SourceLocation EndLoc
+        = ParentIList->getInit(EndIndex)->getSourceRange().getEnd();
+      StructuredSubobjectInitList->setRBraceLoc(EndLoc);
+    }
+
+    // Complain about missing braces.
+    if (T->isArrayType() || T->isRecordType()) {
+      SemaRef.Diag(StructuredSubobjectInitList->getLocStart(),
+                    AllowBraceElision ? diag::warn_missing_braces :
+                                        diag::err_missing_braces)
+        << StructuredSubobjectInitList->getSourceRange()
+        << FixItHint::CreateInsertion(
+              StructuredSubobjectInitList->getLocStart(), "{")
+        << FixItHint::CreateInsertion(
+              SemaRef.PP.getLocForEndOfToken(
+                                      StructuredSubobjectInitList->getLocEnd()),
+              "}");
+      if (!AllowBraceElision)
+        hadError = true;
+    }
+  }
+}
+
+void InitListChecker::CheckExplicitInitList(const InitializedEntity &Entity,
+                                            InitListExpr *IList, QualType &T,
+                                            unsigned &Index,
+                                            InitListExpr *StructuredList,
+                                            unsigned &StructuredIndex,
+                                            bool TopLevelObject) {
+  assert(IList->isExplicit() && "Illegal Implicit InitListExpr");
+  if (!VerifyOnly) {
+    SyntacticToSemantic[IList] = StructuredList;
+    StructuredList->setSyntacticForm(IList);
+  }
+  CheckListElementTypes(Entity, IList, T, /*SubobjectIsDesignatorContext=*/true,
+                        Index, StructuredList, StructuredIndex, TopLevelObject);
+  if (!VerifyOnly) {
+    QualType ExprTy = T;
+    if (!ExprTy->isArrayType())
+      ExprTy = ExprTy.getNonLValueExprType(SemaRef.Context);
+    IList->setType(ExprTy);
+    StructuredList->setType(ExprTy);
+  }
+  if (hadError)
+    return;
+
+  if (Index < IList->getNumInits()) {
+    // We have leftover initializers
+    if (VerifyOnly) {
+      if (SemaRef.getLangOpts().CPlusPlus ||
+          (SemaRef.getLangOpts().OpenCL &&
+           IList->getType()->isVectorType())) {
+        hadError = true;
+      }
+      return;
+    }
+
+    if (StructuredIndex == 1 &&
+        IsStringInit(StructuredList->getInit(0), T, SemaRef.Context)) {
+      unsigned DK = diag::warn_excess_initializers_in_char_array_initializer;
+      if (SemaRef.getLangOpts().CPlusPlus) {
+        DK = diag::err_excess_initializers_in_char_array_initializer;
+        hadError = true;
+      }
+      // Special-case
+      SemaRef.Diag(IList->getInit(Index)->getLocStart(), DK)
+        << IList->getInit(Index)->getSourceRange();
+    } else if (!T->isIncompleteType()) {
+      // Don't complain for incomplete types, since we'll get an error
+      // elsewhere
+      QualType CurrentObjectType = StructuredList->getType();
+      int initKind =
+        CurrentObjectType->isArrayType()? 0 :
+        CurrentObjectType->isVectorType()? 1 :
+        CurrentObjectType->isScalarType()? 2 :
+        CurrentObjectType->isUnionType()? 3 :
+        4;
+
+      unsigned DK = diag::warn_excess_initializers;
+      if (SemaRef.getLangOpts().CPlusPlus) {
+        DK = diag::err_excess_initializers;
+        hadError = true;
+      }
+      if (SemaRef.getLangOpts().OpenCL && initKind == 1) {
+        DK = diag::err_excess_initializers;
+        hadError = true;
+      }
+
+      SemaRef.Diag(IList->getInit(Index)->getLocStart(), DK)
+        << initKind << IList->getInit(Index)->getSourceRange();
+    }
+  }
+
+  if (!VerifyOnly && T->isScalarType() && IList->getNumInits() == 1 &&
+      !TopLevelObject)
+    SemaRef.Diag(IList->getLocStart(), diag::warn_braces_around_scalar_init)
+      << IList->getSourceRange()
+      << FixItHint::CreateRemoval(IList->getLocStart())
+      << FixItHint::CreateRemoval(IList->getLocEnd());
+}
+
+void InitListChecker::CheckListElementTypes(const InitializedEntity &Entity,
+                                            InitListExpr *IList,
+                                            QualType &DeclType,
+                                            bool SubobjectIsDesignatorContext,
+                                            unsigned &Index,
+                                            InitListExpr *StructuredList,
+                                            unsigned &StructuredIndex,
+                                            bool TopLevelObject) {
+  if (DeclType->isAnyComplexType() && SubobjectIsDesignatorContext) {
+    // Explicitly braced initializer for complex type can be real+imaginary
+    // parts.
+    CheckComplexType(Entity, IList, DeclType, Index,
+                     StructuredList, StructuredIndex);
+  } else if (DeclType->isScalarType()) {
+    CheckScalarType(Entity, IList, DeclType, Index,
+                    StructuredList, StructuredIndex);
+  } else if (DeclType->isVectorType()) {
+    CheckVectorType(Entity, IList, DeclType, Index,
+                    StructuredList, StructuredIndex);
+  } else if (DeclType->isAggregateType()) {
+    if (DeclType->isRecordType()) {
+      RecordDecl *RD = DeclType->getAs<RecordType>()->getDecl();
+      CheckStructUnionTypes(Entity, IList, DeclType, RD->field_begin(),
+                            SubobjectIsDesignatorContext, Index,
+                            StructuredList, StructuredIndex,
+                            TopLevelObject);
+    } else if (DeclType->isArrayType()) {
+      llvm::APSInt Zero(
+                      SemaRef.Context.getTypeSize(SemaRef.Context.getSizeType()),
+                      false);
+      CheckArrayType(Entity, IList, DeclType, Zero,
+                     SubobjectIsDesignatorContext, Index,
+                     StructuredList, StructuredIndex);
+    } else
+      llvm_unreachable("Aggregate that isn't a structure or array?!");
+  } else if (DeclType->isVoidType() || DeclType->isFunctionType()) {
+    // This type is invalid, issue a diagnostic.
+    ++Index;
+    if (!VerifyOnly)
+      SemaRef.Diag(IList->getLocStart(), diag::err_illegal_initializer_type)
+        << DeclType;
+    hadError = true;
+  } else if (DeclType->isRecordType()) {
+    // C++ [dcl.init]p14:
+    //   [...] If the class is an aggregate (8.5.1), and the initializer
+    //   is a brace-enclosed list, see 8.5.1.
+    //
+    // Note: 8.5.1 is handled below; here, we diagnose the case where
+    // we have an initializer list and a destination type that is not
+    // an aggregate.
+    // FIXME: In C++0x, this is yet another form of initialization.
+    if (!VerifyOnly)
+      SemaRef.Diag(IList->getLocStart(), diag::err_init_non_aggr_init_list)
+        << DeclType << IList->getSourceRange();
+    hadError = true;
+  } else if (DeclType->isReferenceType()) {
+    CheckReferenceType(Entity, IList, DeclType, Index,
+                       StructuredList, StructuredIndex);
+  } else if (DeclType->isObjCObjectType()) {
+    if (!VerifyOnly)
+      SemaRef.Diag(IList->getLocStart(), diag::err_init_objc_class)
+        << DeclType;
+    hadError = true;
+  } else {
+    if (!VerifyOnly)
+      SemaRef.Diag(IList->getLocStart(), diag::err_illegal_initializer_type)
+        << DeclType;
+    hadError = true;
+  }
+}
+
+void InitListChecker::CheckSubElementType(const InitializedEntity &Entity,
+                                          InitListExpr *IList,
+                                          QualType ElemType,
+                                          unsigned &Index,
+                                          InitListExpr *StructuredList,
+                                          unsigned &StructuredIndex) {
+  Expr *expr = IList->getInit(Index);
+  if (InitListExpr *SubInitList = dyn_cast<InitListExpr>(expr)) {
+    unsigned newIndex = 0;
+    unsigned newStructuredIndex = 0;
+    InitListExpr *newStructuredList
+      = getStructuredSubobjectInit(IList, Index, ElemType,
+                                   StructuredList, StructuredIndex,
+                                   SubInitList->getSourceRange());
+    CheckExplicitInitList(Entity, SubInitList, ElemType, newIndex,
+                          newStructuredList, newStructuredIndex);
+    ++StructuredIndex;
+    ++Index;
+    return;
+  } else if (ElemType->isScalarType()) {
+    return CheckScalarType(Entity, IList, ElemType, Index,
+                           StructuredList, StructuredIndex);
+  } else if (ElemType->isReferenceType()) {
+    return CheckReferenceType(Entity, IList, ElemType, Index,
+                              StructuredList, StructuredIndex);
+  }
+
+  if (const ArrayType *arrayType = SemaRef.Context.getAsArrayType(ElemType)) {
+    // arrayType can be incomplete if we're initializing a flexible
+    // array member.  There's nothing we can do with the completed
+    // type here, though.
+
+    if (Expr *Str = IsStringInit(expr, arrayType, SemaRef.Context)) {
+      if (!VerifyOnly) {
+        CheckStringInit(Str, ElemType, arrayType, SemaRef);
+        UpdateStructuredListElement(StructuredList, StructuredIndex, Str);
+      }
+      ++Index;
+      return;
+    }
+
+    // Fall through for subaggregate initialization.
+
+  } else if (SemaRef.getLangOpts().CPlusPlus) {
+    // C++ [dcl.init.aggr]p12:
+    //   All implicit type conversions (clause 4) are considered when
+    //   initializing the aggregate member with an initializer from
+    //   an initializer-list. If the initializer can initialize a
+    //   member, the member is initialized. [...]
+
+    // FIXME: Better EqualLoc?
+    InitializationKind Kind =
+      InitializationKind::CreateCopy(expr->getLocStart(), SourceLocation());
+    InitializationSequence Seq(SemaRef, Entity, Kind, &expr, 1);
+
+    if (Seq) {
+      if (!VerifyOnly) {
+        ExprResult Result =
+          Seq.Perform(SemaRef, Entity, Kind, MultiExprArg(&expr, 1));
+        if (Result.isInvalid())
+          hadError = true;
+
+        UpdateStructuredListElement(StructuredList, StructuredIndex,
+                                    Result.takeAs<Expr>());
+      }
+      ++Index;
+      return;
+    }
+
+    // Fall through for subaggregate initialization
+  } else {
+    // C99 6.7.8p13:
+    //
+    //   The initializer for a structure or union object that has
+    //   automatic storage duration shall be either an initializer
+    //   list as described below, or a single expression that has
+    //   compatible structure or union type. In the latter case, the
+    //   initial value of the object, including unnamed members, is
+    //   that of the expression.
+    ExprResult ExprRes = SemaRef.Owned(expr);
+    if ((ElemType->isRecordType() || ElemType->isVectorType()) &&
+        SemaRef.CheckSingleAssignmentConstraints(ElemType, ExprRes,
+                                                 !VerifyOnly)
+          == Sema::Compatible) {
+      if (ExprRes.isInvalid())
+        hadError = true;
+      else {
+        ExprRes = SemaRef.DefaultFunctionArrayLvalueConversion(ExprRes.take());
+	      if (ExprRes.isInvalid())
+	        hadError = true;
+      }
+      UpdateStructuredListElement(StructuredList, StructuredIndex,
+                                  ExprRes.takeAs<Expr>());
+      ++Index;
+      return;
+    }
+    ExprRes.release();
+    // Fall through for subaggregate initialization
+  }
+
+  // C++ [dcl.init.aggr]p12:
+  //
+  //   [...] Otherwise, if the member is itself a non-empty
+  //   subaggregate, brace elision is assumed and the initializer is
+  //   considered for the initialization of the first member of
+  //   the subaggregate.
+  if (!SemaRef.getLangOpts().OpenCL && 
+      (ElemType->isAggregateType() || ElemType->isVectorType())) {
+    CheckImplicitInitList(Entity, IList, ElemType, Index, StructuredList,
+                          StructuredIndex);
+    ++StructuredIndex;
+  } else {
+    if (!VerifyOnly) {
+      // We cannot initialize this element, so let
+      // PerformCopyInitialization produce the appropriate diagnostic.
+      SemaRef.PerformCopyInitialization(Entity, SourceLocation(),
+                                        SemaRef.Owned(expr),
+                                        /*TopLevelOfInitList=*/true);
+    }
+    hadError = true;
+    ++Index;
+    ++StructuredIndex;
+  }
+}
+
+void InitListChecker::CheckComplexType(const InitializedEntity &Entity,
+                                       InitListExpr *IList, QualType DeclType,
+                                       unsigned &Index,
+                                       InitListExpr *StructuredList,
+                                       unsigned &StructuredIndex) {
+  assert(Index == 0 && "Index in explicit init list must be zero");
+
+  // As an extension, clang supports complex initializers, which initialize
+  // a complex number component-wise.  When an explicit initializer list for
+  // a complex number contains two two initializers, this extension kicks in:
+  // it exepcts the initializer list to contain two elements convertible to
+  // the element type of the complex type. The first element initializes
+  // the real part, and the second element intitializes the imaginary part.
+
+  if (IList->getNumInits() != 2)
+    return CheckScalarType(Entity, IList, DeclType, Index, StructuredList,
+                           StructuredIndex);
+
+  // This is an extension in C.  (The builtin _Complex type does not exist
+  // in the C++ standard.)
+  if (!SemaRef.getLangOpts().CPlusPlus && !VerifyOnly)
+    SemaRef.Diag(IList->getLocStart(), diag::ext_complex_component_init)
+      << IList->getSourceRange();
+
+  // Initialize the complex number.
+  QualType elementType = DeclType->getAs<ComplexType>()->getElementType();
+  InitializedEntity ElementEntity =
+    InitializedEntity::InitializeElement(SemaRef.Context, 0, Entity);
+
+  for (unsigned i = 0; i < 2; ++i) {
+    ElementEntity.setElementIndex(Index);
+    CheckSubElementType(ElementEntity, IList, elementType, Index,
+                        StructuredList, StructuredIndex);
+  }
+}
+
+
+void InitListChecker::CheckScalarType(const InitializedEntity &Entity,
+                                      InitListExpr *IList, QualType DeclType,
+                                      unsigned &Index,
+                                      InitListExpr *StructuredList,
+                                      unsigned &StructuredIndex) {
+  if (Index >= IList->getNumInits()) {
+    if (!VerifyOnly)
+      SemaRef.Diag(IList->getLocStart(),
+                   SemaRef.getLangOpts().CPlusPlus0x ?
+                     diag::warn_cxx98_compat_empty_scalar_initializer :
+                     diag::err_empty_scalar_initializer)
+        << IList->getSourceRange();
+    hadError = !SemaRef.getLangOpts().CPlusPlus0x;
+    ++Index;
+    ++StructuredIndex;
+    return;
+  }
+
+  Expr *expr = IList->getInit(Index);
+  if (InitListExpr *SubIList = dyn_cast<InitListExpr>(expr)) {
+    if (!VerifyOnly)
+      SemaRef.Diag(SubIList->getLocStart(),
+                   diag::warn_many_braces_around_scalar_init)
+        << SubIList->getSourceRange();
+
+    CheckScalarType(Entity, SubIList, DeclType, Index, StructuredList,
+                    StructuredIndex);
+    return;
+  } else if (isa<DesignatedInitExpr>(expr)) {
+    if (!VerifyOnly)
+      SemaRef.Diag(expr->getLocStart(),
+                   diag::err_designator_for_scalar_init)
+        << DeclType << expr->getSourceRange();
+    hadError = true;
+    ++Index;
+    ++StructuredIndex;
+    return;
+  }
+
+  if (VerifyOnly) {
+    if (!SemaRef.CanPerformCopyInitialization(Entity, SemaRef.Owned(expr)))
+      hadError = true;
+    ++Index;
+    return;
+  }
+
+  ExprResult Result =
+    SemaRef.PerformCopyInitialization(Entity, expr->getLocStart(),
+                                      SemaRef.Owned(expr),
+                                      /*TopLevelOfInitList=*/true);
+
+  Expr *ResultExpr = 0;
+
+  if (Result.isInvalid())
+    hadError = true; // types weren't compatible.
+  else {
+    ResultExpr = Result.takeAs<Expr>();
+
+    if (ResultExpr != expr) {
+      // The type was promoted, update initializer list.
+      IList->setInit(Index, ResultExpr);
+    }
+  }
+  if (hadError)
+    ++StructuredIndex;
+  else
+    UpdateStructuredListElement(StructuredList, StructuredIndex, ResultExpr);
+  ++Index;
+}
+
+void InitListChecker::CheckReferenceType(const InitializedEntity &Entity,
+                                         InitListExpr *IList, QualType DeclType,
+                                         unsigned &Index,
+                                         InitListExpr *StructuredList,
+                                         unsigned &StructuredIndex) {
+  if (Index >= IList->getNumInits()) {
+    // FIXME: It would be wonderful if we could point at the actual member. In
+    // general, it would be useful to pass location information down the stack,
+    // so that we know the location (or decl) of the "current object" being
+    // initialized.
+    if (!VerifyOnly)
+      SemaRef.Diag(IList->getLocStart(),
+                    diag::err_init_reference_member_uninitialized)
+        << DeclType
+        << IList->getSourceRange();
+    hadError = true;
+    ++Index;
+    ++StructuredIndex;
+    return;
+  }
+
+  Expr *expr = IList->getInit(Index);
+  if (isa<InitListExpr>(expr) && !SemaRef.getLangOpts().CPlusPlus0x) {
+    if (!VerifyOnly)
+      SemaRef.Diag(IList->getLocStart(), diag::err_init_non_aggr_init_list)
+        << DeclType << IList->getSourceRange();
+    hadError = true;
+    ++Index;
+    ++StructuredIndex;
+    return;
+  }
+
+  if (VerifyOnly) {
+    if (!SemaRef.CanPerformCopyInitialization(Entity, SemaRef.Owned(expr)))
+      hadError = true;
+    ++Index;
+    return;
+  }
+
+  ExprResult Result =
+    SemaRef.PerformCopyInitialization(Entity, expr->getLocStart(),
+                                      SemaRef.Owned(expr),
+                                      /*TopLevelOfInitList=*/true);
+
+  if (Result.isInvalid())
+    hadError = true;
+
+  expr = Result.takeAs<Expr>();
+  IList->setInit(Index, expr);
+
+  if (hadError)
+    ++StructuredIndex;
+  else
+    UpdateStructuredListElement(StructuredList, StructuredIndex, expr);
+  ++Index;
+}
+
+void InitListChecker::CheckVectorType(const InitializedEntity &Entity,
+                                      InitListExpr *IList, QualType DeclType,
+                                      unsigned &Index,
+                                      InitListExpr *StructuredList,
+                                      unsigned &StructuredIndex) {
+  const VectorType *VT = DeclType->getAs<VectorType>();
+  unsigned maxElements = VT->getNumElements();
+  unsigned numEltsInit = 0;
+  QualType elementType = VT->getElementType();
+
+  if (Index >= IList->getNumInits()) {
+    // Make sure the element type can be value-initialized.
+    if (VerifyOnly)
+      CheckValueInitializable(
+          InitializedEntity::InitializeElement(SemaRef.Context, 0, Entity));
+    return;
+  }
+
+  if (!SemaRef.getLangOpts().OpenCL) {
+    // If the initializing element is a vector, try to copy-initialize
+    // instead of breaking it apart (which is doomed to failure anyway).
+    Expr *Init = IList->getInit(Index);
+    if (!isa<InitListExpr>(Init) && Init->getType()->isVectorType()) {
+      if (VerifyOnly) {
+        if (!SemaRef.CanPerformCopyInitialization(Entity, SemaRef.Owned(Init)))
+          hadError = true;
+        ++Index;
+        return;
+      }
+
+      ExprResult Result =
+        SemaRef.PerformCopyInitialization(Entity, Init->getLocStart(),
+                                          SemaRef.Owned(Init),
+                                          /*TopLevelOfInitList=*/true);
+
+      Expr *ResultExpr = 0;
+      if (Result.isInvalid())
+        hadError = true; // types weren't compatible.
+      else {
+        ResultExpr = Result.takeAs<Expr>();
+
+        if (ResultExpr != Init) {
+          // The type was promoted, update initializer list.
+          IList->setInit(Index, ResultExpr);
+        }
+      }
+      if (hadError)
+        ++StructuredIndex;
+      else
+        UpdateStructuredListElement(StructuredList, StructuredIndex,
+                                    ResultExpr);
+      ++Index;
+      return;
+    }
+
+    InitializedEntity ElementEntity =
+      InitializedEntity::InitializeElement(SemaRef.Context, 0, Entity);
+
+    for (unsigned i = 0; i < maxElements; ++i, ++numEltsInit) {
+      // Don't attempt to go past the end of the init list
+      if (Index >= IList->getNumInits()) {
+        if (VerifyOnly)
+          CheckValueInitializable(ElementEntity);
+        break;
+      }
+
+      ElementEntity.setElementIndex(Index);
+      CheckSubElementType(ElementEntity, IList, elementType, Index,
+                          StructuredList, StructuredIndex);
+    }
+    return;
+  }
+
+  InitializedEntity ElementEntity =
+    InitializedEntity::InitializeElement(SemaRef.Context, 0, Entity);
+
+  // OpenCL initializers allows vectors to be constructed from vectors.
+  for (unsigned i = 0; i < maxElements; ++i) {
+    // Don't attempt to go past the end of the init list
+    if (Index >= IList->getNumInits())
+      break;
+
+    ElementEntity.setElementIndex(Index);
+
+    QualType IType = IList->getInit(Index)->getType();
+    if (!IType->isVectorType()) {
+      CheckSubElementType(ElementEntity, IList, elementType, Index,
+                          StructuredList, StructuredIndex);
+      ++numEltsInit;
+    } else {
+      QualType VecType;
+      const VectorType *IVT = IType->getAs<VectorType>();
+      unsigned numIElts = IVT->getNumElements();
+
+      if (IType->isExtVectorType())
+        VecType = SemaRef.Context.getExtVectorType(elementType, numIElts);
+      else
+        VecType = SemaRef.Context.getVectorType(elementType, numIElts,
+                                                IVT->getVectorKind());
+      CheckSubElementType(ElementEntity, IList, VecType, Index,
+                          StructuredList, StructuredIndex);
+      numEltsInit += numIElts;
+    }
+  }
+
+  // OpenCL requires all elements to be initialized.
+  if (numEltsInit != maxElements) {
+    if (!VerifyOnly)
+      SemaRef.Diag(IList->getLocStart(),
+                   diag::err_vector_incorrect_num_initializers)
+        << (numEltsInit < maxElements) << maxElements << numEltsInit;
+    hadError = true;
+  }
+}
+
+void InitListChecker::CheckArrayType(const InitializedEntity &Entity,
+                                     InitListExpr *IList, QualType &DeclType,
+                                     llvm::APSInt elementIndex,
+                                     bool SubobjectIsDesignatorContext,
+                                     unsigned &Index,
+                                     InitListExpr *StructuredList,
+                                     unsigned &StructuredIndex) {
+  const ArrayType *arrayType = SemaRef.Context.getAsArrayType(DeclType);
+
+  // Check for the special-case of initializing an array with a string.
+  if (Index < IList->getNumInits()) {
+    if (Expr *Str = IsStringInit(IList->getInit(Index), arrayType,
+                                 SemaRef.Context)) {
+      // We place the string literal directly into the resulting
+      // initializer list. This is the only place where the structure
+      // of the structured initializer list doesn't match exactly,
+      // because doing so would involve allocating one character
+      // constant for each string.
+      if (!VerifyOnly) {
+        CheckStringInit(Str, DeclType, arrayType, SemaRef);
+        UpdateStructuredListElement(StructuredList, StructuredIndex, Str);
+        StructuredList->resizeInits(SemaRef.Context, StructuredIndex);
+      }
+      ++Index;
+      return;
+    }
+  }
+  if (const VariableArrayType *VAT = dyn_cast<VariableArrayType>(arrayType)) {
+    // Check for VLAs; in standard C it would be possible to check this
+    // earlier, but I don't know where clang accepts VLAs (gcc accepts
+    // them in all sorts of strange places).
+    if (!VerifyOnly)
+      SemaRef.Diag(VAT->getSizeExpr()->getLocStart(),
+                    diag::err_variable_object_no_init)
+        << VAT->getSizeExpr()->getSourceRange();
+    hadError = true;
+    ++Index;
+    ++StructuredIndex;
+    return;
+  }
+
+  // We might know the maximum number of elements in advance.
+  llvm::APSInt maxElements(elementIndex.getBitWidth(),
+                           elementIndex.isUnsigned());
+  bool maxElementsKnown = false;
+  if (const ConstantArrayType *CAT = dyn_cast<ConstantArrayType>(arrayType)) {
+    maxElements = CAT->getSize();
+    elementIndex = elementIndex.extOrTrunc(maxElements.getBitWidth());
+    elementIndex.setIsUnsigned(maxElements.isUnsigned());
+    maxElementsKnown = true;
+  }
+
+  QualType elementType = arrayType->getElementType();
+  while (Index < IList->getNumInits()) {
+    Expr *Init = IList->getInit(Index);
+    if (DesignatedInitExpr *DIE = dyn_cast<DesignatedInitExpr>(Init)) {
+      // If we're not the subobject that matches up with the '{' for
+      // the designator, we shouldn't be handling the
+      // designator. Return immediately.
+      if (!SubobjectIsDesignatorContext)
+        return;
+
+      // Handle this designated initializer. elementIndex will be
+      // updated to be the next array element we'll initialize.
+      if (CheckDesignatedInitializer(Entity, IList, DIE, 0,
+                                     DeclType, 0, &elementIndex, Index,
+                                     StructuredList, StructuredIndex, true,
+                                     false)) {
+        hadError = true;
+        continue;
+      }
+
+      if (elementIndex.getBitWidth() > maxElements.getBitWidth())
+        maxElements = maxElements.extend(elementIndex.getBitWidth());
+      else if (elementIndex.getBitWidth() < maxElements.getBitWidth())
+        elementIndex = elementIndex.extend(maxElements.getBitWidth());
+      elementIndex.setIsUnsigned(maxElements.isUnsigned());
+
+      // If the array is of incomplete type, keep track of the number of
+      // elements in the initializer.
+      if (!maxElementsKnown && elementIndex > maxElements)
+        maxElements = elementIndex;
+
+      continue;
+    }
+
+    // If we know the maximum number of elements, and we've already
+    // hit it, stop consuming elements in the initializer list.
+    if (maxElementsKnown && elementIndex == maxElements)
+      break;
+
+    InitializedEntity ElementEntity =
+      InitializedEntity::InitializeElement(SemaRef.Context, StructuredIndex,
+                                           Entity);
+    // Check this element.
+    CheckSubElementType(ElementEntity, IList, elementType, Index,
+                        StructuredList, StructuredIndex);
+    ++elementIndex;
+
+    // If the array is of incomplete type, keep track of the number of
+    // elements in the initializer.
+    if (!maxElementsKnown && elementIndex > maxElements)
+      maxElements = elementIndex;
+  }
+  if (!hadError && DeclType->isIncompleteArrayType() && !VerifyOnly) {
+    // If this is an incomplete array type, the actual type needs to
+    // be calculated here.
+    llvm::APSInt Zero(maxElements.getBitWidth(), maxElements.isUnsigned());
+    if (maxElements == Zero) {
+      // Sizing an array implicitly to zero is not allowed by ISO C,
+      // but is supported by GNU.
+      SemaRef.Diag(IList->getLocStart(),
+                    diag::ext_typecheck_zero_array_size);
+    }
+
+    DeclType = SemaRef.Context.getConstantArrayType(elementType, maxElements,
+                                                     ArrayType::Normal, 0);
+  }
+  if (!hadError && VerifyOnly) {
+    // Check if there are any members of the array that get value-initialized.
+    // If so, check if doing that is possible.
+    // FIXME: This needs to detect holes left by designated initializers too.
+    if (maxElementsKnown && elementIndex < maxElements)
+      CheckValueInitializable(InitializedEntity::InitializeElement(
+                                                  SemaRef.Context, 0, Entity));
+  }
+}
+
+bool InitListChecker::CheckFlexibleArrayInit(const InitializedEntity &Entity,
+                                             Expr *InitExpr,
+                                             FieldDecl *Field,
+                                             bool TopLevelObject) {
+  // Handle GNU flexible array initializers.
+  unsigned FlexArrayDiag;
+  if (isa<InitListExpr>(InitExpr) &&
+      cast<InitListExpr>(InitExpr)->getNumInits() == 0) {
+    // Empty flexible array init always allowed as an extension
+    FlexArrayDiag = diag::ext_flexible_array_init;
+  } else if (SemaRef.getLangOpts().CPlusPlus) {
+    // Disallow flexible array init in C++; it is not required for gcc
+    // compatibility, and it needs work to IRGen correctly in general.
+    FlexArrayDiag = diag::err_flexible_array_init;
+  } else if (!TopLevelObject) {
+    // Disallow flexible array init on non-top-level object
+    FlexArrayDiag = diag::err_flexible_array_init;
+  } else if (Entity.getKind() != InitializedEntity::EK_Variable) {
+    // Disallow flexible array init on anything which is not a variable.
+    FlexArrayDiag = diag::err_flexible_array_init;
+  } else if (cast<VarDecl>(Entity.getDecl())->hasLocalStorage()) {
+    // Disallow flexible array init on local variables.
+    FlexArrayDiag = diag::err_flexible_array_init;
+  } else {
+    // Allow other cases.
+    FlexArrayDiag = diag::ext_flexible_array_init;
+  }
+
+  if (!VerifyOnly) {
+    SemaRef.Diag(InitExpr->getLocStart(),
+                 FlexArrayDiag)
+      << InitExpr->getLocStart();
+    SemaRef.Diag(Field->getLocation(), diag::note_flexible_array_member)
+      << Field;
+  }
+
+  return FlexArrayDiag != diag::ext_flexible_array_init;
+}
+
+void InitListChecker::CheckStructUnionTypes(const InitializedEntity &Entity,
+                                            InitListExpr *IList,
+                                            QualType DeclType,
+                                            RecordDecl::field_iterator Field,
+                                            bool SubobjectIsDesignatorContext,
+                                            unsigned &Index,
+                                            InitListExpr *StructuredList,
+                                            unsigned &StructuredIndex,
+                                            bool TopLevelObject) {
+  RecordDecl* structDecl = DeclType->getAs<RecordType>()->getDecl();
+
+  // If the record is invalid, some of it's members are invalid. To avoid
+  // confusion, we forgo checking the intializer for the entire record.
+  if (structDecl->isInvalidDecl()) {
+    hadError = true;
+    return;
+  }
+
+  if (DeclType->isUnionType() && IList->getNumInits() == 0) {
+    // Value-initialize the first named member of the union.
+    RecordDecl *RD = DeclType->getAs<RecordType>()->getDecl();
+    for (RecordDecl::field_iterator FieldEnd = RD->field_end();
+         Field != FieldEnd; ++Field) {
+      if (Field->getDeclName()) {
+        if (VerifyOnly)
+          CheckValueInitializable(
+              InitializedEntity::InitializeMember(*Field, &Entity));
+        else
+          StructuredList->setInitializedFieldInUnion(*Field);
+        break;
+      }
+    }
+    return;
+  }
+
+  // If structDecl is a forward declaration, this loop won't do
+  // anything except look at designated initializers; That's okay,
+  // because an error should get printed out elsewhere. It might be
+  // worthwhile to skip over the rest of the initializer, though.
+  RecordDecl *RD = DeclType->getAs<RecordType>()->getDecl();
+  RecordDecl::field_iterator FieldEnd = RD->field_end();
+  bool InitializedSomething = false;
+  bool CheckForMissingFields = true;
+  while (Index < IList->getNumInits()) {
+    Expr *Init = IList->getInit(Index);
+
+    if (DesignatedInitExpr *DIE = dyn_cast<DesignatedInitExpr>(Init)) {
+      // If we're not the subobject that matches up with the '{' for
+      // the designator, we shouldn't be handling the
+      // designator. Return immediately.
+      if (!SubobjectIsDesignatorContext)
+        return;
+
+      // Handle this designated initializer. Field will be updated to
+      // the next field that we'll be initializing.
+      if (CheckDesignatedInitializer(Entity, IList, DIE, 0,
+                                     DeclType, &Field, 0, Index,
+                                     StructuredList, StructuredIndex,
+                                     true, TopLevelObject))
+        hadError = true;
+
+      InitializedSomething = true;
+
+      // Disable check for missing fields when designators are used.
+      // This matches gcc behaviour.
+      CheckForMissingFields = false;
+      continue;
+    }
+
+    if (Field == FieldEnd) {
+      // We've run out of fields. We're done.
+      break;
+    }
+
+    // We've already initialized a member of a union. We're done.
+    if (InitializedSomething && DeclType->isUnionType())
+      break;
+
+    // If we've hit the flexible array member at the end, we're done.
+    if (Field->getType()->isIncompleteArrayType())
+      break;
+
+    if (Field->isUnnamedBitfield()) {
+      // Don't initialize unnamed bitfields, e.g. "int : 20;"
+      ++Field;
+      continue;
+    }
+
+    // Make sure we can use this declaration.
+    bool InvalidUse;
+    if (VerifyOnly)
+      InvalidUse = !SemaRef.CanUseDecl(*Field);
+    else
+      InvalidUse = SemaRef.DiagnoseUseOfDecl(*Field,
+                                          IList->getInit(Index)->getLocStart());
+    if (InvalidUse) {
+      ++Index;
+      ++Field;
+      hadError = true;
+      continue;
+    }
+
+    InitializedEntity MemberEntity =
+      InitializedEntity::InitializeMember(*Field, &Entity);
+    CheckSubElementType(MemberEntity, IList, Field->getType(), Index,
+                        StructuredList, StructuredIndex);
+    InitializedSomething = true;
+
+    if (DeclType->isUnionType() && !VerifyOnly) {
+      // Initialize the first field within the union.
+      StructuredList->setInitializedFieldInUnion(*Field);
+    }
+
+    ++Field;
+  }
+
+  // Emit warnings for missing struct field initializers.
+  if (!VerifyOnly && InitializedSomething && CheckForMissingFields &&
+      Field != FieldEnd && !Field->getType()->isIncompleteArrayType() &&
+      !DeclType->isUnionType()) {
+    // It is possible we have one or more unnamed bitfields remaining.
+    // Find first (if any) named field and emit warning.
+    for (RecordDecl::field_iterator it = Field, end = RD->field_end();
+         it != end; ++it) {
+      if (!it->isUnnamedBitfield()) {
+        SemaRef.Diag(IList->getSourceRange().getEnd(),
+                     diag::warn_missing_field_initializers) << it->getName();
+        break;
+      }
+    }
+  }
+
+  // Check that any remaining fields can be value-initialized.
+  if (VerifyOnly && Field != FieldEnd && !DeclType->isUnionType() &&
+      !Field->getType()->isIncompleteArrayType()) {
+    // FIXME: Should check for holes left by designated initializers too.
+    for (; Field != FieldEnd && !hadError; ++Field) {
+      if (!Field->isUnnamedBitfield())
+        CheckValueInitializable(
+            InitializedEntity::InitializeMember(*Field, &Entity));
+    }
+  }
+
+  if (Field == FieldEnd || !Field->getType()->isIncompleteArrayType() ||
+      Index >= IList->getNumInits())
+    return;
+
+  if (CheckFlexibleArrayInit(Entity, IList->getInit(Index), *Field,
+                             TopLevelObject)) {
+    hadError = true;
+    ++Index;
+    return;
+  }
+
+  InitializedEntity MemberEntity =
+    InitializedEntity::InitializeMember(*Field, &Entity);
+
+  if (isa<InitListExpr>(IList->getInit(Index)))
+    CheckSubElementType(MemberEntity, IList, Field->getType(), Index,
+                        StructuredList, StructuredIndex);
+  else
+    CheckImplicitInitList(MemberEntity, IList, Field->getType(), Index,
+                          StructuredList, StructuredIndex);
+}
+
+/// \brief Expand a field designator that refers to a member of an
+/// anonymous struct or union into a series of field designators that
+/// refers to the field within the appropriate subobject.
+///
+static void ExpandAnonymousFieldDesignator(Sema &SemaRef,
+                                           DesignatedInitExpr *DIE,
+                                           unsigned DesigIdx,
+                                           IndirectFieldDecl *IndirectField) {
+  typedef DesignatedInitExpr::Designator Designator;
+
+  // Build the replacement designators.
+  SmallVector<Designator, 4> Replacements;
+  for (IndirectFieldDecl::chain_iterator PI = IndirectField->chain_begin(),
+       PE = IndirectField->chain_end(); PI != PE; ++PI) {
+    if (PI + 1 == PE)
+      Replacements.push_back(Designator((IdentifierInfo *)0,
+                                    DIE->getDesignator(DesigIdx)->getDotLoc(),
+                                DIE->getDesignator(DesigIdx)->getFieldLoc()));
+    else
+      Replacements.push_back(Designator((IdentifierInfo *)0, SourceLocation(),
+                                        SourceLocation()));
+    assert(isa<FieldDecl>(*PI));
+    Replacements.back().setField(cast<FieldDecl>(*PI));
+  }
+
+  // Expand the current designator into the set of replacement
+  // designators, so we have a full subobject path down to where the
+  // member of the anonymous struct/union is actually stored.
+  DIE->ExpandDesignator(SemaRef.Context, DesigIdx, &Replacements[0],
+                        &Replacements[0] + Replacements.size());
+}
+
+/// \brief Given an implicit anonymous field, search the IndirectField that
+///  corresponds to FieldName.
+static IndirectFieldDecl *FindIndirectFieldDesignator(FieldDecl *AnonField,
+                                                 IdentifierInfo *FieldName) {
+  assert(AnonField->isAnonymousStructOrUnion());
+  Decl *NextDecl = AnonField->getNextDeclInContext();
+  while (IndirectFieldDecl *IF = 
+          dyn_cast_or_null<IndirectFieldDecl>(NextDecl)) {
+    if (FieldName && FieldName == IF->getAnonField()->getIdentifier())
+      return IF;
+    NextDecl = NextDecl->getNextDeclInContext();
+  }
+  return 0;
+}
+
+static DesignatedInitExpr *CloneDesignatedInitExpr(Sema &SemaRef,
+                                                   DesignatedInitExpr *DIE) {
+  unsigned NumIndexExprs = DIE->getNumSubExprs() - 1;
+  SmallVector<Expr*, 4> IndexExprs(NumIndexExprs);
+  for (unsigned I = 0; I < NumIndexExprs; ++I)
+    IndexExprs[I] = DIE->getSubExpr(I + 1);
+  return DesignatedInitExpr::Create(SemaRef.Context, DIE->designators_begin(),
+                                    DIE->size(), IndexExprs.data(),
+                                    NumIndexExprs, DIE->getEqualOrColonLoc(),
+                                    DIE->usesGNUSyntax(), DIE->getInit());
+}
+
+namespace {
+
+// Callback to only accept typo corrections that are for field members of
+// the given struct or union.
+class FieldInitializerValidatorCCC : public CorrectionCandidateCallback {
+ public:
+  explicit FieldInitializerValidatorCCC(RecordDecl *RD)
+      : Record(RD) {}
+
+  virtual bool ValidateCandidate(const TypoCorrection &candidate) {
+    FieldDecl *FD = candidate.getCorrectionDeclAs<FieldDecl>();
+    return FD && FD->getDeclContext()->getRedeclContext()->Equals(Record);
+  }
+
+ private:
+  RecordDecl *Record;
+};
+
+}
+
+/// @brief Check the well-formedness of a C99 designated initializer.
+///
+/// Determines whether the designated initializer @p DIE, which
+/// resides at the given @p Index within the initializer list @p
+/// IList, is well-formed for a current object of type @p DeclType
+/// (C99 6.7.8). The actual subobject that this designator refers to
+/// within the current subobject is returned in either
+/// @p NextField or @p NextElementIndex (whichever is appropriate).
+///
+/// @param IList  The initializer list in which this designated
+/// initializer occurs.
+///
+/// @param DIE The designated initializer expression.
+///
+/// @param DesigIdx  The index of the current designator.
+///
+/// @param DeclType  The type of the "current object" (C99 6.7.8p17),
+/// into which the designation in @p DIE should refer.
+///
+/// @param NextField  If non-NULL and the first designator in @p DIE is
+/// a field, this will be set to the field declaration corresponding
+/// to the field named by the designator.
+///
+/// @param NextElementIndex  If non-NULL and the first designator in @p
+/// DIE is an array designator or GNU array-range designator, this
+/// will be set to the last index initialized by this designator.
+///
+/// @param Index  Index into @p IList where the designated initializer
+/// @p DIE occurs.
+///
+/// @param StructuredList  The initializer list expression that
+/// describes all of the subobject initializers in the order they'll
+/// actually be initialized.
+///
+/// @returns true if there was an error, false otherwise.
+bool
+InitListChecker::CheckDesignatedInitializer(const InitializedEntity &Entity,
+                                            InitListExpr *IList,
+                                            DesignatedInitExpr *DIE,
+                                            unsigned DesigIdx,
+                                            QualType &CurrentObjectType,
+                                          RecordDecl::field_iterator *NextField,
+                                            llvm::APSInt *NextElementIndex,
+                                            unsigned &Index,
+                                            InitListExpr *StructuredList,
+                                            unsigned &StructuredIndex,
+                                            bool FinishSubobjectInit,
+                                            bool TopLevelObject) {
+  if (DesigIdx == DIE->size()) {
+    // Check the actual initialization for the designated object type.
+    bool prevHadError = hadError;
+
+    // Temporarily remove the designator expression from the
+    // initializer list that the child calls see, so that we don't try
+    // to re-process the designator.
+    unsigned OldIndex = Index;
+    IList->setInit(OldIndex, DIE->getInit());
+
+    CheckSubElementType(Entity, IList, CurrentObjectType, Index,
+                        StructuredList, StructuredIndex);
+
+    // Restore the designated initializer expression in the syntactic
+    // form of the initializer list.
+    if (IList->getInit(OldIndex) != DIE->getInit())
+      DIE->setInit(IList->getInit(OldIndex));
+    IList->setInit(OldIndex, DIE);
+
+    return hadError && !prevHadError;
+  }
+
+  DesignatedInitExpr::Designator *D = DIE->getDesignator(DesigIdx);
+  bool IsFirstDesignator = (DesigIdx == 0);
+  if (!VerifyOnly) {
+    assert((IsFirstDesignator || StructuredList) &&
+           "Need a non-designated initializer list to start from");
+
+    // Determine the structural initializer list that corresponds to the
+    // current subobject.
+    StructuredList = IsFirstDesignator? SyntacticToSemantic.lookup(IList)
+      : getStructuredSubobjectInit(IList, Index, CurrentObjectType,
+                                   StructuredList, StructuredIndex,
+                                   SourceRange(D->getStartLocation(),
+                                               DIE->getSourceRange().getEnd()));
+    assert(StructuredList && "Expected a structured initializer list");
+  }
+
+  if (D->isFieldDesignator()) {
+    // C99 6.7.8p7:
+    //
+    //   If a designator has the form
+    //
+    //      . identifier
+    //
+    //   then the current object (defined below) shall have
+    //   structure or union type and the identifier shall be the
+    //   name of a member of that type.
+    const RecordType *RT = CurrentObjectType->getAs<RecordType>();
+    if (!RT) {
+      SourceLocation Loc = D->getDotLoc();
+      if (Loc.isInvalid())
+        Loc = D->getFieldLoc();
+      if (!VerifyOnly)
+        SemaRef.Diag(Loc, diag::err_field_designator_non_aggr)
+          << SemaRef.getLangOpts().CPlusPlus << CurrentObjectType;
+      ++Index;
+      return true;
+    }
+
+    // Note: we perform a linear search of the fields here, despite
+    // the fact that we have a faster lookup method, because we always
+    // need to compute the field's index.
+    FieldDecl *KnownField = D->getField();
+    IdentifierInfo *FieldName = D->getFieldName();
+    unsigned FieldIndex = 0;
+    RecordDecl::field_iterator
+      Field = RT->getDecl()->field_begin(),
+      FieldEnd = RT->getDecl()->field_end();
+    for (; Field != FieldEnd; ++Field) {
+      if (Field->isUnnamedBitfield())
+        continue;
+
+      // If we find a field representing an anonymous field, look in the
+      // IndirectFieldDecl that follow for the designated initializer.
+      if (!KnownField && Field->isAnonymousStructOrUnion()) {
+        if (IndirectFieldDecl *IF =
+            FindIndirectFieldDesignator(*Field, FieldName)) {
+          // In verify mode, don't modify the original.
+          if (VerifyOnly)
+            DIE = CloneDesignatedInitExpr(SemaRef, DIE);
+          ExpandAnonymousFieldDesignator(SemaRef, DIE, DesigIdx, IF);
+          D = DIE->getDesignator(DesigIdx);
+          break;
+        }
+      }
+      if (KnownField && KnownField == *Field)
+        break;
+      if (FieldName && FieldName == Field->getIdentifier())
+        break;
+
+      ++FieldIndex;
+    }
+
+    if (Field == FieldEnd) {
+      if (VerifyOnly) {
+        ++Index;
+        return true; // No typo correction when just trying this out.
+      }
+
+      // There was no normal field in the struct with the designated
+      // name. Perform another lookup for this name, which may find
+      // something that we can't designate (e.g., a member function),
+      // may find nothing, or may find a member of an anonymous
+      // struct/union.
+      DeclContext::lookup_result Lookup = RT->getDecl()->lookup(FieldName);
+      FieldDecl *ReplacementField = 0;
+      if (Lookup.first == Lookup.second) {
+        // Name lookup didn't find anything. Determine whether this
+        // was a typo for another field name.
+        FieldInitializerValidatorCCC Validator(RT->getDecl());
+        TypoCorrection Corrected = SemaRef.CorrectTypo(
+            DeclarationNameInfo(FieldName, D->getFieldLoc()),
+            Sema::LookupMemberName, /*Scope=*/0, /*SS=*/0, Validator,
+            RT->getDecl());
+        if (Corrected) {
+          std::string CorrectedStr(
+              Corrected.getAsString(SemaRef.getLangOpts()));
+          std::string CorrectedQuotedStr(
+              Corrected.getQuoted(SemaRef.getLangOpts()));
+          ReplacementField = Corrected.getCorrectionDeclAs<FieldDecl>();
+          SemaRef.Diag(D->getFieldLoc(),
+                       diag::err_field_designator_unknown_suggest)
+            << FieldName << CurrentObjectType << CorrectedQuotedStr
+            << FixItHint::CreateReplacement(D->getFieldLoc(), CorrectedStr);
+          SemaRef.Diag(ReplacementField->getLocation(),
+                       diag::note_previous_decl) << CorrectedQuotedStr;
+          hadError = true;
+        } else {
+          SemaRef.Diag(D->getFieldLoc(), diag::err_field_designator_unknown)
+            << FieldName << CurrentObjectType;
+          ++Index;
+          return true;
+        }
+      }
+
+      if (!ReplacementField) {
+        // Name lookup found something, but it wasn't a field.
+        SemaRef.Diag(D->getFieldLoc(), diag::err_field_designator_nonfield)
+          << FieldName;
+        SemaRef.Diag((*Lookup.first)->getLocation(),
+                      diag::note_field_designator_found);
+        ++Index;
+        return true;
+      }
+
+      if (!KnownField) {
+        // The replacement field comes from typo correction; find it
+        // in the list of fields.
+        FieldIndex = 0;
+        Field = RT->getDecl()->field_begin();
+        for (; Field != FieldEnd; ++Field) {
+          if (Field->isUnnamedBitfield())
+            continue;
+
+          if (ReplacementField == *Field ||
+              Field->getIdentifier() == ReplacementField->getIdentifier())
+            break;
+
+          ++FieldIndex;
+        }
+      }
+    }
+
+    // All of the fields of a union are located at the same place in
+    // the initializer list.
+    if (RT->getDecl()->isUnion()) {
+      FieldIndex = 0;
+      if (!VerifyOnly)
+        StructuredList->setInitializedFieldInUnion(*Field);
+    }
+
+    // Make sure we can use this declaration.
+    bool InvalidUse;
+    if (VerifyOnly)
+      InvalidUse = !SemaRef.CanUseDecl(*Field);
+    else
+      InvalidUse = SemaRef.DiagnoseUseOfDecl(*Field, D->getFieldLoc());
+    if (InvalidUse) {
+      ++Index;
+      return true;
+    }
+
+    if (!VerifyOnly) {
+      // Update the designator with the field declaration.
+      D->setField(*Field);
+
+      // Make sure that our non-designated initializer list has space
+      // for a subobject corresponding to this field.
+      if (FieldIndex >= StructuredList->getNumInits())
+        StructuredList->resizeInits(SemaRef.Context, FieldIndex + 1);
+    }
+
+    // This designator names a flexible array member.
+    if (Field->getType()->isIncompleteArrayType()) {
+      bool Invalid = false;
+      if ((DesigIdx + 1) != DIE->size()) {
+        // We can't designate an object within the flexible array
+        // member (because GCC doesn't allow it).
+        if (!VerifyOnly) {
+          DesignatedInitExpr::Designator *NextD
+            = DIE->getDesignator(DesigIdx + 1);
+          SemaRef.Diag(NextD->getStartLocation(),
+                        diag::err_designator_into_flexible_array_member)
+            << SourceRange(NextD->getStartLocation(),
+                           DIE->getSourceRange().getEnd());
+          SemaRef.Diag(Field->getLocation(), diag::note_flexible_array_member)
+            << *Field;
+        }
+        Invalid = true;
+      }
+
+      if (!hadError && !isa<InitListExpr>(DIE->getInit()) &&
+          !isa<StringLiteral>(DIE->getInit())) {
+        // The initializer is not an initializer list.
+        if (!VerifyOnly) {
+          SemaRef.Diag(DIE->getInit()->getLocStart(),
+                        diag::err_flexible_array_init_needs_braces)
+            << DIE->getInit()->getSourceRange();
+          SemaRef.Diag(Field->getLocation(), diag::note_flexible_array_member)
+            << *Field;
+        }
+        Invalid = true;
+      }
+
+      // Check GNU flexible array initializer.
+      if (!Invalid && CheckFlexibleArrayInit(Entity, DIE->getInit(), *Field,
+                                             TopLevelObject))
+        Invalid = true;
+
+      if (Invalid) {
+        ++Index;
+        return true;
+      }
+
+      // Initialize the array.
+      bool prevHadError = hadError;
+      unsigned newStructuredIndex = FieldIndex;
+      unsigned OldIndex = Index;
+      IList->setInit(Index, DIE->getInit());
+
+      InitializedEntity MemberEntity =
+        InitializedEntity::InitializeMember(*Field, &Entity);
+      CheckSubElementType(MemberEntity, IList, Field->getType(), Index,
+                          StructuredList, newStructuredIndex);
+
+      IList->setInit(OldIndex, DIE);
+      if (hadError && !prevHadError) {
+        ++Field;
+        ++FieldIndex;
+        if (NextField)
+          *NextField = Field;
+        StructuredIndex = FieldIndex;
+        return true;
+      }
+    } else {
+      // Recurse to check later designated subobjects.
+      QualType FieldType = (*Field)->getType();
+      unsigned newStructuredIndex = FieldIndex;
+
+      InitializedEntity MemberEntity =
+        InitializedEntity::InitializeMember(*Field, &Entity);
+      if (CheckDesignatedInitializer(MemberEntity, IList, DIE, DesigIdx + 1,
+                                     FieldType, 0, 0, Index,
+                                     StructuredList, newStructuredIndex,
+                                     true, false))
+        return true;
+    }
+
+    // Find the position of the next field to be initialized in this
+    // subobject.
+    ++Field;
+    ++FieldIndex;
+
+    // If this the first designator, our caller will continue checking
+    // the rest of this struct/class/union subobject.
+    if (IsFirstDesignator) {
+      if (NextField)
+        *NextField = Field;
+      StructuredIndex = FieldIndex;
+      return false;
+    }
+
+    if (!FinishSubobjectInit)
+      return false;
+
+    // We've already initialized something in the union; we're done.
+    if (RT->getDecl()->isUnion())
+      return hadError;
+
+    // Check the remaining fields within this class/struct/union subobject.
+    bool prevHadError = hadError;
+
+    CheckStructUnionTypes(Entity, IList, CurrentObjectType, Field, false, Index,
+                          StructuredList, FieldIndex);
+    return hadError && !prevHadError;
+  }
+
+  // C99 6.7.8p6:
+  //
+  //   If a designator has the form
+  //
+  //      [ constant-expression ]
+  //
+  //   then the current object (defined below) shall have array
+  //   type and the expression shall be an integer constant
+  //   expression. If the array is of unknown size, any
+  //   nonnegative value is valid.
+  //
+  // Additionally, cope with the GNU extension that permits
+  // designators of the form
+  //
+  //      [ constant-expression ... constant-expression ]
+  const ArrayType *AT = SemaRef.Context.getAsArrayType(CurrentObjectType);
+  if (!AT) {
+    if (!VerifyOnly)
+      SemaRef.Diag(D->getLBracketLoc(), diag::err_array_designator_non_array)
+        << CurrentObjectType;
+    ++Index;
+    return true;
+  }
+
+  Expr *IndexExpr = 0;
+  llvm::APSInt DesignatedStartIndex, DesignatedEndIndex;
+  if (D->isArrayDesignator()) {
+    IndexExpr = DIE->getArrayIndex(*D);
+    DesignatedStartIndex = IndexExpr->EvaluateKnownConstInt(SemaRef.Context);
+    DesignatedEndIndex = DesignatedStartIndex;
+  } else {
+    assert(D->isArrayRangeDesignator() && "Need array-range designator");
+
+    DesignatedStartIndex =
+      DIE->getArrayRangeStart(*D)->EvaluateKnownConstInt(SemaRef.Context);
+    DesignatedEndIndex =
+      DIE->getArrayRangeEnd(*D)->EvaluateKnownConstInt(SemaRef.Context);
+    IndexExpr = DIE->getArrayRangeEnd(*D);
+
+    // Codegen can't handle evaluating array range designators that have side
+    // effects, because we replicate the AST value for each initialized element.
+    // As such, set the sawArrayRangeDesignator() bit if we initialize multiple
+    // elements with something that has a side effect, so codegen can emit an
+    // "error unsupported" error instead of miscompiling the app.
+    if (DesignatedStartIndex.getZExtValue()!=DesignatedEndIndex.getZExtValue()&&
+        DIE->getInit()->HasSideEffects(SemaRef.Context) && !VerifyOnly)
+      FullyStructuredList->sawArrayRangeDesignator();
+  }
+
+  if (isa<ConstantArrayType>(AT)) {
+    llvm::APSInt MaxElements(cast<ConstantArrayType>(AT)->getSize(), false);
+    DesignatedStartIndex
+      = DesignatedStartIndex.extOrTrunc(MaxElements.getBitWidth());
+    DesignatedStartIndex.setIsUnsigned(MaxElements.isUnsigned());
+    DesignatedEndIndex
+      = DesignatedEndIndex.extOrTrunc(MaxElements.getBitWidth());
+    DesignatedEndIndex.setIsUnsigned(MaxElements.isUnsigned());
+    if (DesignatedEndIndex >= MaxElements) {
+      if (!VerifyOnly)
+        SemaRef.Diag(IndexExpr->getLocStart(),
+                      diag::err_array_designator_too_large)
+          << DesignatedEndIndex.toString(10) << MaxElements.toString(10)
+          << IndexExpr->getSourceRange();
+      ++Index;
+      return true;
+    }
+  } else {
+    // Make sure the bit-widths and signedness match.
+    if (DesignatedStartIndex.getBitWidth() > DesignatedEndIndex.getBitWidth())
+      DesignatedEndIndex
+        = DesignatedEndIndex.extend(DesignatedStartIndex.getBitWidth());
+    else if (DesignatedStartIndex.getBitWidth() <
+             DesignatedEndIndex.getBitWidth())
+      DesignatedStartIndex
+        = DesignatedStartIndex.extend(DesignatedEndIndex.getBitWidth());
+    DesignatedStartIndex.setIsUnsigned(true);
+    DesignatedEndIndex.setIsUnsigned(true);
+  }
+
+  // Make sure that our non-designated initializer list has space
+  // for a subobject corresponding to this array element.
+  if (!VerifyOnly &&
+      DesignatedEndIndex.getZExtValue() >= StructuredList->getNumInits())
+    StructuredList->resizeInits(SemaRef.Context,
+                                DesignatedEndIndex.getZExtValue() + 1);
+
+  // Repeatedly perform subobject initializations in the range
+  // [DesignatedStartIndex, DesignatedEndIndex].
+
+  // Move to the next designator
+  unsigned ElementIndex = DesignatedStartIndex.getZExtValue();
+  unsigned OldIndex = Index;
+
+  InitializedEntity ElementEntity =
+    InitializedEntity::InitializeElement(SemaRef.Context, 0, Entity);
+
+  while (DesignatedStartIndex <= DesignatedEndIndex) {
+    // Recurse to check later designated subobjects.
+    QualType ElementType = AT->getElementType();
+    Index = OldIndex;
+
+    ElementEntity.setElementIndex(ElementIndex);
+    if (CheckDesignatedInitializer(ElementEntity, IList, DIE, DesigIdx + 1,
+                                   ElementType, 0, 0, Index,
+                                   StructuredList, ElementIndex,
+                                   (DesignatedStartIndex == DesignatedEndIndex),
+                                   false))
+      return true;
+
+    // Move to the next index in the array that we'll be initializing.
+    ++DesignatedStartIndex;
+    ElementIndex = DesignatedStartIndex.getZExtValue();
+  }
+
+  // If this the first designator, our caller will continue checking
+  // the rest of this array subobject.
+  if (IsFirstDesignator) {
+    if (NextElementIndex)
+      *NextElementIndex = DesignatedStartIndex;
+    StructuredIndex = ElementIndex;
+    return false;
+  }
+
+  if (!FinishSubobjectInit)
+    return false;
+
+  // Check the remaining elements within this array subobject.
+  bool prevHadError = hadError;
+  CheckArrayType(Entity, IList, CurrentObjectType, DesignatedStartIndex,
+                 /*SubobjectIsDesignatorContext=*/false, Index,
+                 StructuredList, ElementIndex);
+  return hadError && !prevHadError;
+}
+
+// Get the structured initializer list for a subobject of type
+// @p CurrentObjectType.
+InitListExpr *
+InitListChecker::getStructuredSubobjectInit(InitListExpr *IList, unsigned Index,
+                                            QualType CurrentObjectType,
+                                            InitListExpr *StructuredList,
+                                            unsigned StructuredIndex,
+                                            SourceRange InitRange) {
+  if (VerifyOnly)
+    return 0; // No structured list in verification-only mode.
+  Expr *ExistingInit = 0;
+  if (!StructuredList)
+    ExistingInit = SyntacticToSemantic.lookup(IList);
+  else if (StructuredIndex < StructuredList->getNumInits())
+    ExistingInit = StructuredList->getInit(StructuredIndex);
+
+  if (InitListExpr *Result = dyn_cast_or_null<InitListExpr>(ExistingInit))
+    return Result;
+
+  if (ExistingInit) {
+    // We are creating an initializer list that initializes the
+    // subobjects of the current object, but there was already an
+    // initialization that completely initialized the current
+    // subobject, e.g., by a compound literal:
+    //
+    // struct X { int a, b; };
+    // struct X xs[] = { [0] = (struct X) { 1, 2 }, [0].b = 3 };
+    //
+    // Here, xs[0].a == 0 and xs[0].b == 3, since the second,
+    // designated initializer re-initializes the whole
+    // subobject [0], overwriting previous initializers.
+    SemaRef.Diag(InitRange.getBegin(),
+                 diag::warn_subobject_initializer_overrides)
+      << InitRange;
+    SemaRef.Diag(ExistingInit->getLocStart(),
+                  diag::note_previous_initializer)
+      << /*FIXME:has side effects=*/0
+      << ExistingInit->getSourceRange();
+  }
+
+  InitListExpr *Result
+    = new (SemaRef.Context) InitListExpr(SemaRef.Context,
+                                         InitRange.getBegin(), 0, 0,
+                                         InitRange.getEnd());
+
+  QualType ResultType = CurrentObjectType;
+  if (!ResultType->isArrayType())
+    ResultType = ResultType.getNonLValueExprType(SemaRef.Context);
+  Result->setType(ResultType);
+
+  // Pre-allocate storage for the structured initializer list.
+  unsigned NumElements = 0;
+  unsigned NumInits = 0;
+  bool GotNumInits = false;
+  if (!StructuredList) {
+    NumInits = IList->getNumInits();
+    GotNumInits = true;
+  } else if (Index < IList->getNumInits()) {
+    if (InitListExpr *SubList = dyn_cast<InitListExpr>(IList->getInit(Index))) {
+      NumInits = SubList->getNumInits();
+      GotNumInits = true;
+    }
+  }
+
+  if (const ArrayType *AType
+      = SemaRef.Context.getAsArrayType(CurrentObjectType)) {
+    if (const ConstantArrayType *CAType = dyn_cast<ConstantArrayType>(AType)) {
+      NumElements = CAType->getSize().getZExtValue();
+      // Simple heuristic so that we don't allocate a very large
+      // initializer with many empty entries at the end.
+      if (GotNumInits && NumElements > NumInits)
+        NumElements = 0;
+    }
+  } else if (const VectorType *VType = CurrentObjectType->getAs<VectorType>())
+    NumElements = VType->getNumElements();
+  else if (const RecordType *RType = CurrentObjectType->getAs<RecordType>()) {
+    RecordDecl *RDecl = RType->getDecl();
+    if (RDecl->isUnion())
+      NumElements = 1;
+    else
+      NumElements = std::distance(RDecl->field_begin(),
+                                  RDecl->field_end());
+  }
+
+  Result->reserveInits(SemaRef.Context, NumElements);
+
+  // Link this new initializer list into the structured initializer
+  // lists.
+  if (StructuredList)
+    StructuredList->updateInit(SemaRef.Context, StructuredIndex, Result);
+  else {
+    Result->setSyntacticForm(IList);
+    SyntacticToSemantic[IList] = Result;
+  }
+
+  return Result;
+}
+
+/// Update the initializer at index @p StructuredIndex within the
+/// structured initializer list to the value @p expr.
+void InitListChecker::UpdateStructuredListElement(InitListExpr *StructuredList,
+                                                  unsigned &StructuredIndex,
+                                                  Expr *expr) {
+  // No structured initializer list to update
+  if (!StructuredList)
+    return;
+
+  if (Expr *PrevInit = StructuredList->updateInit(SemaRef.Context,
+                                                  StructuredIndex, expr)) {
+    // This initializer overwrites a previous initializer. Warn.
+    SemaRef.Diag(expr->getLocStart(),
+                  diag::warn_initializer_overrides)
+      << expr->getSourceRange();
+    SemaRef.Diag(PrevInit->getLocStart(),
+                  diag::note_previous_initializer)
+      << /*FIXME:has side effects=*/0
+      << PrevInit->getSourceRange();
+  }
+
+  ++StructuredIndex;
+}
+
+/// Check that the given Index expression is a valid array designator
+/// value. This is essentially just a wrapper around
+/// VerifyIntegerConstantExpression that also checks for negative values
+/// and produces a reasonable diagnostic if there is a
+/// failure. Returns the index expression, possibly with an implicit cast
+/// added, on success.  If everything went okay, Value will receive the
+/// value of the constant expression.
+static ExprResult
+CheckArrayDesignatorExpr(Sema &S, Expr *Index, llvm::APSInt &Value) {
+  SourceLocation Loc = Index->getLocStart();
+
+  // Make sure this is an integer constant expression.
+  ExprResult Result = S.VerifyIntegerConstantExpression(Index, &Value);
+  if (Result.isInvalid())
+    return Result;
+
+  if (Value.isSigned() && Value.isNegative())
+    return S.Diag(Loc, diag::err_array_designator_negative)
+      << Value.toString(10) << Index->getSourceRange();
+
+  Value.setIsUnsigned(true);
+  return Result;
+}
+
+ExprResult Sema::ActOnDesignatedInitializer(Designation &Desig,
+                                            SourceLocation Loc,
+                                            bool GNUSyntax,
+                                            ExprResult Init) {
+  typedef DesignatedInitExpr::Designator ASTDesignator;
+
+  bool Invalid = false;
+  SmallVector<ASTDesignator, 32> Designators;
+  SmallVector<Expr *, 32> InitExpressions;
+
+  // Build designators and check array designator expressions.
+  for (unsigned Idx = 0; Idx < Desig.getNumDesignators(); ++Idx) {
+    const Designator &D = Desig.getDesignator(Idx);
+    switch (D.getKind()) {
+    case Designator::FieldDesignator:
+      Designators.push_back(ASTDesignator(D.getField(), D.getDotLoc(),
+                                          D.getFieldLoc()));
+      break;
+
+    case Designator::ArrayDesignator: {
+      Expr *Index = static_cast<Expr *>(D.getArrayIndex());
+      llvm::APSInt IndexValue;
+      if (!Index->isTypeDependent() && !Index->isValueDependent())
+        Index = CheckArrayDesignatorExpr(*this, Index, IndexValue).take();
+      if (!Index)
+        Invalid = true;
+      else {
+        Designators.push_back(ASTDesignator(InitExpressions.size(),
+                                            D.getLBracketLoc(),
+                                            D.getRBracketLoc()));
+        InitExpressions.push_back(Index);
+      }
+      break;
+    }
+
+    case Designator::ArrayRangeDesignator: {
+      Expr *StartIndex = static_cast<Expr *>(D.getArrayRangeStart());
+      Expr *EndIndex = static_cast<Expr *>(D.getArrayRangeEnd());
+      llvm::APSInt StartValue;
+      llvm::APSInt EndValue;
+      bool StartDependent = StartIndex->isTypeDependent() ||
+                            StartIndex->isValueDependent();
+      bool EndDependent = EndIndex->isTypeDependent() ||
+                          EndIndex->isValueDependent();
+      if (!StartDependent)
+        StartIndex =
+            CheckArrayDesignatorExpr(*this, StartIndex, StartValue).take();
+      if (!EndDependent)
+        EndIndex = CheckArrayDesignatorExpr(*this, EndIndex, EndValue).take();
+
+      if (!StartIndex || !EndIndex)
+        Invalid = true;
+      else {
+        // Make sure we're comparing values with the same bit width.
+        if (StartDependent || EndDependent) {
+          // Nothing to compute.
+        } else if (StartValue.getBitWidth() > EndValue.getBitWidth())
+          EndValue = EndValue.extend(StartValue.getBitWidth());
+        else if (StartValue.getBitWidth() < EndValue.getBitWidth())
+          StartValue = StartValue.extend(EndValue.getBitWidth());
+
+        if (!StartDependent && !EndDependent && EndValue < StartValue) {
+          Diag(D.getEllipsisLoc(), diag::err_array_designator_empty_range)
+            << StartValue.toString(10) << EndValue.toString(10)
+            << StartIndex->getSourceRange() << EndIndex->getSourceRange();
+          Invalid = true;
+        } else {
+          Designators.push_back(ASTDesignator(InitExpressions.size(),
+                                              D.getLBracketLoc(),
+                                              D.getEllipsisLoc(),
+                                              D.getRBracketLoc()));
+          InitExpressions.push_back(StartIndex);
+          InitExpressions.push_back(EndIndex);
+        }
+      }
+      break;
+    }
+    }
+  }
+
+  if (Invalid || Init.isInvalid())
+    return ExprError();
+
+  // Clear out the expressions within the designation.
+  Desig.ClearExprs(*this);
+
+  DesignatedInitExpr *DIE
+    = DesignatedInitExpr::Create(Context,
+                                 Designators.data(), Designators.size(),
+                                 InitExpressions.data(), InitExpressions.size(),
+                                 Loc, GNUSyntax, Init.takeAs<Expr>());
+
+  if (!getLangOpts().C99)
+    Diag(DIE->getLocStart(), diag::ext_designated_init)
+      << DIE->getSourceRange();
+
+  return Owned(DIE);
+}
+
+//===----------------------------------------------------------------------===//
+// Initialization entity
+//===----------------------------------------------------------------------===//
+
+InitializedEntity::InitializedEntity(ASTContext &Context, unsigned Index,
+                                     const InitializedEntity &Parent)
+  : Parent(&Parent), Index(Index)
+{
+  if (const ArrayType *AT = Context.getAsArrayType(Parent.getType())) {
+    Kind = EK_ArrayElement;
+    Type = AT->getElementType();
+  } else if (const VectorType *VT = Parent.getType()->getAs<VectorType>()) {
+    Kind = EK_VectorElement;
+    Type = VT->getElementType();
+  } else {
+    const ComplexType *CT = Parent.getType()->getAs<ComplexType>();
+    assert(CT && "Unexpected type");
+    Kind = EK_ComplexElement;
+    Type = CT->getElementType();
+  }
+}
+
+InitializedEntity InitializedEntity::InitializeBase(ASTContext &Context,
+                                                    CXXBaseSpecifier *Base,
+                                                    bool IsInheritedVirtualBase)
+{
+  InitializedEntity Result;
+  Result.Kind = EK_Base;
+  Result.Base = reinterpret_cast<uintptr_t>(Base);
+  if (IsInheritedVirtualBase)
+    Result.Base |= 0x01;
+
+  Result.Type = Base->getType();
+  return Result;
+}
+
+DeclarationName InitializedEntity::getName() const {
+  switch (getKind()) {
+  case EK_Parameter: {
+    ParmVarDecl *D = reinterpret_cast<ParmVarDecl*>(Parameter & ~0x1);
+    return (D ? D->getDeclName() : DeclarationName());
+  }
+
+  case EK_Variable:
+  case EK_Member:
+    return VariableOrMember->getDeclName();
+
+  case EK_LambdaCapture:
+    return Capture.Var->getDeclName();
+      
+  case EK_Result:
+  case EK_Exception:
+  case EK_New:
+  case EK_Temporary:
+  case EK_Base:
+  case EK_Delegating:
+  case EK_ArrayElement:
+  case EK_VectorElement:
+  case EK_ComplexElement:
+  case EK_BlockElement:
+    return DeclarationName();
+  }
+
+  llvm_unreachable("Invalid EntityKind!");
+}
+
+DeclaratorDecl *InitializedEntity::getDecl() const {
+  switch (getKind()) {
+  case EK_Variable:
+  case EK_Member:
+    return VariableOrMember;
+
+  case EK_Parameter:
+    return reinterpret_cast<ParmVarDecl*>(Parameter & ~0x1);
+
+  case EK_Result:
+  case EK_Exception:
+  case EK_New:
+  case EK_Temporary:
+  case EK_Base:
+  case EK_Delegating:
+  case EK_ArrayElement:
+  case EK_VectorElement:
+  case EK_ComplexElement:
+  case EK_BlockElement:
+  case EK_LambdaCapture:
+    return 0;
+  }
+
+  llvm_unreachable("Invalid EntityKind!");
+}
+
+bool InitializedEntity::allowsNRVO() const {
+  switch (getKind()) {
+  case EK_Result:
+  case EK_Exception:
+    return LocAndNRVO.NRVO;
+
+  case EK_Variable:
+  case EK_Parameter:
+  case EK_Member:
+  case EK_New:
+  case EK_Temporary:
+  case EK_Base:
+  case EK_Delegating:
+  case EK_ArrayElement:
+  case EK_VectorElement:
+  case EK_ComplexElement:
+  case EK_BlockElement:
+  case EK_LambdaCapture:
+    break;
+  }
+
+  return false;
+}
+
+//===----------------------------------------------------------------------===//
+// Initialization sequence
+//===----------------------------------------------------------------------===//
+
+void InitializationSequence::Step::Destroy() {
+  switch (Kind) {
+  case SK_ResolveAddressOfOverloadedFunction:
+  case SK_CastDerivedToBaseRValue:
+  case SK_CastDerivedToBaseXValue:
+  case SK_CastDerivedToBaseLValue:
+  case SK_BindReference:
+  case SK_BindReferenceToTemporary:
+  case SK_ExtraneousCopyToTemporary:
+  case SK_UserConversion:
+  case SK_QualificationConversionRValue:
+  case SK_QualificationConversionXValue:
+  case SK_QualificationConversionLValue:
+  case SK_ListInitialization:
+  case SK_ListConstructorCall:
+  case SK_UnwrapInitList:
+  case SK_RewrapInitList:
+  case SK_ConstructorInitialization:
+  case SK_ZeroInitialization:
+  case SK_CAssignment:
+  case SK_StringInit:
+  case SK_ObjCObjectConversion:
+  case SK_ArrayInit:
+  case SK_ParenthesizedArrayInit:
+  case SK_PassByIndirectCopyRestore:
+  case SK_PassByIndirectRestore:
+  case SK_ProduceObjCObject:
+  case SK_StdInitializerList:
+    break;
+
+  case SK_ConversionSequence:
+    delete ICS;
+  }
+}
+
+bool InitializationSequence::isDirectReferenceBinding() const {
+  return !Steps.empty() && Steps.back().Kind == SK_BindReference;
+}
+
+bool InitializationSequence::isAmbiguous() const {
+  if (!Failed())
+    return false;
+
+  switch (getFailureKind()) {
+  case FK_TooManyInitsForReference:
+  case FK_ArrayNeedsInitList:
+  case FK_ArrayNeedsInitListOrStringLiteral:
+  case FK_AddressOfOverloadFailed: // FIXME: Could do better
+  case FK_NonConstLValueReferenceBindingToTemporary:
+  case FK_NonConstLValueReferenceBindingToUnrelated:
+  case FK_RValueReferenceBindingToLValue:
+  case FK_ReferenceInitDropsQualifiers:
+  case FK_ReferenceInitFailed:
+  case FK_ConversionFailed:
+  case FK_ConversionFromPropertyFailed:
+  case FK_TooManyInitsForScalar:
+  case FK_ReferenceBindingToInitList:
+  case FK_InitListBadDestinationType:
+  case FK_DefaultInitOfConst:
+  case FK_Incomplete:
+  case FK_ArrayTypeMismatch:
+  case FK_NonConstantArrayInit:
+  case FK_ListInitializationFailed:
+  case FK_VariableLengthArrayHasInitializer:
+  case FK_PlaceholderType:
+  case FK_InitListElementCopyFailure:
+  case FK_ExplicitConstructor:
+    return false;
+
+  case FK_ReferenceInitOverloadFailed:
+  case FK_UserConversionOverloadFailed:
+  case FK_ConstructorOverloadFailed:
+  case FK_ListConstructorOverloadFailed:
+    return FailedOverloadResult == OR_Ambiguous;
+  }
+
+  llvm_unreachable("Invalid EntityKind!");
+}
+
+bool InitializationSequence::isConstructorInitialization() const {
+  return !Steps.empty() && Steps.back().Kind == SK_ConstructorInitialization;
+}
+
+void
+InitializationSequence
+::AddAddressOverloadResolutionStep(FunctionDecl *Function,
+                                   DeclAccessPair Found,
+                                   bool HadMultipleCandidates) {
+  Step S;
+  S.Kind = SK_ResolveAddressOfOverloadedFunction;
+  S.Type = Function->getType();
+  S.Function.HadMultipleCandidates = HadMultipleCandidates;
+  S.Function.Function = Function;
+  S.Function.FoundDecl = Found;
+  Steps.push_back(S);
+}
+
+void InitializationSequence::AddDerivedToBaseCastStep(QualType BaseType,
+                                                      ExprValueKind VK) {
+  Step S;
+  switch (VK) {
+  case VK_RValue: S.Kind = SK_CastDerivedToBaseRValue; break;
+  case VK_XValue: S.Kind = SK_CastDerivedToBaseXValue; break;
+  case VK_LValue: S.Kind = SK_CastDerivedToBaseLValue; break;
+  }
+  S.Type = BaseType;
+  Steps.push_back(S);
+}
+
+void InitializationSequence::AddReferenceBindingStep(QualType T,
+                                                     bool BindingTemporary) {
+  Step S;
+  S.Kind = BindingTemporary? SK_BindReferenceToTemporary : SK_BindReference;
+  S.Type = T;
+  Steps.push_back(S);
+}
+
+void InitializationSequence::AddExtraneousCopyToTemporary(QualType T) {
+  Step S;
+  S.Kind = SK_ExtraneousCopyToTemporary;
+  S.Type = T;
+  Steps.push_back(S);
+}
+
+void
+InitializationSequence::AddUserConversionStep(FunctionDecl *Function,
+                                              DeclAccessPair FoundDecl,
+                                              QualType T,
+                                              bool HadMultipleCandidates) {
+  Step S;
+  S.Kind = SK_UserConversion;
+  S.Type = T;
+  S.Function.HadMultipleCandidates = HadMultipleCandidates;
+  S.Function.Function = Function;
+  S.Function.FoundDecl = FoundDecl;
+  Steps.push_back(S);
+}
+
+void InitializationSequence::AddQualificationConversionStep(QualType Ty,
+                                                            ExprValueKind VK) {
+  Step S;
+  S.Kind = SK_QualificationConversionRValue; // work around a gcc warning
+  switch (VK) {
+  case VK_RValue:
+    S.Kind = SK_QualificationConversionRValue;
+    break;
+  case VK_XValue:
+    S.Kind = SK_QualificationConversionXValue;
+    break;
+  case VK_LValue:
+    S.Kind = SK_QualificationConversionLValue;
+    break;
+  }
+  S.Type = Ty;
+  Steps.push_back(S);
+}
+
+void InitializationSequence::AddConversionSequenceStep(
+                                       const ImplicitConversionSequence &ICS,
+                                                       QualType T) {
+  Step S;
+  S.Kind = SK_ConversionSequence;
+  S.Type = T;
+  S.ICS = new ImplicitConversionSequence(ICS);
+  Steps.push_back(S);
+}
+
+void InitializationSequence::AddListInitializationStep(QualType T) {
+  Step S;
+  S.Kind = SK_ListInitialization;
+  S.Type = T;
+  Steps.push_back(S);
+}
+
+void
+InitializationSequence
+::AddConstructorInitializationStep(CXXConstructorDecl *Constructor,
+                                   AccessSpecifier Access,
+                                   QualType T,
+                                   bool HadMultipleCandidates,
+                                   bool FromInitList, bool AsInitList) {
+  Step S;
+  S.Kind = FromInitList && !AsInitList ? SK_ListConstructorCall
+                                       : SK_ConstructorInitialization;
+  S.Type = T;
+  S.Function.HadMultipleCandidates = HadMultipleCandidates;
+  S.Function.Function = Constructor;
+  S.Function.FoundDecl = DeclAccessPair::make(Constructor, Access);
+  Steps.push_back(S);
+}
+
+void InitializationSequence::AddZeroInitializationStep(QualType T) {
+  Step S;
+  S.Kind = SK_ZeroInitialization;
+  S.Type = T;
+  Steps.push_back(S);
+}
+
+void InitializationSequence::AddCAssignmentStep(QualType T) {
+  Step S;
+  S.Kind = SK_CAssignment;
+  S.Type = T;
+  Steps.push_back(S);
+}
+
+void InitializationSequence::AddStringInitStep(QualType T) {
+  Step S;
+  S.Kind = SK_StringInit;
+  S.Type = T;
+  Steps.push_back(S);
+}
+
+void InitializationSequence::AddObjCObjectConversionStep(QualType T) {
+  Step S;
+  S.Kind = SK_ObjCObjectConversion;
+  S.Type = T;
+  Steps.push_back(S);
+}
+
+void InitializationSequence::AddArrayInitStep(QualType T) {
+  Step S;
+  S.Kind = SK_ArrayInit;
+  S.Type = T;
+  Steps.push_back(S);
+}
+
+void InitializationSequence::AddParenthesizedArrayInitStep(QualType T) {
+  Step S;
+  S.Kind = SK_ParenthesizedArrayInit;
+  S.Type = T;
+  Steps.push_back(S);
+}
+
+void InitializationSequence::AddPassByIndirectCopyRestoreStep(QualType type,
+                                                              bool shouldCopy) {
+  Step s;
+  s.Kind = (shouldCopy ? SK_PassByIndirectCopyRestore
+                       : SK_PassByIndirectRestore);
+  s.Type = type;
+  Steps.push_back(s);
+}
+
+void InitializationSequence::AddProduceObjCObjectStep(QualType T) {
+  Step S;
+  S.Kind = SK_ProduceObjCObject;
+  S.Type = T;
+  Steps.push_back(S);
+}
+
+void InitializationSequence::AddStdInitializerListConstructionStep(QualType T) {
+  Step S;
+  S.Kind = SK_StdInitializerList;
+  S.Type = T;
+  Steps.push_back(S);
+}
+
+void InitializationSequence::RewrapReferenceInitList(QualType T,
+                                                     InitListExpr *Syntactic) {
+  assert(Syntactic->getNumInits() == 1 &&
+         "Can only rewrap trivial init lists.");
+  Step S;
+  S.Kind = SK_UnwrapInitList;
+  S.Type = Syntactic->getInit(0)->getType();
+  Steps.insert(Steps.begin(), S);
+
+  S.Kind = SK_RewrapInitList;
+  S.Type = T;
+  S.WrappingSyntacticList = Syntactic;
+  Steps.push_back(S);
+}
+
+void InitializationSequence::SetOverloadFailure(FailureKind Failure,
+                                                OverloadingResult Result) {
+  setSequenceKind(FailedSequence);
+  this->Failure = Failure;
+  this->FailedOverloadResult = Result;
+}
+
+//===----------------------------------------------------------------------===//
+// Attempt initialization
+//===----------------------------------------------------------------------===//
+
+static void MaybeProduceObjCObject(Sema &S,
+                                   InitializationSequence &Sequence,
+                                   const InitializedEntity &Entity) {
+  if (!S.getLangOpts().ObjCAutoRefCount) return;
+
+  /// When initializing a parameter, produce the value if it's marked
+  /// __attribute__((ns_consumed)).
+  if (Entity.getKind() == InitializedEntity::EK_Parameter) {
+    if (!Entity.isParameterConsumed())
+      return;
+
+    assert(Entity.getType()->isObjCRetainableType() &&
+           "consuming an object of unretainable type?");
+    Sequence.AddProduceObjCObjectStep(Entity.getType());
+
+  /// When initializing a return value, if the return type is a
+  /// retainable type, then returns need to immediately retain the
+  /// object.  If an autorelease is required, it will be done at the
+  /// last instant.
+  } else if (Entity.getKind() == InitializedEntity::EK_Result) {
+    if (!Entity.getType()->isObjCRetainableType())
+      return;
+
+    Sequence.AddProduceObjCObjectStep(Entity.getType());
+  }
+}
+
+/// \brief When initializing from init list via constructor, deal with the
+/// empty init list and std::initializer_list special cases.
+///
+/// \return True if this was a special case, false otherwise.
+static bool TryListConstructionSpecialCases(Sema &S,
+                                            InitListExpr *List,
+                                            CXXRecordDecl *DestRecordDecl,
+                                            QualType DestType,
+                                            InitializationSequence &Sequence) {
+  // C++11 [dcl.init.list]p3:
+  //   List-initialization of an object or reference of type T is defined as
+  //   follows:
+  //   - If T is an aggregate, aggregate initialization is performed.
+  if (DestType->isAggregateType())
+    return false;
+
+  //   - Otherwise, if the initializer list has no elements and T is a class
+  //     type with a default constructor, the object is value-initialized.
+  if (List->getNumInits() == 0) {
+    if (CXXConstructorDecl *DefaultConstructor =
+            S.LookupDefaultConstructor(DestRecordDecl)) {
+      if (DefaultConstructor->isDeleted() ||
+          S.isFunctionConsideredUnavailable(DefaultConstructor)) {
+        // Fake an overload resolution failure.
+        OverloadCandidateSet &CandidateSet = Sequence.getFailedCandidateSet();
+        DeclAccessPair FoundDecl = DeclAccessPair::make(DefaultConstructor,
+                                              DefaultConstructor->getAccess());
+        if (FunctionTemplateDecl *ConstructorTmpl =
+                dyn_cast<FunctionTemplateDecl>(DefaultConstructor))
+          S.AddTemplateOverloadCandidate(ConstructorTmpl, FoundDecl,
+                                         /*ExplicitArgs*/ 0,
+                                         ArrayRef<Expr*>(), CandidateSet,
+                                         /*SuppressUserConversions*/ false);
+        else
+          S.AddOverloadCandidate(DefaultConstructor, FoundDecl,
+                                 ArrayRef<Expr*>(), CandidateSet,
+                                 /*SuppressUserConversions*/ false);
+        Sequence.SetOverloadFailure(
+                       InitializationSequence::FK_ListConstructorOverloadFailed,
+                       OR_Deleted);
+      } else
+        Sequence.AddConstructorInitializationStep(DefaultConstructor,
+                                                DefaultConstructor->getAccess(),
+                                                  DestType,
+                                                  /*MultipleCandidates=*/false,
+                                                  /*FromInitList=*/true,
+                                                  /*AsInitList=*/false);
+      return true;
+    }
+  }
+
+  //   - Otherwise, if T is a specialization of std::initializer_list, [...]
+  QualType E;
+  if (S.isStdInitializerList(DestType, &E)) {
+    // Check that each individual element can be copy-constructed. But since we
+    // have no place to store further information, we'll recalculate everything
+    // later.
+    InitializedEntity HiddenArray = InitializedEntity::InitializeTemporary(
+        S.Context.getConstantArrayType(E,
+            llvm::APInt(S.Context.getTypeSize(S.Context.getSizeType()),
+                        List->getNumInits()),
+            ArrayType::Normal, 0));
+    InitializedEntity Element = InitializedEntity::InitializeElement(S.Context,
+        0, HiddenArray);
+    for (unsigned i = 0, n = List->getNumInits(); i < n; ++i) {
+      Element.setElementIndex(i);
+      if (!S.CanPerformCopyInitialization(Element, List->getInit(i))) {
+        Sequence.SetFailed(
+            InitializationSequence::FK_InitListElementCopyFailure);
+        return true;
+      }
+    }
+    Sequence.AddStdInitializerListConstructionStep(DestType);
+    return true;
+  }
+
+  // Not a special case.
+  return false;
+}
+
+static OverloadingResult
+ResolveConstructorOverload(Sema &S, SourceLocation DeclLoc,
+                           Expr **Args, unsigned NumArgs,
+                           OverloadCandidateSet &CandidateSet,
+                           DeclContext::lookup_iterator Con,
+                           DeclContext::lookup_iterator ConEnd,
+                           OverloadCandidateSet::iterator &Best,
+                           bool CopyInitializing, bool AllowExplicit,
+                           bool OnlyListConstructors, bool InitListSyntax) {
+  CandidateSet.clear();
+
+  for (; Con != ConEnd; ++Con) {
+    NamedDecl *D = *Con;
+    DeclAccessPair FoundDecl = DeclAccessPair::make(D, D->getAccess());
+    bool SuppressUserConversions = false;
+
+    // Find the constructor (which may be a template).
+    CXXConstructorDecl *Constructor = 0;
+    FunctionTemplateDecl *ConstructorTmpl = dyn_cast<FunctionTemplateDecl>(D);
+    if (ConstructorTmpl)
+      Constructor = cast<CXXConstructorDecl>(
+                                           ConstructorTmpl->getTemplatedDecl());
+    else {
+      Constructor = cast<CXXConstructorDecl>(D);
+
+      // If we're performing copy initialization using a copy constructor, we
+      // suppress user-defined conversions on the arguments. We do the same for
+      // move constructors.
+      if ((CopyInitializing || (InitListSyntax && NumArgs == 1)) &&
+          Constructor->isCopyOrMoveConstructor())
+        SuppressUserConversions = true;
+    }
+
+    if (!Constructor->isInvalidDecl() &&
+        (AllowExplicit || !Constructor->isExplicit()) &&
+        (!OnlyListConstructors || S.isInitListConstructor(Constructor))) {
+      if (ConstructorTmpl)
+        S.AddTemplateOverloadCandidate(ConstructorTmpl, FoundDecl,
+                                       /*ExplicitArgs*/ 0,
+                                       llvm::makeArrayRef(Args, NumArgs),
+                                       CandidateSet, SuppressUserConversions);
+      else {
+        // C++ [over.match.copy]p1:
+        //   - When initializing a temporary to be bound to the first parameter 
+        //     of a constructor that takes a reference to possibly cv-qualified 
+        //     T as its first argument, called with a single argument in the 
+        //     context of direct-initialization, explicit conversion functions
+        //     are also considered.
+        bool AllowExplicitConv = AllowExplicit && !CopyInitializing && 
+                                 NumArgs == 1 &&
+                                 Constructor->isCopyOrMoveConstructor();
+        S.AddOverloadCandidate(Constructor, FoundDecl,
+                               llvm::makeArrayRef(Args, NumArgs), CandidateSet,
+                               SuppressUserConversions,
+                               /*PartialOverloading=*/false,
+                               /*AllowExplicit=*/AllowExplicitConv);
+      }
+    }
+  }
+
+  // Perform overload resolution and return the result.
+  return CandidateSet.BestViableFunction(S, DeclLoc, Best);
+}
+
+/// \brief Attempt initialization by constructor (C++ [dcl.init]), which
+/// enumerates the constructors of the initialized entity and performs overload
+/// resolution to select the best.
+/// If InitListSyntax is true, this is list-initialization of a non-aggregate
+/// class type.
+static void TryConstructorInitialization(Sema &S,
+                                         const InitializedEntity &Entity,
+                                         const InitializationKind &Kind,
+                                         Expr **Args, unsigned NumArgs,
+                                         QualType DestType,
+                                         InitializationSequence &Sequence,
+                                         bool InitListSyntax = false) {
+  assert((!InitListSyntax || (NumArgs == 1 && isa<InitListExpr>(Args[0]))) &&
+         "InitListSyntax must come with a single initializer list argument.");
+
+  // Check constructor arguments for self reference.
+  if (DeclaratorDecl *DD = Entity.getDecl())
+    // Parameters arguments are occassionially constructed with itself,
+    // for instance, in recursive functions.  Skip them.
+    if (!isa<ParmVarDecl>(DD))
+      for (unsigned i = 0; i < NumArgs; ++i)
+        S.CheckSelfReference(DD, Args[i]);
+
+  // The type we're constructing needs to be complete.
+  if (S.RequireCompleteType(Kind.getLocation(), DestType, 0)) {
+    Sequence.setIncompleteTypeFailure(DestType);
+    return;
+  }
+
+  const RecordType *DestRecordType = DestType->getAs<RecordType>();
+  assert(DestRecordType && "Constructor initialization requires record type");
+  CXXRecordDecl *DestRecordDecl
+    = cast<CXXRecordDecl>(DestRecordType->getDecl());
+
+  if (InitListSyntax &&
+      TryListConstructionSpecialCases(S, cast<InitListExpr>(Args[0]),
+                                      DestRecordDecl, DestType, Sequence))
+    return;
+
+  // Build the candidate set directly in the initialization sequence
+  // structure, so that it will persist if we fail.
+  OverloadCandidateSet &CandidateSet = Sequence.getFailedCandidateSet();
+
+  // Determine whether we are allowed to call explicit constructors or
+  // explicit conversion operators.
+  bool AllowExplicit = Kind.AllowExplicit() || InitListSyntax;
+  bool CopyInitialization = Kind.getKind() == InitializationKind::IK_Copy;
+
+  //   - Otherwise, if T is a class type, constructors are considered. The
+  //     applicable constructors are enumerated, and the best one is chosen
+  //     through overload resolution.
+  DeclContext::lookup_iterator ConStart, ConEnd;
+  llvm::tie(ConStart, ConEnd) = S.LookupConstructors(DestRecordDecl);
+
+  OverloadingResult Result = OR_No_Viable_Function;
+  OverloadCandidateSet::iterator Best;
+  bool AsInitializerList = false;
+
+  // C++11 [over.match.list]p1:
+  //   When objects of non-aggregate type T are list-initialized, overload
+  //   resolution selects the constructor in two phases:
+  //   - Initially, the candidate functions are the initializer-list
+  //     constructors of the class T and the argument list consists of the
+  //     initializer list as a single argument.
+  if (InitListSyntax) {
+    AsInitializerList = true;
+    Result = ResolveConstructorOverload(S, Kind.getLocation(), Args, NumArgs,
+                                        CandidateSet, ConStart, ConEnd, Best,
+                                        CopyInitialization, AllowExplicit,
+                                        /*OnlyListConstructor=*/true,
+                                        InitListSyntax);
+
+    // Time to unwrap the init list.
+    InitListExpr *ILE = cast<InitListExpr>(Args[0]);
+    Args = ILE->getInits();
+    NumArgs = ILE->getNumInits();
+  }
+
+  // C++11 [over.match.list]p1:
+  //   - If no viable initializer-list constructor is found, overload resolution
+  //     is performed again, where the candidate functions are all the
+  //     constructors of the class T nad the argument list consists of the
+  //     elements of the initializer list.
+  if (Result == OR_No_Viable_Function) {
+    AsInitializerList = false;
+    Result = ResolveConstructorOverload(S, Kind.getLocation(), Args, NumArgs,
+                                        CandidateSet, ConStart, ConEnd, Best,
+                                        CopyInitialization, AllowExplicit,
+                                        /*OnlyListConstructors=*/false,
+                                        InitListSyntax);
+  }
+  if (Result) {
+    Sequence.SetOverloadFailure(InitListSyntax ?
+                      InitializationSequence::FK_ListConstructorOverloadFailed :
+                      InitializationSequence::FK_ConstructorOverloadFailed,
+                                Result);
+    return;
+  }
+
+  // C++0x [dcl.init]p6:
+  //   If a program calls for the default initialization of an object
+  //   of a const-qualified type T, T shall be a class type with a
+  //   user-provided default constructor.
+  if (Kind.getKind() == InitializationKind::IK_Default &&
+      Entity.getType().isConstQualified() &&
+      cast<CXXConstructorDecl>(Best->Function)->isImplicit()) {
+    Sequence.SetFailed(InitializationSequence::FK_DefaultInitOfConst);
+    return;
+  }
+
+  // C++11 [over.match.list]p1:
+  //   In copy-list-initialization, if an explicit constructor is chosen, the
+  //   initializer is ill-formed.
+  CXXConstructorDecl *CtorDecl = cast<CXXConstructorDecl>(Best->Function);
+  if (InitListSyntax && !Kind.AllowExplicit() && CtorDecl->isExplicit()) {
+    Sequence.SetFailed(InitializationSequence::FK_ExplicitConstructor);
+    return;
+  }
+
+  // Add the constructor initialization step. Any cv-qualification conversion is
+  // subsumed by the initialization.
+  bool HadMultipleCandidates = (CandidateSet.size() > 1);
+  Sequence.AddConstructorInitializationStep(CtorDecl,
+                                            Best->FoundDecl.getAccess(),
+                                            DestType, HadMultipleCandidates,
+                                            InitListSyntax, AsInitializerList);
+}
+
+static bool
+ResolveOverloadedFunctionForReferenceBinding(Sema &S,
+                                             Expr *Initializer,
+                                             QualType &SourceType,
+                                             QualType &UnqualifiedSourceType,
+                                             QualType UnqualifiedTargetType,
+                                             InitializationSequence &Sequence) {
+  if (S.Context.getCanonicalType(UnqualifiedSourceType) ==
+        S.Context.OverloadTy) {
+    DeclAccessPair Found;
+    bool HadMultipleCandidates = false;
+    if (FunctionDecl *Fn
+        = S.ResolveAddressOfOverloadedFunction(Initializer,
+                                               UnqualifiedTargetType,
+                                               false, Found,
+                                               &HadMultipleCandidates)) {
+      Sequence.AddAddressOverloadResolutionStep(Fn, Found,
+                                                HadMultipleCandidates);
+      SourceType = Fn->getType();
+      UnqualifiedSourceType = SourceType.getUnqualifiedType();
+    } else if (!UnqualifiedTargetType->isRecordType()) {
+      Sequence.SetFailed(InitializationSequence::FK_AddressOfOverloadFailed);
+      return true;
+    }
+  }
+  return false;
+}
+
+static void TryReferenceInitializationCore(Sema &S,
+                                           const InitializedEntity &Entity,
+                                           const InitializationKind &Kind,
+                                           Expr *Initializer,
+                                           QualType cv1T1, QualType T1,
+                                           Qualifiers T1Quals,
+                                           QualType cv2T2, QualType T2,
+                                           Qualifiers T2Quals,
+                                           InitializationSequence &Sequence);
+
+static void TryListInitialization(Sema &S,
+                                  const InitializedEntity &Entity,
+                                  const InitializationKind &Kind,
+                                  InitListExpr *InitList,
+                                  InitializationSequence &Sequence);
+
+/// \brief Attempt list initialization of a reference.
+static void TryReferenceListInitialization(Sema &S,
+                                           const InitializedEntity &Entity,
+                                           const InitializationKind &Kind,
+                                           InitListExpr *InitList,
+                                           InitializationSequence &Sequence)
+{
+  // First, catch C++03 where this isn't possible.
+  if (!S.getLangOpts().CPlusPlus0x) {
+    Sequence.SetFailed(InitializationSequence::FK_ReferenceBindingToInitList);
+    return;
+  }
+
+  QualType DestType = Entity.getType();
+  QualType cv1T1 = DestType->getAs<ReferenceType>()->getPointeeType();
+  Qualifiers T1Quals;
+  QualType T1 = S.Context.getUnqualifiedArrayType(cv1T1, T1Quals);
+
+  // Reference initialization via an initializer list works thus:
+  // If the initializer list consists of a single element that is
+  // reference-related to the referenced type, bind directly to that element
+  // (possibly creating temporaries).
+  // Otherwise, initialize a temporary with the initializer list and
+  // bind to that.
+  if (InitList->getNumInits() == 1) {
+    Expr *Initializer = InitList->getInit(0);
+    QualType cv2T2 = Initializer->getType();
+    Qualifiers T2Quals;
+    QualType T2 = S.Context.getUnqualifiedArrayType(cv2T2, T2Quals);
+
+    // If this fails, creating a temporary wouldn't work either.
+    if (ResolveOverloadedFunctionForReferenceBinding(S, Initializer, cv2T2, T2,
+                                                     T1, Sequence))
+      return;
+
+    SourceLocation DeclLoc = Initializer->getLocStart();
+    bool dummy1, dummy2, dummy3;
+    Sema::ReferenceCompareResult RefRelationship
+      = S.CompareReferenceRelationship(DeclLoc, cv1T1, cv2T2, dummy1,
+                                       dummy2, dummy3);
+    if (RefRelationship >= Sema::Ref_Related) {
+      // Try to bind the reference here.
+      TryReferenceInitializationCore(S, Entity, Kind, Initializer, cv1T1, T1,
+                                     T1Quals, cv2T2, T2, T2Quals, Sequence);
+      if (Sequence)
+        Sequence.RewrapReferenceInitList(cv1T1, InitList);
+      return;
+    }
+  }
+
+  // Not reference-related. Create a temporary and bind to that.
+  InitializedEntity TempEntity = InitializedEntity::InitializeTemporary(cv1T1);
+
+  TryListInitialization(S, TempEntity, Kind, InitList, Sequence);
+  if (Sequence) {
+    if (DestType->isRValueReferenceType() ||
+        (T1Quals.hasConst() && !T1Quals.hasVolatile()))
+      Sequence.AddReferenceBindingStep(cv1T1, /*bindingTemporary=*/true);
+    else
+      Sequence.SetFailed(
+          InitializationSequence::FK_NonConstLValueReferenceBindingToTemporary);
+  }
+}
+
+/// \brief Attempt list initialization (C++0x [dcl.init.list])
+static void TryListInitialization(Sema &S,
+                                  const InitializedEntity &Entity,
+                                  const InitializationKind &Kind,
+                                  InitListExpr *InitList,
+                                  InitializationSequence &Sequence) {
+  QualType DestType = Entity.getType();
+
+  // C++ doesn't allow scalar initialization with more than one argument.
+  // But C99 complex numbers are scalars and it makes sense there.
+  if (S.getLangOpts().CPlusPlus && DestType->isScalarType() &&
+      !DestType->isAnyComplexType() && InitList->getNumInits() > 1) {
+    Sequence.SetFailed(InitializationSequence::FK_TooManyInitsForScalar);
+    return;
+  }
+  if (DestType->isReferenceType()) {
+    TryReferenceListInitialization(S, Entity, Kind, InitList, Sequence);
+    return;
+  }
+  if (DestType->isRecordType()) {
+    if (S.RequireCompleteType(InitList->getLocStart(), DestType, S.PDiag())) {
+      Sequence.setIncompleteTypeFailure(DestType);
+      return;
+    }
+
+    if (!DestType->isAggregateType()) {
+      if (S.getLangOpts().CPlusPlus0x) {
+        Expr *Arg = InitList;
+        // A direct-initializer is not list-syntax, i.e. there's no special
+        // treatment of "A a({1, 2});".
+        TryConstructorInitialization(S, Entity, Kind, &Arg, 1, DestType, 
+                                     Sequence,
+                               Kind.getKind() != InitializationKind::IK_Direct);
+      } else
+        Sequence.SetFailed(
+            InitializationSequence::FK_InitListBadDestinationType);
+      return;
+    }
+  }
+
+  InitListChecker CheckInitList(S, Entity, InitList,
+          DestType, /*VerifyOnly=*/true,
+          Kind.getKind() != InitializationKind::IK_DirectList ||
+            !S.getLangOpts().CPlusPlus0x);
+  if (CheckInitList.HadError()) {
+    Sequence.SetFailed(InitializationSequence::FK_ListInitializationFailed);
+    return;
+  }
+
+  // Add the list initialization step with the built init list.
+  Sequence.AddListInitializationStep(DestType);
+}
+
+/// \brief Try a reference initialization that involves calling a conversion
+/// function.
+static OverloadingResult TryRefInitWithConversionFunction(Sema &S,
+                                             const InitializedEntity &Entity,
+                                             const InitializationKind &Kind,
+                                             Expr *Initializer,
+                                             bool AllowRValues,
+                                             InitializationSequence &Sequence) {
+  QualType DestType = Entity.getType();
+  QualType cv1T1 = DestType->getAs<ReferenceType>()->getPointeeType();
+  QualType T1 = cv1T1.getUnqualifiedType();
+  QualType cv2T2 = Initializer->getType();
+  QualType T2 = cv2T2.getUnqualifiedType();
+
+  bool DerivedToBase;
+  bool ObjCConversion;
+  bool ObjCLifetimeConversion;
+  assert(!S.CompareReferenceRelationship(Initializer->getLocStart(),
+                                         T1, T2, DerivedToBase,
+                                         ObjCConversion,
+                                         ObjCLifetimeConversion) &&
+         "Must have incompatible references when binding via conversion");
+  (void)DerivedToBase;
+  (void)ObjCConversion;
+  (void)ObjCLifetimeConversion;
+  
+  // Build the candidate set directly in the initialization sequence
+  // structure, so that it will persist if we fail.
+  OverloadCandidateSet &CandidateSet = Sequence.getFailedCandidateSet();
+  CandidateSet.clear();
+
+  // Determine whether we are allowed to call explicit constructors or
+  // explicit conversion operators.
+  bool AllowExplicit = Kind.AllowExplicit();
+  bool AllowExplicitConvs = Kind.allowExplicitConversionFunctions();
+  
+  const RecordType *T1RecordType = 0;
+  if (AllowRValues && (T1RecordType = T1->getAs<RecordType>()) &&
+      !S.RequireCompleteType(Kind.getLocation(), T1, 0)) {
+    // The type we're converting to is a class type. Enumerate its constructors
+    // to see if there is a suitable conversion.
+    CXXRecordDecl *T1RecordDecl = cast<CXXRecordDecl>(T1RecordType->getDecl());
+
+    DeclContext::lookup_iterator Con, ConEnd;
+    for (llvm::tie(Con, ConEnd) = S.LookupConstructors(T1RecordDecl);
+         Con != ConEnd; ++Con) {
+      NamedDecl *D = *Con;
+      DeclAccessPair FoundDecl = DeclAccessPair::make(D, D->getAccess());
+
+      // Find the constructor (which may be a template).
+      CXXConstructorDecl *Constructor = 0;
+      FunctionTemplateDecl *ConstructorTmpl = dyn_cast<FunctionTemplateDecl>(D);
+      if (ConstructorTmpl)
+        Constructor = cast<CXXConstructorDecl>(
+                                         ConstructorTmpl->getTemplatedDecl());
+      else
+        Constructor = cast<CXXConstructorDecl>(D);
+
+      if (!Constructor->isInvalidDecl() &&
+          Constructor->isConvertingConstructor(AllowExplicit)) {
+        if (ConstructorTmpl)
+          S.AddTemplateOverloadCandidate(ConstructorTmpl, FoundDecl,
+                                         /*ExplicitArgs*/ 0,
+                                         Initializer, CandidateSet,
+                                         /*SuppressUserConversions=*/true);
+        else
+          S.AddOverloadCandidate(Constructor, FoundDecl,
+                                 Initializer, CandidateSet,
+                                 /*SuppressUserConversions=*/true);
+      }
+    }
+  }
+  if (T1RecordType && T1RecordType->getDecl()->isInvalidDecl())
+    return OR_No_Viable_Function;
+
+  const RecordType *T2RecordType = 0;
+  if ((T2RecordType = T2->getAs<RecordType>()) &&
+      !S.RequireCompleteType(Kind.getLocation(), T2, 0)) {
+    // The type we're converting from is a class type, enumerate its conversion
+    // functions.
+    CXXRecordDecl *T2RecordDecl = cast<CXXRecordDecl>(T2RecordType->getDecl());
+
+    const UnresolvedSetImpl *Conversions
+      = T2RecordDecl->getVisibleConversionFunctions();
+    for (UnresolvedSetImpl::const_iterator I = Conversions->begin(),
+           E = Conversions->end(); I != E; ++I) {
+      NamedDecl *D = *I;
+      CXXRecordDecl *ActingDC = cast<CXXRecordDecl>(D->getDeclContext());
+      if (isa<UsingShadowDecl>(D))
+        D = cast<UsingShadowDecl>(D)->getTargetDecl();
+
+      FunctionTemplateDecl *ConvTemplate = dyn_cast<FunctionTemplateDecl>(D);
+      CXXConversionDecl *Conv;
+      if (ConvTemplate)
+        Conv = cast<CXXConversionDecl>(ConvTemplate->getTemplatedDecl());
+      else
+        Conv = cast<CXXConversionDecl>(D);
+
+      // If the conversion function doesn't return a reference type,
+      // it can't be considered for this conversion unless we're allowed to
+      // consider rvalues.
+      // FIXME: Do we need to make sure that we only consider conversion
+      // candidates with reference-compatible results? That might be needed to
+      // break recursion.
+      if ((AllowExplicitConvs || !Conv->isExplicit()) &&
+          (AllowRValues || Conv->getConversionType()->isLValueReferenceType())){
+        if (ConvTemplate)
+          S.AddTemplateConversionCandidate(ConvTemplate, I.getPair(),
+                                           ActingDC, Initializer,
+                                           DestType, CandidateSet);
+        else
+          S.AddConversionCandidate(Conv, I.getPair(), ActingDC,
+                                   Initializer, DestType, CandidateSet);
+      }
+    }
+  }
+  if (T2RecordType && T2RecordType->getDecl()->isInvalidDecl())
+    return OR_No_Viable_Function;
+
+  SourceLocation DeclLoc = Initializer->getLocStart();
+
+  // Perform overload resolution. If it fails, return the failed result.
+  OverloadCandidateSet::iterator Best;
+  if (OverloadingResult Result
+        = CandidateSet.BestViableFunction(S, DeclLoc, Best, true))
+    return Result;
+
+  FunctionDecl *Function = Best->Function;
+
+  // This is the overload that will actually be used for the initialization, so
+  // mark it as used.
+  S.MarkFunctionReferenced(DeclLoc, Function);
+
+  // Compute the returned type of the conversion.
+  if (isa<CXXConversionDecl>(Function))
+    T2 = Function->getResultType();
+  else
+    T2 = cv1T1;
+
+  // Add the user-defined conversion step.
+  bool HadMultipleCandidates = (CandidateSet.size() > 1);
+  Sequence.AddUserConversionStep(Function, Best->FoundDecl,
+                                 T2.getNonLValueExprType(S.Context),
+                                 HadMultipleCandidates);
+
+  // Determine whether we need to perform derived-to-base or
+  // cv-qualification adjustments.
+  ExprValueKind VK = VK_RValue;
+  if (T2->isLValueReferenceType())
+    VK = VK_LValue;
+  else if (const RValueReferenceType *RRef = T2->getAs<RValueReferenceType>())
+    VK = RRef->getPointeeType()->isFunctionType() ? VK_LValue : VK_XValue;
+
+  bool NewDerivedToBase = false;
+  bool NewObjCConversion = false;
+  bool NewObjCLifetimeConversion = false;
+  Sema::ReferenceCompareResult NewRefRelationship
+    = S.CompareReferenceRelationship(DeclLoc, T1,
+                                     T2.getNonLValueExprType(S.Context),
+                                     NewDerivedToBase, NewObjCConversion,
+                                     NewObjCLifetimeConversion);
+  if (NewRefRelationship == Sema::Ref_Incompatible) {
+    // If the type we've converted to is not reference-related to the
+    // type we're looking for, then there is another conversion step
+    // we need to perform to produce a temporary of the right type
+    // that we'll be binding to.
+    ImplicitConversionSequence ICS;
+    ICS.setStandard();
+    ICS.Standard = Best->FinalConversion;
+    T2 = ICS.Standard.getToType(2);
+    Sequence.AddConversionSequenceStep(ICS, T2);
+  } else if (NewDerivedToBase)
+    Sequence.AddDerivedToBaseCastStep(
+                                S.Context.getQualifiedType(T1,
+                                  T2.getNonReferenceType().getQualifiers()),
+                                      VK);
+  else if (NewObjCConversion)
+    Sequence.AddObjCObjectConversionStep(
+                                S.Context.getQualifiedType(T1,
+                                  T2.getNonReferenceType().getQualifiers()));
+
+  if (cv1T1.getQualifiers() != T2.getNonReferenceType().getQualifiers())
+    Sequence.AddQualificationConversionStep(cv1T1, VK);
+
+  Sequence.AddReferenceBindingStep(cv1T1, !T2->isReferenceType());
+  return OR_Success;
+}
+
+static void CheckCXX98CompatAccessibleCopy(Sema &S,
+                                           const InitializedEntity &Entity,
+                                           Expr *CurInitExpr);
+
+/// \brief Attempt reference initialization (C++0x [dcl.init.ref])
+static void TryReferenceInitialization(Sema &S,
+                                       const InitializedEntity &Entity,
+                                       const InitializationKind &Kind,
+                                       Expr *Initializer,
+                                       InitializationSequence &Sequence) {
+  QualType DestType = Entity.getType();
+  QualType cv1T1 = DestType->getAs<ReferenceType>()->getPointeeType();
+  Qualifiers T1Quals;
+  QualType T1 = S.Context.getUnqualifiedArrayType(cv1T1, T1Quals);
+  QualType cv2T2 = Initializer->getType();
+  Qualifiers T2Quals;
+  QualType T2 = S.Context.getUnqualifiedArrayType(cv2T2, T2Quals);
+
+  // If the initializer is the address of an overloaded function, try
+  // to resolve the overloaded function. If all goes well, T2 is the
+  // type of the resulting function.
+  if (ResolveOverloadedFunctionForReferenceBinding(S, Initializer, cv2T2, T2,
+                                                   T1, Sequence))
+    return;
+
+  // Delegate everything else to a subfunction.
+  TryReferenceInitializationCore(S, Entity, Kind, Initializer, cv1T1, T1,
+                                 T1Quals, cv2T2, T2, T2Quals, Sequence);
+}
+
+/// \brief Reference initialization without resolving overloaded functions.
+static void TryReferenceInitializationCore(Sema &S,
+                                           const InitializedEntity &Entity,
+                                           const InitializationKind &Kind,
+                                           Expr *Initializer,
+                                           QualType cv1T1, QualType T1,
+                                           Qualifiers T1Quals,
+                                           QualType cv2T2, QualType T2,
+                                           Qualifiers T2Quals,
+                                           InitializationSequence &Sequence) {
+  QualType DestType = Entity.getType();
+  SourceLocation DeclLoc = Initializer->getLocStart();
+  // Compute some basic properties of the types and the initializer.
+  bool isLValueRef = DestType->isLValueReferenceType();
+  bool isRValueRef = !isLValueRef;
+  bool DerivedToBase = false;
+  bool ObjCConversion = false;
+  bool ObjCLifetimeConversion = false;
+  Expr::Classification InitCategory = Initializer->Classify(S.Context);
+  Sema::ReferenceCompareResult RefRelationship
+    = S.CompareReferenceRelationship(DeclLoc, cv1T1, cv2T2, DerivedToBase,
+                                     ObjCConversion, ObjCLifetimeConversion);
+
+  // C++0x [dcl.init.ref]p5:
+  //   A reference to type "cv1 T1" is initialized by an expression of type
+  //   "cv2 T2" as follows:
+  //
+  //     - If the reference is an lvalue reference and the initializer
+  //       expression
+  // Note the analogous bullet points for rvlaue refs to functions. Because
+  // there are no function rvalues in C++, rvalue refs to functions are treated
+  // like lvalue refs.
+  OverloadingResult ConvOvlResult = OR_Success;
+  bool T1Function = T1->isFunctionType();
+  if (isLValueRef || T1Function) {
+    if (InitCategory.isLValue() &&
+        (RefRelationship >= Sema::Ref_Compatible_With_Added_Qualification ||
+         (Kind.isCStyleOrFunctionalCast() &&
+          RefRelationship == Sema::Ref_Related))) {
+      //   - is an lvalue (but is not a bit-field), and "cv1 T1" is
+      //     reference-compatible with "cv2 T2," or
+      //
+      // Per C++ [over.best.ics]p2, we don't diagnose whether the lvalue is a
+      // bit-field when we're determining whether the reference initialization
+      // can occur. However, we do pay attention to whether it is a bit-field
+      // to decide whether we're actually binding to a temporary created from
+      // the bit-field.
+      if (DerivedToBase)
+        Sequence.AddDerivedToBaseCastStep(
+                         S.Context.getQualifiedType(T1, T2Quals),
+                         VK_LValue);
+      else if (ObjCConversion)
+        Sequence.AddObjCObjectConversionStep(
+                                     S.Context.getQualifiedType(T1, T2Quals));
+
+      if (T1Quals != T2Quals)
+        Sequence.AddQualificationConversionStep(cv1T1, VK_LValue);
+      bool BindingTemporary = T1Quals.hasConst() && !T1Quals.hasVolatile() &&
+        (Initializer->getBitField() || Initializer->refersToVectorElement());
+      Sequence.AddReferenceBindingStep(cv1T1, BindingTemporary);
+      return;
+    }
+
+    //     - has a class type (i.e., T2 is a class type), where T1 is not
+    //       reference-related to T2, and can be implicitly converted to an
+    //       lvalue of type "cv3 T3," where "cv1 T1" is reference-compatible
+    //       with "cv3 T3" (this conversion is selected by enumerating the
+    //       applicable conversion functions (13.3.1.6) and choosing the best
+    //       one through overload resolution (13.3)),
+    // If we have an rvalue ref to function type here, the rhs must be
+    // an rvalue.
+    if (RefRelationship == Sema::Ref_Incompatible && T2->isRecordType() &&
+        (isLValueRef || InitCategory.isRValue())) {
+      ConvOvlResult = TryRefInitWithConversionFunction(S, Entity, Kind,
+                                                       Initializer,
+                                                   /*AllowRValues=*/isRValueRef,
+                                                       Sequence);
+      if (ConvOvlResult == OR_Success)
+        return;
+      if (ConvOvlResult != OR_No_Viable_Function) {
+        Sequence.SetOverloadFailure(
+                      InitializationSequence::FK_ReferenceInitOverloadFailed,
+                                    ConvOvlResult);
+      }
+    }
+  }
+
+  //     - Otherwise, the reference shall be an lvalue reference to a
+  //       non-volatile const type (i.e., cv1 shall be const), or the reference
+  //       shall be an rvalue reference.
+  if (isLValueRef && !(T1Quals.hasConst() && !T1Quals.hasVolatile())) {
+    if (S.Context.getCanonicalType(T2) == S.Context.OverloadTy)
+      Sequence.SetFailed(InitializationSequence::FK_AddressOfOverloadFailed);
+    else if (ConvOvlResult && !Sequence.getFailedCandidateSet().empty())
+      Sequence.SetOverloadFailure(
+                        InitializationSequence::FK_ReferenceInitOverloadFailed,
+                                  ConvOvlResult);
+    else
+      Sequence.SetFailed(InitCategory.isLValue()
+        ? (RefRelationship == Sema::Ref_Related
+             ? InitializationSequence::FK_ReferenceInitDropsQualifiers
+             : InitializationSequence::FK_NonConstLValueReferenceBindingToUnrelated)
+        : InitializationSequence::FK_NonConstLValueReferenceBindingToTemporary);
+
+    return;
+  }
+
+  //    - If the initializer expression
+  //      - is an xvalue, class prvalue, array prvalue, or function lvalue and
+  //        "cv1 T1" is reference-compatible with "cv2 T2"
+  // Note: functions are handled below.
+  if (!T1Function &&
+      (RefRelationship >= Sema::Ref_Compatible_With_Added_Qualification ||
+       (Kind.isCStyleOrFunctionalCast() &&
+        RefRelationship == Sema::Ref_Related)) &&
+      (InitCategory.isXValue() ||
+       (InitCategory.isPRValue() && T2->isRecordType()) ||
+       (InitCategory.isPRValue() && T2->isArrayType()))) {
+    ExprValueKind ValueKind = InitCategory.isXValue()? VK_XValue : VK_RValue;
+    if (InitCategory.isPRValue() && T2->isRecordType()) {
+      // The corresponding bullet in C++03 [dcl.init.ref]p5 gives the
+      // compiler the freedom to perform a copy here or bind to the
+      // object, while C++0x requires that we bind directly to the
+      // object. Hence, we always bind to the object without making an
+      // extra copy. However, in C++03 requires that we check for the
+      // presence of a suitable copy constructor:
+      //
+      //   The constructor that would be used to make the copy shall
+      //   be callable whether or not the copy is actually done.
+      if (!S.getLangOpts().CPlusPlus0x && !S.getLangOpts().MicrosoftExt)
+        Sequence.AddExtraneousCopyToTemporary(cv2T2);
+      else if (S.getLangOpts().CPlusPlus0x)
+        CheckCXX98CompatAccessibleCopy(S, Entity, Initializer);
+    }
+
+    if (DerivedToBase)
+      Sequence.AddDerivedToBaseCastStep(S.Context.getQualifiedType(T1, T2Quals),
+                                        ValueKind);
+    else if (ObjCConversion)
+      Sequence.AddObjCObjectConversionStep(
+                                       S.Context.getQualifiedType(T1, T2Quals));
+
+    if (T1Quals != T2Quals)
+      Sequence.AddQualificationConversionStep(cv1T1, ValueKind);
+    Sequence.AddReferenceBindingStep(cv1T1,
+                                 /*bindingTemporary=*/InitCategory.isPRValue());
+    return;
+  }
+
+  //       - has a class type (i.e., T2 is a class type), where T1 is not
+  //         reference-related to T2, and can be implicitly converted to an
+  //         xvalue, class prvalue, or function lvalue of type "cv3 T3",
+  //         where "cv1 T1" is reference-compatible with "cv3 T3",
+  if (T2->isRecordType()) {
+    if (RefRelationship == Sema::Ref_Incompatible) {
+      ConvOvlResult = TryRefInitWithConversionFunction(S, Entity,
+                                                       Kind, Initializer,
+                                                       /*AllowRValues=*/true,
+                                                       Sequence);
+      if (ConvOvlResult)
+        Sequence.SetOverloadFailure(
+                      InitializationSequence::FK_ReferenceInitOverloadFailed,
+                                    ConvOvlResult);
+
+      return;
+    }
+
+    Sequence.SetFailed(InitializationSequence::FK_ReferenceInitDropsQualifiers);
+    return;
+  }
+
+  //      - Otherwise, a temporary of type "cv1 T1" is created and initialized
+  //        from the initializer expression using the rules for a non-reference
+  //        copy initialization (8.5). The reference is then bound to the
+  //        temporary. [...]
+
+  // Determine whether we are allowed to call explicit constructors or
+  // explicit conversion operators.
+  bool AllowExplicit = Kind.AllowExplicit();
+
+  InitializedEntity TempEntity = InitializedEntity::InitializeTemporary(cv1T1);
+
+  ImplicitConversionSequence ICS
+    = S.TryImplicitConversion(Initializer, TempEntity.getType(),
+                              /*SuppressUserConversions*/ false,
+                              AllowExplicit,
+                              /*FIXME:InOverloadResolution=*/false,
+                              /*CStyle=*/Kind.isCStyleOrFunctionalCast(),
+                              /*AllowObjCWritebackConversion=*/false);
+  
+  if (ICS.isBad()) {
+    // FIXME: Use the conversion function set stored in ICS to turn
+    // this into an overloading ambiguity diagnostic. However, we need
+    // to keep that set as an OverloadCandidateSet rather than as some
+    // other kind of set.
+    if (ConvOvlResult && !Sequence.getFailedCandidateSet().empty())
+      Sequence.SetOverloadFailure(
+                        InitializationSequence::FK_ReferenceInitOverloadFailed,
+                                  ConvOvlResult);
+    else if (S.Context.getCanonicalType(T2) == S.Context.OverloadTy)
+      Sequence.SetFailed(InitializationSequence::FK_AddressOfOverloadFailed);
+    else
+      Sequence.SetFailed(InitializationSequence::FK_ReferenceInitFailed);
+    return;
+  } else {
+    Sequence.AddConversionSequenceStep(ICS, TempEntity.getType());
+  }
+
+  //        [...] If T1 is reference-related to T2, cv1 must be the
+  //        same cv-qualification as, or greater cv-qualification
+  //        than, cv2; otherwise, the program is ill-formed.
+  unsigned T1CVRQuals = T1Quals.getCVRQualifiers();
+  unsigned T2CVRQuals = T2Quals.getCVRQualifiers();
+  if (RefRelationship == Sema::Ref_Related &&
+      (T1CVRQuals | T2CVRQuals) != T1CVRQuals) {
+    Sequence.SetFailed(InitializationSequence::FK_ReferenceInitDropsQualifiers);
+    return;
+  }
+
+  //   [...] If T1 is reference-related to T2 and the reference is an rvalue
+  //   reference, the initializer expression shall not be an lvalue.
+  if (RefRelationship >= Sema::Ref_Related && !isLValueRef &&
+      InitCategory.isLValue()) {
+    Sequence.SetFailed(
+                    InitializationSequence::FK_RValueReferenceBindingToLValue);
+    return;
+  }
+
+  Sequence.AddReferenceBindingStep(cv1T1, /*bindingTemporary=*/true);
+  return;
+}
+
+/// \brief Attempt character array initialization from a string literal
+/// (C++ [dcl.init.string], C99 6.7.8).
+static void TryStringLiteralInitialization(Sema &S,
+                                           const InitializedEntity &Entity,
+                                           const InitializationKind &Kind,
+                                           Expr *Initializer,
+                                       InitializationSequence &Sequence) {
+  Sequence.AddStringInitStep(Entity.getType());
+}
+
+/// \brief Attempt value initialization (C++ [dcl.init]p7).
+static void TryValueInitialization(Sema &S,
+                                   const InitializedEntity &Entity,
+                                   const InitializationKind &Kind,
+                                   InitializationSequence &Sequence) {
+  // C++98 [dcl.init]p5, C++11 [dcl.init]p7:
+  //
+  //   To value-initialize an object of type T means:
+  QualType T = Entity.getType();
+
+  //     -- if T is an array type, then each element is value-initialized;
+  T = S.Context.getBaseElementType(T);
+
+  if (const RecordType *RT = T->getAs<RecordType>()) {
+    if (CXXRecordDecl *ClassDecl = dyn_cast<CXXRecordDecl>(RT->getDecl())) {
+      // C++98:
+      // -- if T is a class type (clause 9) with a user-declared
+      //    constructor (12.1), then the default constructor for T is
+      //    called (and the initialization is ill-formed if T has no
+      //    accessible default constructor);
+      if (!S.getLangOpts().CPlusPlus0x) {
+        if (ClassDecl->hasUserDeclaredConstructor())
+          // FIXME: we really want to refer to a single subobject of the array,
+          // but Entity doesn't have a way to capture that (yet).
+          return TryConstructorInitialization(S, Entity, Kind, 0, 0,
+                                              T, Sequence);
+      } else {
+        // C++11:
+        // -- if T is a class type (clause 9) with either no default constructor
+        //    (12.1 [class.ctor]) or a default constructor that is user-provided
+        //    or deleted, then the object is default-initialized;
+        CXXConstructorDecl *CD = S.LookupDefaultConstructor(ClassDecl);
+        if (!CD || !CD->getCanonicalDecl()->isDefaulted() || CD->isDeleted())
+          return TryConstructorInitialization(S, Entity, Kind, 0, 0,
+                                              T, Sequence);
+      }
+
+      // -- if T is a (possibly cv-qualified) non-union class type without a
+      //    user-provided or deleted default constructor, then the object is
+      //    zero-initialized and, if T has a non-trivial default constructor,
+      //    default-initialized;
+      if ((ClassDecl->getTagKind() == TTK_Class ||
+           ClassDecl->getTagKind() == TTK_Struct)) {
+        Sequence.AddZeroInitializationStep(Entity.getType());
+        return TryConstructorInitialization(S, Entity, Kind, 0, 0, T, Sequence);
+      }
+    }
+  }
+
+  Sequence.AddZeroInitializationStep(Entity.getType());
+}
+
+/// \brief Attempt default initialization (C++ [dcl.init]p6).
+static void TryDefaultInitialization(Sema &S,
+                                     const InitializedEntity &Entity,
+                                     const InitializationKind &Kind,
+                                     InitializationSequence &Sequence) {
+  assert(Kind.getKind() == InitializationKind::IK_Default);
+
+  // C++ [dcl.init]p6:
+  //   To default-initialize an object of type T means:
+  //     - if T is an array type, each element is default-initialized;
+  QualType DestType = S.Context.getBaseElementType(Entity.getType());
+         
+  //     - if T is a (possibly cv-qualified) class type (Clause 9), the default
+  //       constructor for T is called (and the initialization is ill-formed if
+  //       T has no accessible default constructor);
+  if (DestType->isRecordType() && S.getLangOpts().CPlusPlus) {
+    TryConstructorInitialization(S, Entity, Kind, 0, 0, DestType, Sequence);
+    return;
+  }
+
+  //     - otherwise, no initialization is performed.
+
+  //   If a program calls for the default initialization of an object of
+  //   a const-qualified type T, T shall be a class type with a user-provided
+  //   default constructor.
+  if (DestType.isConstQualified() && S.getLangOpts().CPlusPlus) {
+    Sequence.SetFailed(InitializationSequence::FK_DefaultInitOfConst);
+    return;
+  }
+
+  // If the destination type has a lifetime property, zero-initialize it.
+  if (DestType.getQualifiers().hasObjCLifetime()) {
+    Sequence.AddZeroInitializationStep(Entity.getType());
+    return;
+  }
+}
+
+/// \brief Attempt a user-defined conversion between two types (C++ [dcl.init]),
+/// which enumerates all conversion functions and performs overload resolution
+/// to select the best.
+static void TryUserDefinedConversion(Sema &S,
+                                     const InitializedEntity &Entity,
+                                     const InitializationKind &Kind,
+                                     Expr *Initializer,
+                                     InitializationSequence &Sequence) {
+  QualType DestType = Entity.getType();
+  assert(!DestType->isReferenceType() && "References are handled elsewhere");
+  QualType SourceType = Initializer->getType();
+  assert((DestType->isRecordType() || SourceType->isRecordType()) &&
+         "Must have a class type to perform a user-defined conversion");
+
+  // Build the candidate set directly in the initialization sequence
+  // structure, so that it will persist if we fail.
+  OverloadCandidateSet &CandidateSet = Sequence.getFailedCandidateSet();
+  CandidateSet.clear();
+
+  // Determine whether we are allowed to call explicit constructors or
+  // explicit conversion operators.
+  bool AllowExplicit = Kind.AllowExplicit();
+
+  if (const RecordType *DestRecordType = DestType->getAs<RecordType>()) {
+    // The type we're converting to is a class type. Enumerate its constructors
+    // to see if there is a suitable conversion.
+    CXXRecordDecl *DestRecordDecl
+      = cast<CXXRecordDecl>(DestRecordType->getDecl());
+
+    // Try to complete the type we're converting to.
+    if (!S.RequireCompleteType(Kind.getLocation(), DestType, 0)) {
+      DeclContext::lookup_iterator Con, ConEnd;
+      for (llvm::tie(Con, ConEnd) = S.LookupConstructors(DestRecordDecl);
+           Con != ConEnd; ++Con) {
+        NamedDecl *D = *Con;
+        DeclAccessPair FoundDecl = DeclAccessPair::make(D, D->getAccess());
+
+        // Find the constructor (which may be a template).
+        CXXConstructorDecl *Constructor = 0;
+        FunctionTemplateDecl *ConstructorTmpl
+          = dyn_cast<FunctionTemplateDecl>(D);
+        if (ConstructorTmpl)
+          Constructor = cast<CXXConstructorDecl>(
+                                           ConstructorTmpl->getTemplatedDecl());
+        else
+          Constructor = cast<CXXConstructorDecl>(D);
+
+        if (!Constructor->isInvalidDecl() &&
+            Constructor->isConvertingConstructor(AllowExplicit)) {
+          if (ConstructorTmpl)
+            S.AddTemplateOverloadCandidate(ConstructorTmpl, FoundDecl,
+                                           /*ExplicitArgs*/ 0,
+                                           Initializer, CandidateSet,
+                                           /*SuppressUserConversions=*/true);
+          else
+            S.AddOverloadCandidate(Constructor, FoundDecl,
+                                   Initializer, CandidateSet,
+                                   /*SuppressUserConversions=*/true);
+        }
+      }
+    }
+  }
+
+  SourceLocation DeclLoc = Initializer->getLocStart();
+
+  if (const RecordType *SourceRecordType = SourceType->getAs<RecordType>()) {
+    // The type we're converting from is a class type, enumerate its conversion
+    // functions.
+
+    // We can only enumerate the conversion functions for a complete type; if
+    // the type isn't complete, simply skip this step.
+    if (!S.RequireCompleteType(DeclLoc, SourceType, 0)) {
+      CXXRecordDecl *SourceRecordDecl
+        = cast<CXXRecordDecl>(SourceRecordType->getDecl());
+
+      const UnresolvedSetImpl *Conversions
+        = SourceRecordDecl->getVisibleConversionFunctions();
+      for (UnresolvedSetImpl::const_iterator I = Conversions->begin(),
+           E = Conversions->end();
+           I != E; ++I) {
+        NamedDecl *D = *I;
+        CXXRecordDecl *ActingDC = cast<CXXRecordDecl>(D->getDeclContext());
+        if (isa<UsingShadowDecl>(D))
+          D = cast<UsingShadowDecl>(D)->getTargetDecl();
+
+        FunctionTemplateDecl *ConvTemplate = dyn_cast<FunctionTemplateDecl>(D);
+        CXXConversionDecl *Conv;
+        if (ConvTemplate)
+          Conv = cast<CXXConversionDecl>(ConvTemplate->getTemplatedDecl());
+        else
+          Conv = cast<CXXConversionDecl>(D);
+
+        if (AllowExplicit || !Conv->isExplicit()) {
+          if (ConvTemplate)
+            S.AddTemplateConversionCandidate(ConvTemplate, I.getPair(),
+                                             ActingDC, Initializer, DestType,
+                                             CandidateSet);
+          else
+            S.AddConversionCandidate(Conv, I.getPair(), ActingDC,
+                                     Initializer, DestType, CandidateSet);
+        }
+      }
+    }
+  }
+
+  // Perform overload resolution. If it fails, return the failed result.
+  OverloadCandidateSet::iterator Best;
+  if (OverloadingResult Result
+        = CandidateSet.BestViableFunction(S, DeclLoc, Best, true)) {
+    Sequence.SetOverloadFailure(
+                        InitializationSequence::FK_UserConversionOverloadFailed,
+                                Result);
+    return;
+  }
+
+  FunctionDecl *Function = Best->Function;
+  S.MarkFunctionReferenced(DeclLoc, Function);
+  bool HadMultipleCandidates = (CandidateSet.size() > 1);
+
+  if (isa<CXXConstructorDecl>(Function)) {
+    // Add the user-defined conversion step. Any cv-qualification conversion is
+    // subsumed by the initialization. Per DR5, the created temporary is of the
+    // cv-unqualified type of the destination.
+    Sequence.AddUserConversionStep(Function, Best->FoundDecl,
+                                   DestType.getUnqualifiedType(),
+                                   HadMultipleCandidates);
+    return;
+  }
+
+  // Add the user-defined conversion step that calls the conversion function.
+  QualType ConvType = Function->getCallResultType();
+  if (ConvType->getAs<RecordType>()) {
+    // If we're converting to a class type, there may be an copy of
+    // the resulting temporary object (possible to create an object of
+    // a base class type). That copy is not a separate conversion, so
+    // we just make a note of the actual destination type (possibly a
+    // base class of the type returned by the conversion function) and
+    // let the user-defined conversion step handle the conversion.
+    Sequence.AddUserConversionStep(Function, Best->FoundDecl, DestType,
+                                   HadMultipleCandidates);
+    return;
+  }
+
+  Sequence.AddUserConversionStep(Function, Best->FoundDecl, ConvType,
+                                 HadMultipleCandidates);
+
+  // If the conversion following the call to the conversion function
+  // is interesting, add it as a separate step.
+  if (Best->FinalConversion.First || Best->FinalConversion.Second ||
+      Best->FinalConversion.Third) {
+    ImplicitConversionSequence ICS;
+    ICS.setStandard();
+    ICS.Standard = Best->FinalConversion;
+    Sequence.AddConversionSequenceStep(ICS, DestType);
+  }
+}
+
+/// The non-zero enum values here are indexes into diagnostic alternatives.
+enum InvalidICRKind { IIK_okay, IIK_nonlocal, IIK_nonscalar };
+
+/// Determines whether this expression is an acceptable ICR source.
+static InvalidICRKind isInvalidICRSource(ASTContext &C, Expr *e,
+                                         bool isAddressOf) {
+  // Skip parens.
+  e = e->IgnoreParens();
+
+  // Skip address-of nodes.
+  if (UnaryOperator *op = dyn_cast<UnaryOperator>(e)) {
+    if (op->getOpcode() == UO_AddrOf)
+      return isInvalidICRSource(C, op->getSubExpr(), /*addressof*/ true);
+
+  // Skip certain casts.
+  } else if (CastExpr *ce = dyn_cast<CastExpr>(e)) {
+    switch (ce->getCastKind()) {
+    case CK_Dependent:
+    case CK_BitCast:
+    case CK_LValueBitCast:
+    case CK_NoOp:
+      return isInvalidICRSource(C, ce->getSubExpr(), isAddressOf);
+
+    case CK_ArrayToPointerDecay:
+      return IIK_nonscalar;
+
+    case CK_NullToPointer:
+      return IIK_okay;
+
+    default:
+      break;
+    }
+
+  // If we have a declaration reference, it had better be a local variable.
+  } else if (isa<DeclRefExpr>(e)) {
+    if (!isAddressOf) return IIK_nonlocal;
+
+    VarDecl *var = dyn_cast<VarDecl>(cast<DeclRefExpr>(e)->getDecl());
+    if (!var) return IIK_nonlocal;
+
+    return (var->hasLocalStorage() ? IIK_okay : IIK_nonlocal);
+
+  // If we have a conditional operator, check both sides.
+  } else if (ConditionalOperator *cond = dyn_cast<ConditionalOperator>(e)) {
+    if (InvalidICRKind iik = isInvalidICRSource(C, cond->getLHS(), isAddressOf))
+      return iik;
+
+    return isInvalidICRSource(C, cond->getRHS(), isAddressOf);
+
+  // These are never scalar.
+  } else if (isa<ArraySubscriptExpr>(e)) {
+    return IIK_nonscalar;
+
+  // Otherwise, it needs to be a null pointer constant.
+  } else {
+    return (e->isNullPointerConstant(C, Expr::NPC_ValueDependentIsNull)
+            ? IIK_okay : IIK_nonlocal);
+  }
+
+  return IIK_nonlocal;
+}
+
+/// Check whether the given expression is a valid operand for an
+/// indirect copy/restore.
+static void checkIndirectCopyRestoreSource(Sema &S, Expr *src) {
+  assert(src->isRValue());
+
+  InvalidICRKind iik = isInvalidICRSource(S.Context, src, false);
+  if (iik == IIK_okay) return;
+
+  S.Diag(src->getExprLoc(), diag::err_arc_nonlocal_writeback)
+    << ((unsigned) iik - 1)  // shift index into diagnostic explanations
+    << src->getSourceRange();
+}
+
+/// \brief Determine whether we have compatible array types for the
+/// purposes of GNU by-copy array initialization.
+static bool hasCompatibleArrayTypes(ASTContext &Context,
+                                    const ArrayType *Dest, 
+                                    const ArrayType *Source) {
+  // If the source and destination array types are equivalent, we're
+  // done.
+  if (Context.hasSameType(QualType(Dest, 0), QualType(Source, 0)))
+    return true;
+
+  // Make sure that the element types are the same.
+  if (!Context.hasSameType(Dest->getElementType(), Source->getElementType()))
+    return false;
+
+  // The only mismatch we allow is when the destination is an
+  // incomplete array type and the source is a constant array type.
+  return Source->isConstantArrayType() && Dest->isIncompleteArrayType();
+}
+
+static bool tryObjCWritebackConversion(Sema &S,
+                                       InitializationSequence &Sequence,
+                                       const InitializedEntity &Entity,
+                                       Expr *Initializer) {
+  bool ArrayDecay = false;
+  QualType ArgType = Initializer->getType();
+  QualType ArgPointee;
+  if (const ArrayType *ArgArrayType = S.Context.getAsArrayType(ArgType)) {
+    ArrayDecay = true;
+    ArgPointee = ArgArrayType->getElementType();
+    ArgType = S.Context.getPointerType(ArgPointee);
+  }
+      
+  // Handle write-back conversion.
+  QualType ConvertedArgType;
+  if (!S.isObjCWritebackConversion(ArgType, Entity.getType(),
+                                   ConvertedArgType))
+    return false;
+
+  // We should copy unless we're passing to an argument explicitly
+  // marked 'out'.
+  bool ShouldCopy = true;
+  if (ParmVarDecl *param = cast_or_null<ParmVarDecl>(Entity.getDecl()))
+    ShouldCopy = (param->getObjCDeclQualifier() != ParmVarDecl::OBJC_TQ_Out);
+
+  // Do we need an lvalue conversion?
+  if (ArrayDecay || Initializer->isGLValue()) {
+    ImplicitConversionSequence ICS;
+    ICS.setStandard();
+    ICS.Standard.setAsIdentityConversion();
+
+    QualType ResultType;
+    if (ArrayDecay) {
+      ICS.Standard.First = ICK_Array_To_Pointer;
+      ResultType = S.Context.getPointerType(ArgPointee);
+    } else {
+      ICS.Standard.First = ICK_Lvalue_To_Rvalue;
+      ResultType = Initializer->getType().getNonLValueExprType(S.Context);
+    }
+          
+    Sequence.AddConversionSequenceStep(ICS, ResultType);
+  }
+        
+  Sequence.AddPassByIndirectCopyRestoreStep(Entity.getType(), ShouldCopy);
+  return true;
+}
+
+InitializationSequence::InitializationSequence(Sema &S,
+                                               const InitializedEntity &Entity,
+                                               const InitializationKind &Kind,
+                                               Expr **Args,
+                                               unsigned NumArgs)
+    : FailedCandidateSet(Kind.getLocation()) {
+  ASTContext &Context = S.Context;
+
+  // C++0x [dcl.init]p16:
+  //   The semantics of initializers are as follows. The destination type is
+  //   the type of the object or reference being initialized and the source
+  //   type is the type of the initializer expression. The source type is not
+  //   defined when the initializer is a braced-init-list or when it is a
+  //   parenthesized list of expressions.
+  QualType DestType = Entity.getType();
+
+  if (DestType->isDependentType() ||
+      Expr::hasAnyTypeDependentArguments(llvm::makeArrayRef(Args, NumArgs))) {
+    SequenceKind = DependentSequence;
+    return;
+  }
+
+  // Almost everything is a normal sequence.
+  setSequenceKind(NormalSequence);
+
+  for (unsigned I = 0; I != NumArgs; ++I)
+    if (Args[I]->getType()->isNonOverloadPlaceholderType()) {
+      // FIXME: should we be doing this here?
+      ExprResult result = S.CheckPlaceholderExpr(Args[I]);
+      if (result.isInvalid()) {
+        SetFailed(FK_PlaceholderType);
+        return;
+      }
+      Args[I] = result.take();
+    }
+
+
+  QualType SourceType;
+  Expr *Initializer = 0;
+  if (NumArgs == 1) {
+    Initializer = Args[0];
+    if (!isa<InitListExpr>(Initializer))
+      SourceType = Initializer->getType();
+  }
+
+  //     - If the initializer is a (non-parenthesized) braced-init-list, the
+  //       object is list-initialized (8.5.4).
+  if (Kind.getKind() != InitializationKind::IK_Direct) {
+    if (InitListExpr *InitList = dyn_cast_or_null<InitListExpr>(Initializer)) {
+      TryListInitialization(S, Entity, Kind, InitList, *this);
+      return;
+    }
+  }
+
+  //     - If the destination type is a reference type, see 8.5.3.
+  if (DestType->isReferenceType()) {
+    // C++0x [dcl.init.ref]p1:
+    //   A variable declared to be a T& or T&&, that is, "reference to type T"
+    //   (8.3.2), shall be initialized by an object, or function, of type T or
+    //   by an object that can be converted into a T.
+    // (Therefore, multiple arguments are not permitted.)
+    if (NumArgs != 1)
+      SetFailed(FK_TooManyInitsForReference);
+    else
+      TryReferenceInitialization(S, Entity, Kind, Args[0], *this);
+    return;
+  }
+
+  //     - If the initializer is (), the object is value-initialized.
+  if (Kind.getKind() == InitializationKind::IK_Value ||
+      (Kind.getKind() == InitializationKind::IK_Direct && NumArgs == 0)) {
+    TryValueInitialization(S, Entity, Kind, *this);
+    return;
+  }
+
+  // Handle default initialization.
+  if (Kind.getKind() == InitializationKind::IK_Default) {
+    TryDefaultInitialization(S, Entity, Kind, *this);
+    return;
+  }
+
+  //     - If the destination type is an array of characters, an array of
+  //       char16_t, an array of char32_t, or an array of wchar_t, and the
+  //       initializer is a string literal, see 8.5.2.
+  //     - Otherwise, if the destination type is an array, the program is
+  //       ill-formed.
+  if (const ArrayType *DestAT = Context.getAsArrayType(DestType)) {
+    if (Initializer && isa<VariableArrayType>(DestAT)) {
+      SetFailed(FK_VariableLengthArrayHasInitializer);
+      return;
+    }
+
+    if (Initializer && IsStringInit(Initializer, DestAT, Context)) {
+      TryStringLiteralInitialization(S, Entity, Kind, Initializer, *this);
+      return;
+    }
+
+    // Note: as an GNU C extension, we allow initialization of an
+    // array from a compound literal that creates an array of the same
+    // type, so long as the initializer has no side effects.
+    if (!S.getLangOpts().CPlusPlus && Initializer &&
+        isa<CompoundLiteralExpr>(Initializer->IgnoreParens()) &&
+        Initializer->getType()->isArrayType()) {
+      const ArrayType *SourceAT
+        = Context.getAsArrayType(Initializer->getType());
+      if (!hasCompatibleArrayTypes(S.Context, DestAT, SourceAT))
+        SetFailed(FK_ArrayTypeMismatch);
+      else if (Initializer->HasSideEffects(S.Context))
+        SetFailed(FK_NonConstantArrayInit);
+      else {
+        AddArrayInitStep(DestType);
+      }
+    }
+    // Note: as a GNU C++ extension, we allow initialization of a
+    // class member from a parenthesized initializer list.
+    else if (S.getLangOpts().CPlusPlus &&
+             Entity.getKind() == InitializedEntity::EK_Member &&
+             Initializer && isa<InitListExpr>(Initializer)) {
+      TryListInitialization(S, Entity, Kind, cast<InitListExpr>(Initializer),
+                            *this);
+      AddParenthesizedArrayInitStep(DestType);
+    } else if (DestAT->getElementType()->isAnyCharacterType())
+      SetFailed(FK_ArrayNeedsInitListOrStringLiteral);
+    else
+      SetFailed(FK_ArrayNeedsInitList);
+
+    return;
+  }
+
+  // Determine whether we should consider writeback conversions for 
+  // Objective-C ARC.
+  bool allowObjCWritebackConversion = S.getLangOpts().ObjCAutoRefCount &&
+    Entity.getKind() == InitializedEntity::EK_Parameter;
+
+  // We're at the end of the line for C: it's either a write-back conversion
+  // or it's a C assignment. There's no need to check anything else.
+  if (!S.getLangOpts().CPlusPlus) {
+    // If allowed, check whether this is an Objective-C writeback conversion.
+    if (allowObjCWritebackConversion &&
+        tryObjCWritebackConversion(S, *this, Entity, Initializer)) {
+      return;
+    }
+    
+    // Handle initialization in C
+    AddCAssignmentStep(DestType);
+    MaybeProduceObjCObject(S, *this, Entity);
+    return;
+  }
+
+  assert(S.getLangOpts().CPlusPlus);
+      
+  //     - If the destination type is a (possibly cv-qualified) class type:
+  if (DestType->isRecordType()) {
+    //     - If the initialization is direct-initialization, or if it is
+    //       copy-initialization where the cv-unqualified version of the
+    //       source type is the same class as, or a derived class of, the
+    //       class of the destination, constructors are considered. [...]
+    if (Kind.getKind() == InitializationKind::IK_Direct ||
+        (Kind.getKind() == InitializationKind::IK_Copy &&
+         (Context.hasSameUnqualifiedType(SourceType, DestType) ||
+          S.IsDerivedFrom(SourceType, DestType))))
+      TryConstructorInitialization(S, Entity, Kind, Args, NumArgs,
+                                   Entity.getType(), *this);
+    //     - Otherwise (i.e., for the remaining copy-initialization cases),
+    //       user-defined conversion sequences that can convert from the source
+    //       type to the destination type or (when a conversion function is
+    //       used) to a derived class thereof are enumerated as described in
+    //       13.3.1.4, and the best one is chosen through overload resolution
+    //       (13.3).
+    else
+      TryUserDefinedConversion(S, Entity, Kind, Initializer, *this);
+    return;
+  }
+
+  if (NumArgs > 1) {
+    SetFailed(FK_TooManyInitsForScalar);
+    return;
+  }
+  assert(NumArgs == 1 && "Zero-argument case handled above");
+
+  //    - Otherwise, if the source type is a (possibly cv-qualified) class
+  //      type, conversion functions are considered.
+  if (!SourceType.isNull() && SourceType->isRecordType()) {
+    TryUserDefinedConversion(S, Entity, Kind, Initializer, *this);
+    MaybeProduceObjCObject(S, *this, Entity);
+    return;
+  }
+
+  //    - Otherwise, the initial value of the object being initialized is the
+  //      (possibly converted) value of the initializer expression. Standard
+  //      conversions (Clause 4) will be used, if necessary, to convert the
+  //      initializer expression to the cv-unqualified version of the
+  //      destination type; no user-defined conversions are considered.
+      
+  ImplicitConversionSequence ICS
+    = S.TryImplicitConversion(Initializer, Entity.getType(),
+                              /*SuppressUserConversions*/true,
+                              /*AllowExplicitConversions*/ false,
+                              /*InOverloadResolution*/ false,
+                              /*CStyle=*/Kind.isCStyleOrFunctionalCast(),
+                              allowObjCWritebackConversion);
+      
+  if (ICS.isStandard() && 
+      ICS.Standard.Second == ICK_Writeback_Conversion) {
+    // Objective-C ARC writeback conversion.
+    
+    // We should copy unless we're passing to an argument explicitly
+    // marked 'out'.
+    bool ShouldCopy = true;
+    if (ParmVarDecl *Param = cast_or_null<ParmVarDecl>(Entity.getDecl()))
+      ShouldCopy = (Param->getObjCDeclQualifier() != ParmVarDecl::OBJC_TQ_Out);
+    
+    // If there was an lvalue adjustment, add it as a separate conversion.
+    if (ICS.Standard.First == ICK_Array_To_Pointer ||
+        ICS.Standard.First == ICK_Lvalue_To_Rvalue) {
+      ImplicitConversionSequence LvalueICS;
+      LvalueICS.setStandard();
+      LvalueICS.Standard.setAsIdentityConversion();
+      LvalueICS.Standard.setAllToTypes(ICS.Standard.getToType(0));
+      LvalueICS.Standard.First = ICS.Standard.First;
+      AddConversionSequenceStep(LvalueICS, ICS.Standard.getToType(0));
+    }
+    
+    AddPassByIndirectCopyRestoreStep(Entity.getType(), ShouldCopy);
+  } else if (ICS.isBad()) {
+    DeclAccessPair dap;
+    if (Initializer->getType() == Context.OverloadTy && 
+          !S.ResolveAddressOfOverloadedFunction(Initializer
+                      , DestType, false, dap))
+      SetFailed(InitializationSequence::FK_AddressOfOverloadFailed);
+    else
+      SetFailed(InitializationSequence::FK_ConversionFailed);
+  } else {
+    AddConversionSequenceStep(ICS, Entity.getType());
+
+    MaybeProduceObjCObject(S, *this, Entity);
+  }
+}
+
+InitializationSequence::~InitializationSequence() {
+  for (SmallVectorImpl<Step>::iterator Step = Steps.begin(),
+                                          StepEnd = Steps.end();
+       Step != StepEnd; ++Step)
+    Step->Destroy();
+}
+
+//===----------------------------------------------------------------------===//
+// Perform initialization
+//===----------------------------------------------------------------------===//
+static Sema::AssignmentAction
+getAssignmentAction(const InitializedEntity &Entity) {
+  switch(Entity.getKind()) {
+  case InitializedEntity::EK_Variable:
+  case InitializedEntity::EK_New:
+  case InitializedEntity::EK_Exception:
+  case InitializedEntity::EK_Base:
+  case InitializedEntity::EK_Delegating:
+    return Sema::AA_Initializing;
+
+  case InitializedEntity::EK_Parameter:
+    if (Entity.getDecl() &&
+        isa<ObjCMethodDecl>(Entity.getDecl()->getDeclContext()))
+      return Sema::AA_Sending;
+
+    return Sema::AA_Passing;
+
+  case InitializedEntity::EK_Result:
+    return Sema::AA_Returning;
+
+  case InitializedEntity::EK_Temporary:
+    // FIXME: Can we tell apart casting vs. converting?
+    return Sema::AA_Casting;
+
+  case InitializedEntity::EK_Member:
+  case InitializedEntity::EK_ArrayElement:
+  case InitializedEntity::EK_VectorElement:
+  case InitializedEntity::EK_ComplexElement:
+  case InitializedEntity::EK_BlockElement:
+  case InitializedEntity::EK_LambdaCapture:
+    return Sema::AA_Initializing;
+  }
+
+  llvm_unreachable("Invalid EntityKind!");
+}
+
+/// \brief Whether we should binding a created object as a temporary when
+/// initializing the given entity.
+static bool shouldBindAsTemporary(const InitializedEntity &Entity) {
+  switch (Entity.getKind()) {
+  case InitializedEntity::EK_ArrayElement:
+  case InitializedEntity::EK_Member:
+  case InitializedEntity::EK_Result:
+  case InitializedEntity::EK_New:
+  case InitializedEntity::EK_Variable:
+  case InitializedEntity::EK_Base:
+  case InitializedEntity::EK_Delegating:
+  case InitializedEntity::EK_VectorElement:
+  case InitializedEntity::EK_ComplexElement:
+  case InitializedEntity::EK_Exception:
+  case InitializedEntity::EK_BlockElement:
+  case InitializedEntity::EK_LambdaCapture:
+    return false;
+
+  case InitializedEntity::EK_Parameter:
+  case InitializedEntity::EK_Temporary:
+    return true;
+  }
+
+  llvm_unreachable("missed an InitializedEntity kind?");
+}
+
+/// \brief Whether the given entity, when initialized with an object
+/// created for that initialization, requires destruction.
+static bool shouldDestroyTemporary(const InitializedEntity &Entity) {
+  switch (Entity.getKind()) {
+    case InitializedEntity::EK_Member:
+    case InitializedEntity::EK_Result:
+    case InitializedEntity::EK_New:
+    case InitializedEntity::EK_Base:
+    case InitializedEntity::EK_Delegating:
+    case InitializedEntity::EK_VectorElement:
+    case InitializedEntity::EK_ComplexElement:
+    case InitializedEntity::EK_BlockElement:
+    case InitializedEntity::EK_LambdaCapture:
+      return false;
+
+    case InitializedEntity::EK_Variable:
+    case InitializedEntity::EK_Parameter:
+    case InitializedEntity::EK_Temporary:
+    case InitializedEntity::EK_ArrayElement:
+    case InitializedEntity::EK_Exception:
+      return true;
+  }
+
+  llvm_unreachable("missed an InitializedEntity kind?");
+}
+
+/// \brief Look for copy and move constructors and constructor templates, for
+/// copying an object via direct-initialization (per C++11 [dcl.init]p16).
+static void LookupCopyAndMoveConstructors(Sema &S,
+                                          OverloadCandidateSet &CandidateSet,
+                                          CXXRecordDecl *Class,
+                                          Expr *CurInitExpr) {
+  DeclContext::lookup_iterator Con, ConEnd;
+  for (llvm::tie(Con, ConEnd) = S.LookupConstructors(Class);
+       Con != ConEnd; ++Con) {
+    CXXConstructorDecl *Constructor = 0;
+
+    if ((Constructor = dyn_cast<CXXConstructorDecl>(*Con))) {
+      // Handle copy/moveconstructors, only.
+      if (!Constructor || Constructor->isInvalidDecl() ||
+          !Constructor->isCopyOrMoveConstructor() ||
+          !Constructor->isConvertingConstructor(/*AllowExplicit=*/true))
+        continue;
+
+      DeclAccessPair FoundDecl
+        = DeclAccessPair::make(Constructor, Constructor->getAccess());
+      S.AddOverloadCandidate(Constructor, FoundDecl,
+                             CurInitExpr, CandidateSet);
+      continue;
+    }
+
+    // Handle constructor templates.
+    FunctionTemplateDecl *ConstructorTmpl = cast<FunctionTemplateDecl>(*Con);
+    if (ConstructorTmpl->isInvalidDecl())
+      continue;
+
+    Constructor = cast<CXXConstructorDecl>(
+                                         ConstructorTmpl->getTemplatedDecl());
+    if (!Constructor->isConvertingConstructor(/*AllowExplicit=*/true))
+      continue;
+
+    // FIXME: Do we need to limit this to copy-constructor-like
+    // candidates?
+    DeclAccessPair FoundDecl
+      = DeclAccessPair::make(ConstructorTmpl, ConstructorTmpl->getAccess());
+    S.AddTemplateOverloadCandidate(ConstructorTmpl, FoundDecl, 0,
+                                   CurInitExpr, CandidateSet, true);
+  }
+}
+
+/// \brief Get the location at which initialization diagnostics should appear.
+static SourceLocation getInitializationLoc(const InitializedEntity &Entity,
+                                           Expr *Initializer) {
+  switch (Entity.getKind()) {
+  case InitializedEntity::EK_Result:
+    return Entity.getReturnLoc();
+
+  case InitializedEntity::EK_Exception:
+    return Entity.getThrowLoc();
+
+  case InitializedEntity::EK_Variable:
+    return Entity.getDecl()->getLocation();
+
+  case InitializedEntity::EK_LambdaCapture:
+    return Entity.getCaptureLoc();
+      
+  case InitializedEntity::EK_ArrayElement:
+  case InitializedEntity::EK_Member:
+  case InitializedEntity::EK_Parameter:
+  case InitializedEntity::EK_Temporary:
+  case InitializedEntity::EK_New:
+  case InitializedEntity::EK_Base:
+  case InitializedEntity::EK_Delegating:
+  case InitializedEntity::EK_VectorElement:
+  case InitializedEntity::EK_ComplexElement:
+  case InitializedEntity::EK_BlockElement:
+    return Initializer->getLocStart();
+  }
+  llvm_unreachable("missed an InitializedEntity kind?");
+}
+
+/// \brief Make a (potentially elidable) temporary copy of the object
+/// provided by the given initializer by calling the appropriate copy
+/// constructor.
+///
+/// \param S The Sema object used for type-checking.
+///
+/// \param T The type of the temporary object, which must either be
+/// the type of the initializer expression or a superclass thereof.
+///
+/// \param Enter The entity being initialized.
+///
+/// \param CurInit The initializer expression.
+///
+/// \param IsExtraneousCopy Whether this is an "extraneous" copy that
+/// is permitted in C++03 (but not C++0x) when binding a reference to
+/// an rvalue.
+///
+/// \returns An expression that copies the initializer expression into
+/// a temporary object, or an error expression if a copy could not be
+/// created.
+static ExprResult CopyObject(Sema &S,
+                             QualType T,
+                             const InitializedEntity &Entity,
+                             ExprResult CurInit,
+                             bool IsExtraneousCopy) {
+  // Determine which class type we're copying to.
+  Expr *CurInitExpr = (Expr *)CurInit.get();
+  CXXRecordDecl *Class = 0;
+  if (const RecordType *Record = T->getAs<RecordType>())
+    Class = cast<CXXRecordDecl>(Record->getDecl());
+  if (!Class)
+    return move(CurInit);
+
+  // C++0x [class.copy]p32:
+  //   When certain criteria are met, an implementation is allowed to
+  //   omit the copy/move construction of a class object, even if the
+  //   copy/move constructor and/or destructor for the object have
+  //   side effects. [...]
+  //     - when a temporary class object that has not been bound to a
+  //       reference (12.2) would be copied/moved to a class object
+  //       with the same cv-unqualified type, the copy/move operation
+  //       can be omitted by constructing the temporary object
+  //       directly into the target of the omitted copy/move
+  //
+  // Note that the other three bullets are handled elsewhere. Copy
+  // elision for return statements and throw expressions are handled as part
+  // of constructor initialization, while copy elision for exception handlers
+  // is handled by the run-time.
+  bool Elidable = CurInitExpr->isTemporaryObject(S.Context, Class);
+  SourceLocation Loc = getInitializationLoc(Entity, CurInit.get());
+
+  // Make sure that the type we are copying is complete.
+  if (S.RequireCompleteType(Loc, T, S.PDiag(diag::err_temp_copy_incomplete)))
+    return move(CurInit);
+
+  // Perform overload resolution using the class's copy/move constructors.
+  // Only consider constructors and constructor templates. Per
+  // C++0x [dcl.init]p16, second bullet to class types, this initialization
+  // is direct-initialization.
+  OverloadCandidateSet CandidateSet(Loc);
+  LookupCopyAndMoveConstructors(S, CandidateSet, Class, CurInitExpr);
+
+  bool HadMultipleCandidates = (CandidateSet.size() > 1);
+
+  OverloadCandidateSet::iterator Best;
+  switch (CandidateSet.BestViableFunction(S, Loc, Best)) {
+  case OR_Success:
+    break;
+
+  case OR_No_Viable_Function:
+    S.Diag(Loc, IsExtraneousCopy && !S.isSFINAEContext()
+           ? diag::ext_rvalue_to_reference_temp_copy_no_viable
+           : diag::err_temp_copy_no_viable)
+      << (int)Entity.getKind() << CurInitExpr->getType()
+      << CurInitExpr->getSourceRange();
+    CandidateSet.NoteCandidates(S, OCD_AllCandidates, CurInitExpr);
+    if (!IsExtraneousCopy || S.isSFINAEContext())
+      return ExprError();
+    return move(CurInit);
+
+  case OR_Ambiguous:
+    S.Diag(Loc, diag::err_temp_copy_ambiguous)
+      << (int)Entity.getKind() << CurInitExpr->getType()
+      << CurInitExpr->getSourceRange();
+    CandidateSet.NoteCandidates(S, OCD_ViableCandidates, CurInitExpr);
+    return ExprError();
+
+  case OR_Deleted:
+    S.Diag(Loc, diag::err_temp_copy_deleted)
+      << (int)Entity.getKind() << CurInitExpr->getType()
+      << CurInitExpr->getSourceRange();
+    S.NoteDeletedFunction(Best->Function);
+    return ExprError();
+  }
+
+  CXXConstructorDecl *Constructor = cast<CXXConstructorDecl>(Best->Function);
+  ASTOwningVector<Expr*> ConstructorArgs(S);
+  CurInit.release(); // Ownership transferred into MultiExprArg, below.
+
+  S.CheckConstructorAccess(Loc, Constructor, Entity,
+                           Best->FoundDecl.getAccess(), IsExtraneousCopy);
+
+  if (IsExtraneousCopy) {
+    // If this is a totally extraneous copy for C++03 reference
+    // binding purposes, just return the original initialization
+    // expression. We don't generate an (elided) copy operation here
+    // because doing so would require us to pass down a flag to avoid
+    // infinite recursion, where each step adds another extraneous,
+    // elidable copy.
+
+    // Instantiate the default arguments of any extra parameters in
+    // the selected copy constructor, as if we were going to create a
+    // proper call to the copy constructor.
+    for (unsigned I = 1, N = Constructor->getNumParams(); I != N; ++I) {
+      ParmVarDecl *Parm = Constructor->getParamDecl(I);
+      if (S.RequireCompleteType(Loc, Parm->getType(),
+                                S.PDiag(diag::err_call_incomplete_argument)))
+        break;
+
+      // Build the default argument expression; we don't actually care
+      // if this succeeds or not, because this routine will complain
+      // if there was a problem.
+      S.BuildCXXDefaultArgExpr(Loc, Constructor, Parm);
+    }
+
+    return S.Owned(CurInitExpr);
+  }
+
+  S.MarkFunctionReferenced(Loc, Constructor);
+
+  // Determine the arguments required to actually perform the
+  // constructor call (we might have derived-to-base conversions, or
+  // the copy constructor may have default arguments).
+  if (S.CompleteConstructorCall(Constructor, MultiExprArg(&CurInitExpr, 1),
+                                Loc, ConstructorArgs))
+    return ExprError();
+
+  // Actually perform the constructor call.
+  CurInit = S.BuildCXXConstructExpr(Loc, T, Constructor, Elidable,
+                                    move_arg(ConstructorArgs),
+                                    HadMultipleCandidates,
+                                    /*ZeroInit*/ false,
+                                    CXXConstructExpr::CK_Complete,
+                                    SourceRange());
+
+  // If we're supposed to bind temporaries, do so.
+  if (!CurInit.isInvalid() && shouldBindAsTemporary(Entity))
+    CurInit = S.MaybeBindToTemporary(CurInit.takeAs<Expr>());
+  return move(CurInit);
+}
+
+/// \brief Check whether elidable copy construction for binding a reference to
+/// a temporary would have succeeded if we were building in C++98 mode, for
+/// -Wc++98-compat.
+static void CheckCXX98CompatAccessibleCopy(Sema &S,
+                                           const InitializedEntity &Entity,
+                                           Expr *CurInitExpr) {
+  assert(S.getLangOpts().CPlusPlus0x);
+
+  const RecordType *Record = CurInitExpr->getType()->getAs<RecordType>();
+  if (!Record)
+    return;
+
+  SourceLocation Loc = getInitializationLoc(Entity, CurInitExpr);
+  if (S.Diags.getDiagnosticLevel(diag::warn_cxx98_compat_temp_copy, Loc)
+        == DiagnosticsEngine::Ignored)
+    return;
+
+  // Find constructors which would have been considered.
+  OverloadCandidateSet CandidateSet(Loc);
+  LookupCopyAndMoveConstructors(
+      S, CandidateSet, cast<CXXRecordDecl>(Record->getDecl()), CurInitExpr);
+
+  // Perform overload resolution.
+  OverloadCandidateSet::iterator Best;
+  OverloadingResult OR = CandidateSet.BestViableFunction(S, Loc, Best);
+
+  PartialDiagnostic Diag = S.PDiag(diag::warn_cxx98_compat_temp_copy)
+    << OR << (int)Entity.getKind() << CurInitExpr->getType()
+    << CurInitExpr->getSourceRange();
+
+  switch (OR) {
+  case OR_Success:
+    S.CheckConstructorAccess(Loc, cast<CXXConstructorDecl>(Best->Function),
+                             Entity, Best->FoundDecl.getAccess(), Diag);
+    // FIXME: Check default arguments as far as that's possible.
+    break;
+
+  case OR_No_Viable_Function:
+    S.Diag(Loc, Diag);
+    CandidateSet.NoteCandidates(S, OCD_AllCandidates, CurInitExpr);
+    break;
+
+  case OR_Ambiguous:
+    S.Diag(Loc, Diag);
+    CandidateSet.NoteCandidates(S, OCD_ViableCandidates, CurInitExpr);
+    break;
+
+  case OR_Deleted:
+    S.Diag(Loc, Diag);
+    S.NoteDeletedFunction(Best->Function);
+    break;
+  }
+}
+
+void InitializationSequence::PrintInitLocationNote(Sema &S,
+                                              const InitializedEntity &Entity) {
+  if (Entity.getKind() == InitializedEntity::EK_Parameter && Entity.getDecl()) {
+    if (Entity.getDecl()->getLocation().isInvalid())
+      return;
+
+    if (Entity.getDecl()->getDeclName())
+      S.Diag(Entity.getDecl()->getLocation(), diag::note_parameter_named_here)
+        << Entity.getDecl()->getDeclName();
+    else
+      S.Diag(Entity.getDecl()->getLocation(), diag::note_parameter_here);
+  }
+}
+
+static bool isReferenceBinding(const InitializationSequence::Step &s) {
+  return s.Kind == InitializationSequence::SK_BindReference ||
+         s.Kind == InitializationSequence::SK_BindReferenceToTemporary;
+}
+
+static ExprResult
+PerformConstructorInitialization(Sema &S,
+                                 const InitializedEntity &Entity,
+                                 const InitializationKind &Kind,
+                                 MultiExprArg Args,
+                                 const InitializationSequence::Step& Step,
+                                 bool &ConstructorInitRequiresZeroInit) {
+  unsigned NumArgs = Args.size();
+  CXXConstructorDecl *Constructor
+    = cast<CXXConstructorDecl>(Step.Function.Function);
+  bool HadMultipleCandidates = Step.Function.HadMultipleCandidates;
+
+  // Build a call to the selected constructor.
+  ASTOwningVector<Expr*> ConstructorArgs(S);
+  SourceLocation Loc = (Kind.isCopyInit() && Kind.getEqualLoc().isValid())
+                         ? Kind.getEqualLoc()
+                         : Kind.getLocation();
+
+  if (Kind.getKind() == InitializationKind::IK_Default) {
+    // Force even a trivial, implicit default constructor to be
+    // semantically checked. We do this explicitly because we don't build
+    // the definition for completely trivial constructors.
+    assert(Constructor->getParent() && "No parent class for constructor.");
+    if (Constructor->isDefaulted() && Constructor->isDefaultConstructor() &&
+        Constructor->isTrivial() && !Constructor->isUsed(false))
+      S.DefineImplicitDefaultConstructor(Loc, Constructor);
+  }
+
+  ExprResult CurInit = S.Owned((Expr *)0);
+
+  // C++ [over.match.copy]p1:
+  //   - When initializing a temporary to be bound to the first parameter 
+  //     of a constructor that takes a reference to possibly cv-qualified 
+  //     T as its first argument, called with a single argument in the 
+  //     context of direct-initialization, explicit conversion functions
+  //     are also considered.
+  bool AllowExplicitConv = Kind.AllowExplicit() && !Kind.isCopyInit() &&
+                           Args.size() == 1 && 
+                           Constructor->isCopyOrMoveConstructor();
+
+  // Determine the arguments required to actually perform the constructor
+  // call.
+  if (S.CompleteConstructorCall(Constructor, move(Args),
+                                Loc, ConstructorArgs,
+                                AllowExplicitConv))
+    return ExprError();
+
+
+  if (Entity.getKind() == InitializedEntity::EK_Temporary &&
+      (Kind.getKind() == InitializationKind::IK_DirectList ||
+       (NumArgs != 1 && // FIXME: Hack to work around cast weirdness
+        (Kind.getKind() == InitializationKind::IK_Direct ||
+         Kind.getKind() == InitializationKind::IK_Value)))) {
+    // An explicitly-constructed temporary, e.g., X(1, 2).
+    unsigned NumExprs = ConstructorArgs.size();
+    Expr **Exprs = (Expr **)ConstructorArgs.take();
+    S.MarkFunctionReferenced(Loc, Constructor);
+    S.DiagnoseUseOfDecl(Constructor, Loc);
+
+    TypeSourceInfo *TSInfo = Entity.getTypeSourceInfo();
+    if (!TSInfo)
+      TSInfo = S.Context.getTrivialTypeSourceInfo(Entity.getType(), Loc);
+    SourceRange ParenRange;
+    if (Kind.getKind() != InitializationKind::IK_DirectList)
+      ParenRange = Kind.getParenRange();
+
+    CurInit = S.Owned(new (S.Context) CXXTemporaryObjectExpr(S.Context,
+                                                             Constructor,
+                                                             TSInfo,
+                                                             Exprs,
+                                                             NumExprs,
+                                                             ParenRange,
+                                                     HadMultipleCandidates,
+                                         ConstructorInitRequiresZeroInit));
+  } else {
+    CXXConstructExpr::ConstructionKind ConstructKind =
+      CXXConstructExpr::CK_Complete;
+
+    if (Entity.getKind() == InitializedEntity::EK_Base) {
+      ConstructKind = Entity.getBaseSpecifier()->isVirtual() ?
+        CXXConstructExpr::CK_VirtualBase :
+        CXXConstructExpr::CK_NonVirtualBase;
+    } else if (Entity.getKind() == InitializedEntity::EK_Delegating) {
+      ConstructKind = CXXConstructExpr::CK_Delegating;
+    }
+
+    // Only get the parenthesis range if it is a direct construction.
+    SourceRange parenRange =
+        Kind.getKind() == InitializationKind::IK_Direct ?
+        Kind.getParenRange() : SourceRange();
+
+    // If the entity allows NRVO, mark the construction as elidable
+    // unconditionally.
+    if (Entity.allowsNRVO())
+      CurInit = S.BuildCXXConstructExpr(Loc, Entity.getType(),
+                                        Constructor, /*Elidable=*/true,
+                                        move_arg(ConstructorArgs),
+                                        HadMultipleCandidates,
+                                        ConstructorInitRequiresZeroInit,
+                                        ConstructKind,
+                                        parenRange);
+    else
+      CurInit = S.BuildCXXConstructExpr(Loc, Entity.getType(),
+                                        Constructor,
+                                        move_arg(ConstructorArgs),
+                                        HadMultipleCandidates,
+                                        ConstructorInitRequiresZeroInit,
+                                        ConstructKind,
+                                        parenRange);
+  }
+  if (CurInit.isInvalid())
+    return ExprError();
+
+  // Only check access if all of that succeeded.
+  S.CheckConstructorAccess(Loc, Constructor, Entity,
+                           Step.Function.FoundDecl.getAccess());
+  S.DiagnoseUseOfDecl(Step.Function.FoundDecl, Loc);
+
+  if (shouldBindAsTemporary(Entity))
+    CurInit = S.MaybeBindToTemporary(CurInit.takeAs<Expr>());
+
+  return move(CurInit);
+}
+
+ExprResult
+InitializationSequence::Perform(Sema &S,
+                                const InitializedEntity &Entity,
+                                const InitializationKind &Kind,
+                                MultiExprArg Args,
+                                QualType *ResultType) {
+  if (Failed()) {
+    unsigned NumArgs = Args.size();
+    Diagnose(S, Entity, Kind, (Expr **)Args.release(), NumArgs);
+    return ExprError();
+  }
+
+  if (getKind() == DependentSequence) {
+    // If the declaration is a non-dependent, incomplete array type
+    // that has an initializer, then its type will be completed once
+    // the initializer is instantiated.
+    if (ResultType && !Entity.getType()->isDependentType() &&
+        Args.size() == 1) {
+      QualType DeclType = Entity.getType();
+      if (const IncompleteArrayType *ArrayT
+                           = S.Context.getAsIncompleteArrayType(DeclType)) {
+        // FIXME: We don't currently have the ability to accurately
+        // compute the length of an initializer list without
+        // performing full type-checking of the initializer list
+        // (since we have to determine where braces are implicitly
+        // introduced and such).  So, we fall back to making the array
+        // type a dependently-sized array type with no specified
+        // bound.
+        if (isa<InitListExpr>((Expr *)Args.get()[0])) {
+          SourceRange Brackets;
+
+          // Scavange the location of the brackets from the entity, if we can.
+          if (DeclaratorDecl *DD = Entity.getDecl()) {
+            if (TypeSourceInfo *TInfo = DD->getTypeSourceInfo()) {
+              TypeLoc TL = TInfo->getTypeLoc();
+              if (IncompleteArrayTypeLoc *ArrayLoc
+                                      = dyn_cast<IncompleteArrayTypeLoc>(&TL))
+              Brackets = ArrayLoc->getBracketsRange();
+            }
+          }
+
+          *ResultType
+            = S.Context.getDependentSizedArrayType(ArrayT->getElementType(),
+                                                   /*NumElts=*/0,
+                                                   ArrayT->getSizeModifier(),
+                                       ArrayT->getIndexTypeCVRQualifiers(),
+                                                   Brackets);
+        }
+
+      }
+    }
+    if (Kind.getKind() == InitializationKind::IK_Direct &&
+        !Kind.isExplicitCast()) {
+      // Rebuild the ParenListExpr.
+      SourceRange ParenRange = Kind.getParenRange();
+      return S.ActOnParenListExpr(ParenRange.getBegin(), ParenRange.getEnd(),
+                                  move(Args));
+    }
+    assert(Kind.getKind() == InitializationKind::IK_Copy ||
+           Kind.isExplicitCast() || 
+           Kind.getKind() == InitializationKind::IK_DirectList);
+    return ExprResult(Args.release()[0]);
+  }
+
+  // No steps means no initialization.
+  if (Steps.empty())
+    return S.Owned((Expr *)0);
+
+  QualType DestType = Entity.getType().getNonReferenceType();
+  // FIXME: Ugly hack around the fact that Entity.getType() is not
+  // the same as Entity.getDecl()->getType() in cases involving type merging,
+  //  and we want latter when it makes sense.
+  if (ResultType)
+    *ResultType = Entity.getDecl() ? Entity.getDecl()->getType() :
+                                     Entity.getType();
+
+  ExprResult CurInit = S.Owned((Expr *)0);
+
+  // For initialization steps that start with a single initializer,
+  // grab the only argument out the Args and place it into the "current"
+  // initializer.
+  switch (Steps.front().Kind) {
+  case SK_ResolveAddressOfOverloadedFunction:
+  case SK_CastDerivedToBaseRValue:
+  case SK_CastDerivedToBaseXValue:
+  case SK_CastDerivedToBaseLValue:
+  case SK_BindReference:
+  case SK_BindReferenceToTemporary:
+  case SK_ExtraneousCopyToTemporary:
+  case SK_UserConversion:
+  case SK_QualificationConversionLValue:
+  case SK_QualificationConversionXValue:
+  case SK_QualificationConversionRValue:
+  case SK_ConversionSequence:
+  case SK_ListConstructorCall:
+  case SK_ListInitialization:
+  case SK_UnwrapInitList:
+  case SK_RewrapInitList:
+  case SK_CAssignment:
+  case SK_StringInit:
+  case SK_ObjCObjectConversion:
+  case SK_ArrayInit:
+  case SK_ParenthesizedArrayInit:
+  case SK_PassByIndirectCopyRestore:
+  case SK_PassByIndirectRestore:
+  case SK_ProduceObjCObject:
+  case SK_StdInitializerList: {
+    assert(Args.size() == 1);
+    CurInit = Args.get()[0];
+    if (!CurInit.get()) return ExprError();
+    break;
+  }
+
+  case SK_ConstructorInitialization:
+  case SK_ZeroInitialization:
+    break;
+  }
+
+  // Walk through the computed steps for the initialization sequence,
+  // performing the specified conversions along the way.
+  bool ConstructorInitRequiresZeroInit = false;
+  for (step_iterator Step = step_begin(), StepEnd = step_end();
+       Step != StepEnd; ++Step) {
+    if (CurInit.isInvalid())
+      return ExprError();
+
+    QualType SourceType = CurInit.get() ? CurInit.get()->getType() : QualType();
+
+    switch (Step->Kind) {
+    case SK_ResolveAddressOfOverloadedFunction:
+      // Overload resolution determined which function invoke; update the
+      // initializer to reflect that choice.
+      S.CheckAddressOfMemberAccess(CurInit.get(), Step->Function.FoundDecl);
+      S.DiagnoseUseOfDecl(Step->Function.FoundDecl, Kind.getLocation());
+      CurInit = S.FixOverloadedFunctionReference(move(CurInit),
+                                                 Step->Function.FoundDecl,
+                                                 Step->Function.Function);
+      break;
+
+    case SK_CastDerivedToBaseRValue:
+    case SK_CastDerivedToBaseXValue:
+    case SK_CastDerivedToBaseLValue: {
+      // We have a derived-to-base cast that produces either an rvalue or an
+      // lvalue. Perform that cast.
+
+      CXXCastPath BasePath;
+
+      // Casts to inaccessible base classes are allowed with C-style casts.
+      bool IgnoreBaseAccess = Kind.isCStyleOrFunctionalCast();
+      if (S.CheckDerivedToBaseConversion(SourceType, Step->Type,
+                                         CurInit.get()->getLocStart(),
+                                         CurInit.get()->getSourceRange(),
+                                         &BasePath, IgnoreBaseAccess))
+        return ExprError();
+
+      if (S.BasePathInvolvesVirtualBase(BasePath)) {
+        QualType T = SourceType;
+        if (const PointerType *Pointer = T->getAs<PointerType>())
+          T = Pointer->getPointeeType();
+        if (const RecordType *RecordTy = T->getAs<RecordType>())
+          S.MarkVTableUsed(CurInit.get()->getLocStart(),
+                           cast<CXXRecordDecl>(RecordTy->getDecl()));
+      }
+
+      ExprValueKind VK =
+          Step->Kind == SK_CastDerivedToBaseLValue ?
+              VK_LValue :
+              (Step->Kind == SK_CastDerivedToBaseXValue ?
+                   VK_XValue :
+                   VK_RValue);
+      CurInit = S.Owned(ImplicitCastExpr::Create(S.Context,
+                                                 Step->Type,
+                                                 CK_DerivedToBase,
+                                                 CurInit.get(),
+                                                 &BasePath, VK));
+      break;
+    }
+
+    case SK_BindReference:
+      if (FieldDecl *BitField = CurInit.get()->getBitField()) {
+        // References cannot bind to bit fields (C++ [dcl.init.ref]p5).
+        S.Diag(Kind.getLocation(), diag::err_reference_bind_to_bitfield)
+          << Entity.getType().isVolatileQualified()
+          << BitField->getDeclName()
+          << CurInit.get()->getSourceRange();
+        S.Diag(BitField->getLocation(), diag::note_bitfield_decl);
+        return ExprError();
+      }
+
+      if (CurInit.get()->refersToVectorElement()) {
+        // References cannot bind to vector elements.
+        S.Diag(Kind.getLocation(), diag::err_reference_bind_to_vector_element)
+          << Entity.getType().isVolatileQualified()
+          << CurInit.get()->getSourceRange();
+        PrintInitLocationNote(S, Entity);
+        return ExprError();
+      }
+
+      // Reference binding does not have any corresponding ASTs.
+
+      // Check exception specifications
+      if (S.CheckExceptionSpecCompatibility(CurInit.get(), DestType))
+        return ExprError();
+
+      break;
+
+    case SK_BindReferenceToTemporary:
+      // Check exception specifications
+      if (S.CheckExceptionSpecCompatibility(CurInit.get(), DestType))
+        return ExprError();
+
+      // Materialize the temporary into memory.
+      CurInit = new (S.Context) MaterializeTemporaryExpr(
+                                         Entity.getType().getNonReferenceType(),
+                                                         CurInit.get(),
+                                     Entity.getType()->isLValueReferenceType());
+
+      // If we're binding to an Objective-C object that has lifetime, we
+      // need cleanups.
+      if (S.getLangOpts().ObjCAutoRefCount &&
+          CurInit.get()->getType()->isObjCLifetimeType())
+        S.ExprNeedsCleanups = true;
+            
+      break;
+
+    case SK_ExtraneousCopyToTemporary:
+      CurInit = CopyObject(S, Step->Type, Entity, move(CurInit),
+                           /*IsExtraneousCopy=*/true);
+      break;
+
+    case SK_UserConversion: {
+      // We have a user-defined conversion that invokes either a constructor
+      // or a conversion function.
+      CastKind CastKind;
+      bool IsCopy = false;
+      FunctionDecl *Fn = Step->Function.Function;
+      DeclAccessPair FoundFn = Step->Function.FoundDecl;
+      bool HadMultipleCandidates = Step->Function.HadMultipleCandidates;
+      bool CreatedObject = false;
+      if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(Fn)) {
+        // Build a call to the selected constructor.
+        ASTOwningVector<Expr*> ConstructorArgs(S);
+        SourceLocation Loc = CurInit.get()->getLocStart();
+        CurInit.release(); // Ownership transferred into MultiExprArg, below.
+
+        // Determine the arguments required to actually perform the constructor
+        // call.
+        Expr *Arg = CurInit.get();
+        if (S.CompleteConstructorCall(Constructor,
+                                      MultiExprArg(&Arg, 1),
+                                      Loc, ConstructorArgs))
+          return ExprError();
+
+        // Build an expression that constructs a temporary.
+        CurInit = S.BuildCXXConstructExpr(Loc, Step->Type, Constructor,
+                                          move_arg(ConstructorArgs),
+                                          HadMultipleCandidates,
+                                          /*ZeroInit*/ false,
+                                          CXXConstructExpr::CK_Complete,
+                                          SourceRange());
+        if (CurInit.isInvalid())
+          return ExprError();
+
+        S.CheckConstructorAccess(Kind.getLocation(), Constructor, Entity,
+                                 FoundFn.getAccess());
+        S.DiagnoseUseOfDecl(FoundFn, Kind.getLocation());
+
+        CastKind = CK_ConstructorConversion;
+        QualType Class = S.Context.getTypeDeclType(Constructor->getParent());
+        if (S.Context.hasSameUnqualifiedType(SourceType, Class) ||
+            S.IsDerivedFrom(SourceType, Class))
+          IsCopy = true;
+
+        CreatedObject = true;
+      } else {
+        // Build a call to the conversion function.
+        CXXConversionDecl *Conversion = cast<CXXConversionDecl>(Fn);
+        S.CheckMemberOperatorAccess(Kind.getLocation(), CurInit.get(), 0,
+                                    FoundFn);
+        S.DiagnoseUseOfDecl(FoundFn, Kind.getLocation());
+
+        // FIXME: Should we move this initialization into a separate
+        // derived-to-base conversion? I believe the answer is "no", because
+        // we don't want to turn off access control here for c-style casts.
+        ExprResult CurInitExprRes =
+          S.PerformObjectArgumentInitialization(CurInit.take(), /*Qualifier=*/0,
+                                                FoundFn, Conversion);
+        if(CurInitExprRes.isInvalid())
+          return ExprError();
+        CurInit = move(CurInitExprRes);
+
+        // Build the actual call to the conversion function.
+        CurInit = S.BuildCXXMemberCallExpr(CurInit.get(), FoundFn, Conversion,
+                                           HadMultipleCandidates);
+        if (CurInit.isInvalid() || !CurInit.get())
+          return ExprError();
+
+        CastKind = CK_UserDefinedConversion;
+
+        CreatedObject = Conversion->getResultType()->isRecordType();
+      }
+
+      bool RequiresCopy = !IsCopy && !isReferenceBinding(Steps.back());
+      bool MaybeBindToTemp = RequiresCopy || shouldBindAsTemporary(Entity);
+
+      if (!MaybeBindToTemp && CreatedObject && shouldDestroyTemporary(Entity)) {
+        QualType T = CurInit.get()->getType();
+        if (const RecordType *Record = T->getAs<RecordType>()) {
+          CXXDestructorDecl *Destructor
+            = S.LookupDestructor(cast<CXXRecordDecl>(Record->getDecl()));
+          S.CheckDestructorAccess(CurInit.get()->getLocStart(), Destructor,
+                                  S.PDiag(diag::err_access_dtor_temp) << T);
+          S.MarkFunctionReferenced(CurInit.get()->getLocStart(), Destructor);
+          S.DiagnoseUseOfDecl(Destructor, CurInit.get()->getLocStart());
+        }
+      }
+
+      CurInit = S.Owned(ImplicitCastExpr::Create(S.Context,
+                                                 CurInit.get()->getType(),
+                                                 CastKind, CurInit.get(), 0,
+                                                CurInit.get()->getValueKind()));
+      if (MaybeBindToTemp)
+        CurInit = S.MaybeBindToTemporary(CurInit.takeAs<Expr>());
+      if (RequiresCopy)
+        CurInit = CopyObject(S, Entity.getType().getNonReferenceType(), Entity,
+                             move(CurInit), /*IsExtraneousCopy=*/false);
+      break;
+    }
+
+    case SK_QualificationConversionLValue:
+    case SK_QualificationConversionXValue:
+    case SK_QualificationConversionRValue: {
+      // Perform a qualification conversion; these can never go wrong.
+      ExprValueKind VK =
+          Step->Kind == SK_QualificationConversionLValue ?
+              VK_LValue :
+              (Step->Kind == SK_QualificationConversionXValue ?
+                   VK_XValue :
+                   VK_RValue);
+      CurInit = S.ImpCastExprToType(CurInit.take(), Step->Type, CK_NoOp, VK);
+      break;
+    }
+
+    case SK_ConversionSequence: {
+      Sema::CheckedConversionKind CCK 
+        = Kind.isCStyleCast()? Sema::CCK_CStyleCast
+        : Kind.isFunctionalCast()? Sema::CCK_FunctionalCast
+        : Kind.isExplicitCast()? Sema::CCK_OtherCast
+        : Sema::CCK_ImplicitConversion;
+      ExprResult CurInitExprRes =
+        S.PerformImplicitConversion(CurInit.get(), Step->Type, *Step->ICS,
+                                    getAssignmentAction(Entity), CCK);
+      if (CurInitExprRes.isInvalid())
+        return ExprError();
+      CurInit = move(CurInitExprRes);
+      break;
+    }
+
+    case SK_ListInitialization: {
+      InitListExpr *InitList = cast<InitListExpr>(CurInit.get());
+      // Hack: We must pass *ResultType if available in order to set the type
+      // of arrays, e.g. in 'int ar[] = {1, 2, 3};'.
+      // But in 'const X &x = {1, 2, 3};' we're supposed to initialize a
+      // temporary, not a reference, so we should pass Ty.
+      // Worst case: 'const int (&arref)[] = {1, 2, 3};'.
+      // Since this step is never used for a reference directly, we explicitly
+      // unwrap references here and rewrap them afterwards.
+      // We also need to create a InitializeTemporary entity for this.
+      QualType Ty = ResultType ? ResultType->getNonReferenceType() : Step->Type;
+      bool IsTemporary = Entity.getType()->isReferenceType();
+      InitializedEntity TempEntity = InitializedEntity::InitializeTemporary(Ty);
+      InitListChecker PerformInitList(S, IsTemporary ? TempEntity : Entity,
+          InitList, Ty, /*VerifyOnly=*/false,
+          Kind.getKind() != InitializationKind::IK_DirectList ||
+            !S.getLangOpts().CPlusPlus0x);
+      if (PerformInitList.HadError())
+        return ExprError();
+
+      if (ResultType) {
+        if ((*ResultType)->isRValueReferenceType())
+          Ty = S.Context.getRValueReferenceType(Ty);
+        else if ((*ResultType)->isLValueReferenceType())
+          Ty = S.Context.getLValueReferenceType(Ty,
+            (*ResultType)->getAs<LValueReferenceType>()->isSpelledAsLValue());
+        *ResultType = Ty;
+      }
+
+      InitListExpr *StructuredInitList =
+          PerformInitList.getFullyStructuredList();
+      CurInit.release();
+      CurInit = S.Owned(StructuredInitList);
+      break;
+    }
+
+    case SK_ListConstructorCall: {
+      // When an initializer list is passed for a parameter of type "reference
+      // to object", we don't get an EK_Temporary entity, but instead an
+      // EK_Parameter entity with reference type.
+      // FIXME: This is a hack. What we really should do is create a user
+      // conversion step for this case, but this makes it considerably more
+      // complicated. For now, this will do.
+      InitializedEntity TempEntity = InitializedEntity::InitializeTemporary(
+                                        Entity.getType().getNonReferenceType());
+      bool UseTemporary = Entity.getType()->isReferenceType();
+      InitListExpr *InitList = cast<InitListExpr>(CurInit.get());
+      MultiExprArg Arg(InitList->getInits(), InitList->getNumInits());
+      CurInit = PerformConstructorInitialization(S, UseTemporary ? TempEntity :
+                                                                   Entity,
+                                                 Kind, move(Arg), *Step,
+                                               ConstructorInitRequiresZeroInit);
+      break;
+    }
+
+    case SK_UnwrapInitList:
+      CurInit = S.Owned(cast<InitListExpr>(CurInit.take())->getInit(0));
+      break;
+
+    case SK_RewrapInitList: {
+      Expr *E = CurInit.take();
+      InitListExpr *Syntactic = Step->WrappingSyntacticList;
+      InitListExpr *ILE = new (S.Context) InitListExpr(S.Context,
+          Syntactic->getLBraceLoc(), &E, 1, Syntactic->getRBraceLoc());
+      ILE->setSyntacticForm(Syntactic);
+      ILE->setType(E->getType());
+      ILE->setValueKind(E->getValueKind());
+      CurInit = S.Owned(ILE);
+      break;
+    }
+
+    case SK_ConstructorInitialization: {
+      // When an initializer list is passed for a parameter of type "reference
+      // to object", we don't get an EK_Temporary entity, but instead an
+      // EK_Parameter entity with reference type.
+      // FIXME: This is a hack. What we really should do is create a user
+      // conversion step for this case, but this makes it considerably more
+      // complicated. For now, this will do.
+      InitializedEntity TempEntity = InitializedEntity::InitializeTemporary(
+                                        Entity.getType().getNonReferenceType());
+      bool UseTemporary = Entity.getType()->isReferenceType();
+      CurInit = PerformConstructorInitialization(S, UseTemporary ? TempEntity
+                                                                 : Entity,
+                                                 Kind, move(Args), *Step,
+                                               ConstructorInitRequiresZeroInit);
+      break;
+    }
+
+    case SK_ZeroInitialization: {
+      step_iterator NextStep = Step;
+      ++NextStep;
+      if (NextStep != StepEnd &&
+          NextStep->Kind == SK_ConstructorInitialization) {
+        // The need for zero-initialization is recorded directly into
+        // the call to the object's constructor within the next step.
+        ConstructorInitRequiresZeroInit = true;
+      } else if (Kind.getKind() == InitializationKind::IK_Value &&
+                 S.getLangOpts().CPlusPlus &&
+                 !Kind.isImplicitValueInit()) {
+        TypeSourceInfo *TSInfo = Entity.getTypeSourceInfo();
+        if (!TSInfo)
+          TSInfo = S.Context.getTrivialTypeSourceInfo(Step->Type,
+                                                    Kind.getRange().getBegin());
+
+        CurInit = S.Owned(new (S.Context) CXXScalarValueInitExpr(
+                              TSInfo->getType().getNonLValueExprType(S.Context),
+                                                                 TSInfo,
+                                                    Kind.getRange().getEnd()));
+      } else {
+        CurInit = S.Owned(new (S.Context) ImplicitValueInitExpr(Step->Type));
+      }
+      break;
+    }
+
+    case SK_CAssignment: {
+      QualType SourceType = CurInit.get()->getType();
+      ExprResult Result = move(CurInit);
+      Sema::AssignConvertType ConvTy =
+        S.CheckSingleAssignmentConstraints(Step->Type, Result);
+      if (Result.isInvalid())
+        return ExprError();
+      CurInit = move(Result);
+
+      // If this is a call, allow conversion to a transparent union.
+      ExprResult CurInitExprRes = move(CurInit);
+      if (ConvTy != Sema::Compatible &&
+          Entity.getKind() == InitializedEntity::EK_Parameter &&
+          S.CheckTransparentUnionArgumentConstraints(Step->Type, CurInitExprRes)
+            == Sema::Compatible)
+        ConvTy = Sema::Compatible;
+      if (CurInitExprRes.isInvalid())
+        return ExprError();
+      CurInit = move(CurInitExprRes);
+
+      bool Complained;
+      if (S.DiagnoseAssignmentResult(ConvTy, Kind.getLocation(),
+                                     Step->Type, SourceType,
+                                     CurInit.get(),
+                                     getAssignmentAction(Entity),
+                                     &Complained)) {
+        PrintInitLocationNote(S, Entity);
+        return ExprError();
+      } else if (Complained)
+        PrintInitLocationNote(S, Entity);
+      break;
+    }
+
+    case SK_StringInit: {
+      QualType Ty = Step->Type;
+      CheckStringInit(CurInit.get(), ResultType ? *ResultType : Ty,
+                      S.Context.getAsArrayType(Ty), S);
+      break;
+    }
+
+    case SK_ObjCObjectConversion:
+      CurInit = S.ImpCastExprToType(CurInit.take(), Step->Type,
+                          CK_ObjCObjectLValueCast,
+                          CurInit.get()->getValueKind());
+      break;
+
+    case SK_ArrayInit:
+      // Okay: we checked everything before creating this step. Note that
+      // this is a GNU extension.
+      S.Diag(Kind.getLocation(), diag::ext_array_init_copy)
+        << Step->Type << CurInit.get()->getType()
+        << CurInit.get()->getSourceRange();
+
+      // If the destination type is an incomplete array type, update the
+      // type accordingly.
+      if (ResultType) {
+        if (const IncompleteArrayType *IncompleteDest
+                           = S.Context.getAsIncompleteArrayType(Step->Type)) {
+          if (const ConstantArrayType *ConstantSource
+                 = S.Context.getAsConstantArrayType(CurInit.get()->getType())) {
+            *ResultType = S.Context.getConstantArrayType(
+                                             IncompleteDest->getElementType(),
+                                             ConstantSource->getSize(),
+                                             ArrayType::Normal, 0);
+          }
+        }
+      }
+      break;
+
+    case SK_ParenthesizedArrayInit:
+      // Okay: we checked everything before creating this step. Note that
+      // this is a GNU extension.
+      S.Diag(Kind.getLocation(), diag::ext_array_init_parens)
+        << CurInit.get()->getSourceRange();
+      break;
+
+    case SK_PassByIndirectCopyRestore:
+    case SK_PassByIndirectRestore:
+      checkIndirectCopyRestoreSource(S, CurInit.get());
+      CurInit = S.Owned(new (S.Context)
+                        ObjCIndirectCopyRestoreExpr(CurInit.take(), Step->Type,
+                                Step->Kind == SK_PassByIndirectCopyRestore));
+      break;
+
+    case SK_ProduceObjCObject:
+      CurInit = S.Owned(ImplicitCastExpr::Create(S.Context, Step->Type,
+                                                 CK_ARCProduceObject,
+                                                 CurInit.take(), 0, VK_RValue));
+      break;
+
+    case SK_StdInitializerList: {
+      QualType Dest = Step->Type;
+      QualType E;
+      bool Success = S.isStdInitializerList(Dest, &E);
+      (void)Success;
+      assert(Success && "Destination type changed?");
+
+      // If the element type has a destructor, check it.
+      if (CXXRecordDecl *RD = E->getAsCXXRecordDecl()) {
+        if (!RD->hasIrrelevantDestructor()) {
+          if (CXXDestructorDecl *Destructor = S.LookupDestructor(RD)) {
+            S.MarkFunctionReferenced(Kind.getLocation(), Destructor);
+            S.CheckDestructorAccess(Kind.getLocation(), Destructor,
+                                    S.PDiag(diag::err_access_dtor_temp) << E);
+            S.DiagnoseUseOfDecl(Destructor, Kind.getLocation());
+          }
+        }
+      }
+
+      InitListExpr *ILE = cast<InitListExpr>(CurInit.take());
+      unsigned NumInits = ILE->getNumInits();
+      SmallVector<Expr*, 16> Converted(NumInits);
+      InitializedEntity HiddenArray = InitializedEntity::InitializeTemporary(
+          S.Context.getConstantArrayType(E,
+              llvm::APInt(S.Context.getTypeSize(S.Context.getSizeType()),
+                          NumInits),
+              ArrayType::Normal, 0));
+      InitializedEntity Element =InitializedEntity::InitializeElement(S.Context,
+          0, HiddenArray);
+      for (unsigned i = 0; i < NumInits; ++i) {
+        Element.setElementIndex(i);
+        ExprResult Init = S.Owned(ILE->getInit(i));
+        ExprResult Res = S.PerformCopyInitialization(Element,
+                                                     Init.get()->getExprLoc(),
+                                                     Init);
+        assert(!Res.isInvalid() && "Result changed since try phase.");
+        Converted[i] = Res.take();
+      }
+      InitListExpr *Semantic = new (S.Context)
+          InitListExpr(S.Context, ILE->getLBraceLoc(),
+                       Converted.data(), NumInits, ILE->getRBraceLoc());
+      Semantic->setSyntacticForm(ILE);
+      Semantic->setType(Dest);
+      Semantic->setInitializesStdInitializerList();
+      CurInit = S.Owned(Semantic);
+      break;
+    }
+    }
+  }
+
+  // Diagnose non-fatal problems with the completed initialization.
+  if (Entity.getKind() == InitializedEntity::EK_Member &&
+      cast<FieldDecl>(Entity.getDecl())->isBitField())
+    S.CheckBitFieldInitialization(Kind.getLocation(),
+                                  cast<FieldDecl>(Entity.getDecl()),
+                                  CurInit.get());
+
+  return move(CurInit);
+}
+
+//===----------------------------------------------------------------------===//
+// Diagnose initialization failures
+//===----------------------------------------------------------------------===//
+bool InitializationSequence::Diagnose(Sema &S,
+                                      const InitializedEntity &Entity,
+                                      const InitializationKind &Kind,
+                                      Expr **Args, unsigned NumArgs) {
+  if (!Failed())
+    return false;
+
+  QualType DestType = Entity.getType();
+  switch (Failure) {
+  case FK_TooManyInitsForReference:
+    // FIXME: Customize for the initialized entity?
+    if (NumArgs == 0)
+      S.Diag(Kind.getLocation(), diag::err_reference_without_init)
+        << DestType.getNonReferenceType();
+    else  // FIXME: diagnostic below could be better!
+      S.Diag(Kind.getLocation(), diag::err_reference_has_multiple_inits)
+        << SourceRange(Args[0]->getLocStart(), Args[NumArgs - 1]->getLocEnd());
+    break;
+
+  case FK_ArrayNeedsInitList:
+  case FK_ArrayNeedsInitListOrStringLiteral:
+    S.Diag(Kind.getLocation(), diag::err_array_init_not_init_list)
+      << (Failure == FK_ArrayNeedsInitListOrStringLiteral);
+    break;
+
+  case FK_ArrayTypeMismatch:
+  case FK_NonConstantArrayInit:
+    S.Diag(Kind.getLocation(), 
+           (Failure == FK_ArrayTypeMismatch
+              ? diag::err_array_init_different_type
+              : diag::err_array_init_non_constant_array))
+      << DestType.getNonReferenceType()
+      << Args[0]->getType()
+      << Args[0]->getSourceRange();
+    break;
+
+  case FK_VariableLengthArrayHasInitializer:
+    S.Diag(Kind.getLocation(), diag::err_variable_object_no_init)
+      << Args[0]->getSourceRange();
+    break;
+
+  case FK_AddressOfOverloadFailed: {
+    DeclAccessPair Found;
+    S.ResolveAddressOfOverloadedFunction(Args[0],
+                                         DestType.getNonReferenceType(),
+                                         true,
+                                         Found);
+    break;
+  }
+
+  case FK_ReferenceInitOverloadFailed:
+  case FK_UserConversionOverloadFailed:
+    switch (FailedOverloadResult) {
+    case OR_Ambiguous:
+      if (Failure == FK_UserConversionOverloadFailed)
+        S.Diag(Kind.getLocation(), diag::err_typecheck_ambiguous_condition)
+          << Args[0]->getType() << DestType
+          << Args[0]->getSourceRange();
+      else
+        S.Diag(Kind.getLocation(), diag::err_ref_init_ambiguous)
+          << DestType << Args[0]->getType()
+          << Args[0]->getSourceRange();
+
+      FailedCandidateSet.NoteCandidates(S, OCD_ViableCandidates,
+                                        llvm::makeArrayRef(Args, NumArgs));
+      break;
+
+    case OR_No_Viable_Function:
+      S.Diag(Kind.getLocation(), diag::err_typecheck_nonviable_condition)
+        << Args[0]->getType() << DestType.getNonReferenceType()
+        << Args[0]->getSourceRange();
+      FailedCandidateSet.NoteCandidates(S, OCD_AllCandidates,
+                                        llvm::makeArrayRef(Args, NumArgs));
+      break;
+
+    case OR_Deleted: {
+      S.Diag(Kind.getLocation(), diag::err_typecheck_deleted_function)
+        << Args[0]->getType() << DestType.getNonReferenceType()
+        << Args[0]->getSourceRange();
+      OverloadCandidateSet::iterator Best;
+      OverloadingResult Ovl
+        = FailedCandidateSet.BestViableFunction(S, Kind.getLocation(), Best,
+                                                true);
+      if (Ovl == OR_Deleted) {
+        S.NoteDeletedFunction(Best->Function);
+      } else {
+        llvm_unreachable("Inconsistent overload resolution?");
+      }
+      break;
+    }
+
+    case OR_Success:
+      llvm_unreachable("Conversion did not fail!");
+    }
+    break;
+
+  case FK_NonConstLValueReferenceBindingToTemporary:
+    if (isa<InitListExpr>(Args[0])) {
+      S.Diag(Kind.getLocation(),
+             diag::err_lvalue_reference_bind_to_initlist)
+      << DestType.getNonReferenceType().isVolatileQualified()
+      << DestType.getNonReferenceType()
+      << Args[0]->getSourceRange();
+      break;
+    }
+    // Intentional fallthrough
+
+  case FK_NonConstLValueReferenceBindingToUnrelated:
+    S.Diag(Kind.getLocation(),
+           Failure == FK_NonConstLValueReferenceBindingToTemporary
+             ? diag::err_lvalue_reference_bind_to_temporary
+             : diag::err_lvalue_reference_bind_to_unrelated)
+      << DestType.getNonReferenceType().isVolatileQualified()
+      << DestType.getNonReferenceType()
+      << Args[0]->getType()
+      << Args[0]->getSourceRange();
+    break;
+
+  case FK_RValueReferenceBindingToLValue:
+    S.Diag(Kind.getLocation(), diag::err_lvalue_to_rvalue_ref)
+      << DestType.getNonReferenceType() << Args[0]->getType()
+      << Args[0]->getSourceRange();
+    break;
+
+  case FK_ReferenceInitDropsQualifiers:
+    S.Diag(Kind.getLocation(), diag::err_reference_bind_drops_quals)
+      << DestType.getNonReferenceType()
+      << Args[0]->getType()
+      << Args[0]->getSourceRange();
+    break;
+
+  case FK_ReferenceInitFailed:
+    S.Diag(Kind.getLocation(), diag::err_reference_bind_failed)
+      << DestType.getNonReferenceType()
+      << Args[0]->isLValue()
+      << Args[0]->getType()
+      << Args[0]->getSourceRange();
+    if (DestType.getNonReferenceType()->isObjCObjectPointerType() &&
+        Args[0]->getType()->isObjCObjectPointerType())
+      S.EmitRelatedResultTypeNote(Args[0]);
+    break;
+
+  case FK_ConversionFailed: {
+    QualType FromType = Args[0]->getType();
+    PartialDiagnostic PDiag = S.PDiag(diag::err_init_conversion_failed)
+      << (int)Entity.getKind()
+      << DestType
+      << Args[0]->isLValue()
+      << FromType
+      << Args[0]->getSourceRange();
+    S.HandleFunctionTypeMismatch(PDiag, FromType, DestType);
+    S.Diag(Kind.getLocation(), PDiag);
+    if (DestType.getNonReferenceType()->isObjCObjectPointerType() &&
+        Args[0]->getType()->isObjCObjectPointerType())
+      S.EmitRelatedResultTypeNote(Args[0]);
+    break;
+  }
+
+  case FK_ConversionFromPropertyFailed:
+    // No-op. This error has already been reported.
+    break;
+
+  case FK_TooManyInitsForScalar: {
+    SourceRange R;
+
+    if (InitListExpr *InitList = dyn_cast<InitListExpr>(Args[0]))
+      R = SourceRange(InitList->getInit(0)->getLocEnd(),
+                      InitList->getLocEnd());
+    else
+      R = SourceRange(Args[0]->getLocEnd(), Args[NumArgs - 1]->getLocEnd());
+
+    R.setBegin(S.PP.getLocForEndOfToken(R.getBegin()));
+    if (Kind.isCStyleOrFunctionalCast())
+      S.Diag(Kind.getLocation(), diag::err_builtin_func_cast_more_than_one_arg)
+        << R;
+    else
+      S.Diag(Kind.getLocation(), diag::err_excess_initializers)
+        << /*scalar=*/2 << R;
+    break;
+  }
+
+  case FK_ReferenceBindingToInitList:
+    S.Diag(Kind.getLocation(), diag::err_reference_bind_init_list)
+      << DestType.getNonReferenceType() << Args[0]->getSourceRange();
+    break;
+
+  case FK_InitListBadDestinationType:
+    S.Diag(Kind.getLocation(), diag::err_init_list_bad_dest_type)
+      << (DestType->isRecordType()) << DestType << Args[0]->getSourceRange();
+    break;
+
+  case FK_ListConstructorOverloadFailed:
+  case FK_ConstructorOverloadFailed: {
+    SourceRange ArgsRange;
+    if (NumArgs)
+      ArgsRange = SourceRange(Args[0]->getLocStart(),
+                              Args[NumArgs - 1]->getLocEnd());
+
+    if (Failure == FK_ListConstructorOverloadFailed) {
+      assert(NumArgs == 1 && "List construction from other than 1 argument.");
+      InitListExpr *InitList = cast<InitListExpr>(Args[0]);
+      Args = InitList->getInits();
+      NumArgs = InitList->getNumInits();
+    }
+
+    // FIXME: Using "DestType" for the entity we're printing is probably
+    // bad.
+    switch (FailedOverloadResult) {
+      case OR_Ambiguous:
+        S.Diag(Kind.getLocation(), diag::err_ovl_ambiguous_init)
+          << DestType << ArgsRange;
+        FailedCandidateSet.NoteCandidates(S, OCD_ViableCandidates,
+                                          llvm::makeArrayRef(Args, NumArgs));
+        break;
+
+      case OR_No_Viable_Function:
+        if (Kind.getKind() == InitializationKind::IK_Default &&
+            (Entity.getKind() == InitializedEntity::EK_Base ||
+             Entity.getKind() == InitializedEntity::EK_Member) &&
+            isa<CXXConstructorDecl>(S.CurContext)) {
+          // This is implicit default initialization of a member or
+          // base within a constructor. If no viable function was
+          // found, notify the user that she needs to explicitly
+          // initialize this base/member.
+          CXXConstructorDecl *Constructor
+            = cast<CXXConstructorDecl>(S.CurContext);
+          if (Entity.getKind() == InitializedEntity::EK_Base) {
+            S.Diag(Kind.getLocation(), diag::err_missing_default_ctor)
+              << Constructor->isImplicit()
+              << S.Context.getTypeDeclType(Constructor->getParent())
+              << /*base=*/0
+              << Entity.getType();
+
+            RecordDecl *BaseDecl
+              = Entity.getBaseSpecifier()->getType()->getAs<RecordType>()
+                                                                  ->getDecl();
+            S.Diag(BaseDecl->getLocation(), diag::note_previous_decl)
+              << S.Context.getTagDeclType(BaseDecl);
+          } else {
+            S.Diag(Kind.getLocation(), diag::err_missing_default_ctor)
+              << Constructor->isImplicit()
+              << S.Context.getTypeDeclType(Constructor->getParent())
+              << /*member=*/1
+              << Entity.getName();
+            S.Diag(Entity.getDecl()->getLocation(), diag::note_field_decl);
+
+            if (const RecordType *Record
+                                 = Entity.getType()->getAs<RecordType>())
+              S.Diag(Record->getDecl()->getLocation(),
+                     diag::note_previous_decl)
+                << S.Context.getTagDeclType(Record->getDecl());
+          }
+          break;
+        }
+
+        S.Diag(Kind.getLocation(), diag::err_ovl_no_viable_function_in_init)
+          << DestType << ArgsRange;
+        FailedCandidateSet.NoteCandidates(S, OCD_AllCandidates,
+                                          llvm::makeArrayRef(Args, NumArgs));
+        break;
+
+      case OR_Deleted: {
+        OverloadCandidateSet::iterator Best;
+        OverloadingResult Ovl
+          = FailedCandidateSet.BestViableFunction(S, Kind.getLocation(), Best);
+        if (Ovl != OR_Deleted) {
+          S.Diag(Kind.getLocation(), diag::err_ovl_deleted_init)
+            << true << DestType << ArgsRange;
+          llvm_unreachable("Inconsistent overload resolution?");
+          break;
+        }
+       
+        // If this is a defaulted or implicitly-declared function, then
+        // it was implicitly deleted. Make it clear that the deletion was
+        // implicit.
+        if (S.isImplicitlyDeleted(Best->Function))
+          S.Diag(Kind.getLocation(), diag::err_ovl_deleted_special_init)
+            << S.getSpecialMember(cast<CXXMethodDecl>(Best->Function))
+            << DestType << ArgsRange;
+        else
+          S.Diag(Kind.getLocation(), diag::err_ovl_deleted_init)
+            << true << DestType << ArgsRange;
+
+        S.NoteDeletedFunction(Best->Function);
+        break;
+      }
+
+      case OR_Success:
+        llvm_unreachable("Conversion did not fail!");
+    }
+  }
+  break;
+
+  case FK_DefaultInitOfConst:
+    if (Entity.getKind() == InitializedEntity::EK_Member &&
+        isa<CXXConstructorDecl>(S.CurContext)) {
+      // This is implicit default-initialization of a const member in
+      // a constructor. Complain that it needs to be explicitly
+      // initialized.
+      CXXConstructorDecl *Constructor = cast<CXXConstructorDecl>(S.CurContext);
+      S.Diag(Kind.getLocation(), diag::err_uninitialized_member_in_ctor)
+        << Constructor->isImplicit()
+        << S.Context.getTypeDeclType(Constructor->getParent())
+        << /*const=*/1
+        << Entity.getName();
+      S.Diag(Entity.getDecl()->getLocation(), diag::note_previous_decl)
+        << Entity.getName();
+    } else {
+      S.Diag(Kind.getLocation(), diag::err_default_init_const)
+        << DestType << (bool)DestType->getAs<RecordType>();
+    }
+    break;
+
+  case FK_Incomplete:
+    S.RequireCompleteType(Kind.getLocation(), FailedIncompleteType,
+                          diag::err_init_incomplete_type);
+    break;
+
+  case FK_ListInitializationFailed: {
+    // Run the init list checker again to emit diagnostics.
+    InitListExpr* InitList = cast<InitListExpr>(Args[0]);
+    QualType DestType = Entity.getType();
+    InitListChecker DiagnoseInitList(S, Entity, InitList,
+            DestType, /*VerifyOnly=*/false,
+            Kind.getKind() != InitializationKind::IK_DirectList ||
+              !S.getLangOpts().CPlusPlus0x);
+    assert(DiagnoseInitList.HadError() &&
+           "Inconsistent init list check result.");
+    break;
+  }
+
+  case FK_PlaceholderType: {
+    // FIXME: Already diagnosed!
+    break;
+  }
+
+  case FK_InitListElementCopyFailure: {
+    // Try to perform all copies again.
+    InitListExpr* InitList = cast<InitListExpr>(Args[0]);
+    unsigned NumInits = InitList->getNumInits();
+    QualType DestType = Entity.getType();
+    QualType E;
+    bool Success = S.isStdInitializerList(DestType, &E);
+    (void)Success;
+    assert(Success && "Where did the std::initializer_list go?");
+    InitializedEntity HiddenArray = InitializedEntity::InitializeTemporary(
+        S.Context.getConstantArrayType(E,
+            llvm::APInt(S.Context.getTypeSize(S.Context.getSizeType()),
+                        NumInits),
+            ArrayType::Normal, 0));
+    InitializedEntity Element = InitializedEntity::InitializeElement(S.Context,
+        0, HiddenArray);
+    // Show at most 3 errors. Otherwise, you'd get a lot of errors for errors
+    // where the init list type is wrong, e.g.
+    //   std::initializer_list<void*> list = { 1, 2, 3, 4, 5, 6, 7, 8 };
+    // FIXME: Emit a note if we hit the limit?
+    int ErrorCount = 0;
+    for (unsigned i = 0; i < NumInits && ErrorCount < 3; ++i) {
+      Element.setElementIndex(i);
+      ExprResult Init = S.Owned(InitList->getInit(i));
+      if (S.PerformCopyInitialization(Element, Init.get()->getExprLoc(), Init)
+           .isInvalid())
+        ++ErrorCount;
+    }
+    break;
+  }
+
+  case FK_ExplicitConstructor: {
+    S.Diag(Kind.getLocation(), diag::err_selected_explicit_constructor)
+      << Args[0]->getSourceRange();
+    OverloadCandidateSet::iterator Best;
+    OverloadingResult Ovl
+      = FailedCandidateSet.BestViableFunction(S, Kind.getLocation(), Best);
+    (void)Ovl;
+    assert(Ovl == OR_Success && "Inconsistent overload resolution");
+    CXXConstructorDecl *CtorDecl = cast<CXXConstructorDecl>(Best->Function);
+    S.Diag(CtorDecl->getLocation(), diag::note_constructor_declared_here);
+    break;
+  }
+  }
+
+  PrintInitLocationNote(S, Entity);
+  return true;
+}
+
+void InitializationSequence::dump(raw_ostream &OS) const {
+  switch (SequenceKind) {
+  case FailedSequence: {
+    OS << "Failed sequence: ";
+    switch (Failure) {
+    case FK_TooManyInitsForReference:
+      OS << "too many initializers for reference";
+      break;
+
+    case FK_ArrayNeedsInitList:
+      OS << "array requires initializer list";
+      break;
+
+    case FK_ArrayNeedsInitListOrStringLiteral:
+      OS << "array requires initializer list or string literal";
+      break;
+
+    case FK_ArrayTypeMismatch:
+      OS << "array type mismatch";
+      break;
+
+    case FK_NonConstantArrayInit:
+      OS << "non-constant array initializer";
+      break;
+
+    case FK_AddressOfOverloadFailed:
+      OS << "address of overloaded function failed";
+      break;
+
+    case FK_ReferenceInitOverloadFailed:
+      OS << "overload resolution for reference initialization failed";
+      break;
+
+    case FK_NonConstLValueReferenceBindingToTemporary:
+      OS << "non-const lvalue reference bound to temporary";
+      break;
+
+    case FK_NonConstLValueReferenceBindingToUnrelated:
+      OS << "non-const lvalue reference bound to unrelated type";
+      break;
+
+    case FK_RValueReferenceBindingToLValue:
+      OS << "rvalue reference bound to an lvalue";
+      break;
+
+    case FK_ReferenceInitDropsQualifiers:
+      OS << "reference initialization drops qualifiers";
+      break;
+
+    case FK_ReferenceInitFailed:
+      OS << "reference initialization failed";
+      break;
+
+    case FK_ConversionFailed:
+      OS << "conversion failed";
+      break;
+
+    case FK_ConversionFromPropertyFailed:
+      OS << "conversion from property failed";
+      break;
+
+    case FK_TooManyInitsForScalar:
+      OS << "too many initializers for scalar";
+      break;
+
+    case FK_ReferenceBindingToInitList:
+      OS << "referencing binding to initializer list";
+      break;
+
+    case FK_InitListBadDestinationType:
+      OS << "initializer list for non-aggregate, non-scalar type";
+      break;
+
+    case FK_UserConversionOverloadFailed:
+      OS << "overloading failed for user-defined conversion";
+      break;
+
+    case FK_ConstructorOverloadFailed:
+      OS << "constructor overloading failed";
+      break;
+
+    case FK_DefaultInitOfConst:
+      OS << "default initialization of a const variable";
+      break;
+
+    case FK_Incomplete:
+      OS << "initialization of incomplete type";
+      break;
+
+    case FK_ListInitializationFailed:
+      OS << "list initialization checker failure";
+      break;
+
+    case FK_VariableLengthArrayHasInitializer:
+      OS << "variable length array has an initializer";
+      break;
+
+    case FK_PlaceholderType:
+      OS << "initializer expression isn't contextually valid";
+      break;
+
+    case FK_ListConstructorOverloadFailed:
+      OS << "list constructor overloading failed";
+      break;
+
+    case FK_InitListElementCopyFailure:
+      OS << "copy construction of initializer list element failed";
+      break;
+
+    case FK_ExplicitConstructor:
+      OS << "list copy initialization chose explicit constructor";
+      break;
+    }
+    OS << '\n';
+    return;
+  }
+
+  case DependentSequence:
+    OS << "Dependent sequence\n";
+    return;
+
+  case NormalSequence:
+    OS << "Normal sequence: ";
+    break;
+  }
+
+  for (step_iterator S = step_begin(), SEnd = step_end(); S != SEnd; ++S) {
+    if (S != step_begin()) {
+      OS << " -> ";
+    }
+
+    switch (S->Kind) {
+    case SK_ResolveAddressOfOverloadedFunction:
+      OS << "resolve address of overloaded function";
+      break;
+
+    case SK_CastDerivedToBaseRValue:
+      OS << "derived-to-base case (rvalue" << S->Type.getAsString() << ")";
+      break;
+
+    case SK_CastDerivedToBaseXValue:
+      OS << "derived-to-base case (xvalue" << S->Type.getAsString() << ")";
+      break;
+
+    case SK_CastDerivedToBaseLValue:
+      OS << "derived-to-base case (lvalue" << S->Type.getAsString() << ")";
+      break;
+
+    case SK_BindReference:
+      OS << "bind reference to lvalue";
+      break;
+
+    case SK_BindReferenceToTemporary:
+      OS << "bind reference to a temporary";
+      break;
+
+    case SK_ExtraneousCopyToTemporary:
+      OS << "extraneous C++03 copy to temporary";
+      break;
+
+    case SK_UserConversion:
+      OS << "user-defined conversion via " << *S->Function.Function;
+      break;
+
+    case SK_QualificationConversionRValue:
+      OS << "qualification conversion (rvalue)";
+      break;
+
+    case SK_QualificationConversionXValue:
+      OS << "qualification conversion (xvalue)";
+      break;
+
+    case SK_QualificationConversionLValue:
+      OS << "qualification conversion (lvalue)";
+      break;
+
+    case SK_ConversionSequence:
+      OS << "implicit conversion sequence (";
+      S->ICS->DebugPrint(); // FIXME: use OS
+      OS << ")";
+      break;
+
+    case SK_ListInitialization:
+      OS << "list aggregate initialization";
+      break;
+
+    case SK_ListConstructorCall:
+      OS << "list initialization via constructor";
+      break;
+
+    case SK_UnwrapInitList:
+      OS << "unwrap reference initializer list";
+      break;
+
+    case SK_RewrapInitList:
+      OS << "rewrap reference initializer list";
+      break;
+
+    case SK_ConstructorInitialization:
+      OS << "constructor initialization";
+      break;
+
+    case SK_ZeroInitialization:
+      OS << "zero initialization";
+      break;
+
+    case SK_CAssignment:
+      OS << "C assignment";
+      break;
+
+    case SK_StringInit:
+      OS << "string initialization";
+      break;
+
+    case SK_ObjCObjectConversion:
+      OS << "Objective-C object conversion";
+      break;
+
+    case SK_ArrayInit:
+      OS << "array initialization";
+      break;
+
+    case SK_ParenthesizedArrayInit:
+      OS << "parenthesized array initialization";
+      break;
+
+    case SK_PassByIndirectCopyRestore:
+      OS << "pass by indirect copy and restore";
+      break;
+
+    case SK_PassByIndirectRestore:
+      OS << "pass by indirect restore";
+      break;
+
+    case SK_ProduceObjCObject:
+      OS << "Objective-C object retension";
+      break;
+
+    case SK_StdInitializerList:
+      OS << "std::initializer_list from initializer list";
+      break;
+    }
+  }
+}
+
+void InitializationSequence::dump() const {
+  dump(llvm::errs());
+}
+
+static void DiagnoseNarrowingInInitList(Sema &S, InitializationSequence &Seq,
+                                        QualType EntityType,
+                                        const Expr *PreInit,
+                                        const Expr *PostInit) {
+  if (Seq.step_begin() == Seq.step_end() || PreInit->isValueDependent())
+    return;
+
+  // A narrowing conversion can only appear as the final implicit conversion in
+  // an initialization sequence.
+  const InitializationSequence::Step &LastStep = Seq.step_end()[-1];
+  if (LastStep.Kind != InitializationSequence::SK_ConversionSequence)
+    return;
+
+  const ImplicitConversionSequence &ICS = *LastStep.ICS;
+  const StandardConversionSequence *SCS = 0;
+  switch (ICS.getKind()) {
+  case ImplicitConversionSequence::StandardConversion:
+    SCS = &ICS.Standard;
+    break;
+  case ImplicitConversionSequence::UserDefinedConversion:
+    SCS = &ICS.UserDefined.After;
+    break;
+  case ImplicitConversionSequence::AmbiguousConversion:
+  case ImplicitConversionSequence::EllipsisConversion:
+  case ImplicitConversionSequence::BadConversion:
+    return;
+  }
+
+  // Determine the type prior to the narrowing conversion. If a conversion
+  // operator was used, this may be different from both the type of the entity
+  // and of the pre-initialization expression.
+  QualType PreNarrowingType = PreInit->getType();
+  if (Seq.step_begin() + 1 != Seq.step_end())
+    PreNarrowingType = Seq.step_end()[-2].Type;
+
+  // C++11 [dcl.init.list]p7: Check whether this is a narrowing conversion.
+  APValue ConstantValue;
+  QualType ConstantType;
+  switch (SCS->getNarrowingKind(S.Context, PostInit, ConstantValue,
+                                ConstantType)) {
+  case NK_Not_Narrowing:
+    // No narrowing occurred.
+    return;
+
+  case NK_Type_Narrowing:
+    // This was a floating-to-integer conversion, which is always considered a
+    // narrowing conversion even if the value is a constant and can be
+    // represented exactly as an integer.
+    S.Diag(PostInit->getLocStart(),
+           S.getLangOpts().MicrosoftExt || !S.getLangOpts().CPlusPlus0x? 
+             diag::warn_init_list_type_narrowing
+           : S.isSFINAEContext()?
+             diag::err_init_list_type_narrowing_sfinae
+           : diag::err_init_list_type_narrowing)
+      << PostInit->getSourceRange()
+      << PreNarrowingType.getLocalUnqualifiedType()
+      << EntityType.getLocalUnqualifiedType();
+    break;
+
+  case NK_Constant_Narrowing:
+    // A constant value was narrowed.
+    S.Diag(PostInit->getLocStart(),
+           S.getLangOpts().MicrosoftExt || !S.getLangOpts().CPlusPlus0x? 
+             diag::warn_init_list_constant_narrowing
+           : S.isSFINAEContext()?
+             diag::err_init_list_constant_narrowing_sfinae
+           : diag::err_init_list_constant_narrowing)
+      << PostInit->getSourceRange()
+      << ConstantValue.getAsString(S.getASTContext(), ConstantType)
+      << EntityType.getLocalUnqualifiedType();
+    break;
+
+  case NK_Variable_Narrowing:
+    // A variable's value may have been narrowed.
+    S.Diag(PostInit->getLocStart(),
+           S.getLangOpts().MicrosoftExt || !S.getLangOpts().CPlusPlus0x? 
+             diag::warn_init_list_variable_narrowing
+           : S.isSFINAEContext()?
+             diag::err_init_list_variable_narrowing_sfinae
+           : diag::err_init_list_variable_narrowing)
+      << PostInit->getSourceRange()
+      << PreNarrowingType.getLocalUnqualifiedType()
+      << EntityType.getLocalUnqualifiedType();
+    break;
+  }
+
+  SmallString<128> StaticCast;
+  llvm::raw_svector_ostream OS(StaticCast);
+  OS << "static_cast<";
+  if (const TypedefType *TT = EntityType->getAs<TypedefType>()) {
+    // It's important to use the typedef's name if there is one so that the
+    // fixit doesn't break code using types like int64_t.
+    //
+    // FIXME: This will break if the typedef requires qualification.  But
+    // getQualifiedNameAsString() includes non-machine-parsable components.
+    OS << *TT->getDecl();
+  } else if (const BuiltinType *BT = EntityType->getAs<BuiltinType>())
+    OS << BT->getName(S.getLangOpts());
+  else {
+    // Oops, we didn't find the actual type of the variable.  Don't emit a fixit
+    // with a broken cast.
+    return;
+  }
+  OS << ">(";
+  S.Diag(PostInit->getLocStart(), diag::note_init_list_narrowing_override)
+    << PostInit->getSourceRange()
+    << FixItHint::CreateInsertion(PostInit->getLocStart(), OS.str())
+    << FixItHint::CreateInsertion(
+      S.getPreprocessor().getLocForEndOfToken(PostInit->getLocEnd()), ")");
+}
+
+//===----------------------------------------------------------------------===//
+// Initialization helper functions
+//===----------------------------------------------------------------------===//
+bool
+Sema::CanPerformCopyInitialization(const InitializedEntity &Entity,
+                                   ExprResult Init) {
+  if (Init.isInvalid())
+    return false;
+
+  Expr *InitE = Init.get();
+  assert(InitE && "No initialization expression");
+
+  InitializationKind Kind = InitializationKind::CreateCopy(SourceLocation(),
+                                                           SourceLocation());
+  InitializationSequence Seq(*this, Entity, Kind, &InitE, 1);
+  return !Seq.Failed();
+}
+
+ExprResult
+Sema::PerformCopyInitialization(const InitializedEntity &Entity,
+                                SourceLocation EqualLoc,
+                                ExprResult Init,
+                                bool TopLevelOfInitList,
+                                bool AllowExplicit) {
+  if (Init.isInvalid())
+    return ExprError();
+
+  Expr *InitE = Init.get();
+  assert(InitE && "No initialization expression?");
+
+  if (EqualLoc.isInvalid())
+    EqualLoc = InitE->getLocStart();
+
+  InitializationKind Kind = InitializationKind::CreateCopy(InitE->getLocStart(),
+                                                           EqualLoc,
+                                                           AllowExplicit);
+  InitializationSequence Seq(*this, Entity, Kind, &InitE, 1);
+  Init.release();
+
+  ExprResult Result = Seq.Perform(*this, Entity, Kind, MultiExprArg(&InitE, 1));
+
+  if (!Result.isInvalid() && TopLevelOfInitList)
+    DiagnoseNarrowingInInitList(*this, Seq, Entity.getType(),
+                                InitE, Result.get());
+
+  return Result;
+}
diff --git a/clang/lib/Sema/SemaLambda.cpp b/clang/lib/Sema/SemaLambda.cpp
new file mode 100644
index 0000000..6ef8d88
--- /dev/null
+++ b/clang/lib/Sema/SemaLambda.cpp
@@ -0,0 +1,820 @@
+//===--- SemaLambda.cpp - Semantic Analysis for C++11 Lambdas -------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+//  This file implements semantic analysis for C++ lambda expressions.
+//
+//===----------------------------------------------------------------------===//
+#include "clang/Sema/DeclSpec.h"
+#include "clang/Sema/Initialization.h"
+#include "clang/Sema/Lookup.h"
+#include "clang/Sema/Scope.h"
+#include "clang/Sema/ScopeInfo.h"
+#include "clang/Sema/SemaInternal.h"
+#include "clang/Lex/Preprocessor.h"
+#include "clang/AST/ExprCXX.h"
+using namespace clang;
+using namespace sema;
+
+CXXRecordDecl *Sema::createLambdaClosureType(SourceRange IntroducerRange,
+                                             bool KnownDependent) {
+  DeclContext *DC = CurContext;
+  while (!(DC->isFunctionOrMethod() || DC->isRecord() || DC->isFileContext()))
+    DC = DC->getParent();
+  
+  // Start constructing the lambda class.
+  CXXRecordDecl *Class = CXXRecordDecl::CreateLambda(Context, DC, 
+                                                     IntroducerRange.getBegin(),
+                                                     KnownDependent);
+  DC->addDecl(Class);
+  
+  return Class;
+}
+
+/// \brief Determine whether the given context is or is enclosed in an inline
+/// function.
+static bool isInInlineFunction(const DeclContext *DC) {
+  while (!DC->isFileContext()) {
+    if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(DC))
+      if (FD->isInlined())
+        return true;
+    
+    DC = DC->getLexicalParent();
+  }
+  
+  return false;
+}
+
+CXXMethodDecl *Sema::startLambdaDefinition(CXXRecordDecl *Class,
+                 SourceRange IntroducerRange,
+                 TypeSourceInfo *MethodType,
+                 SourceLocation EndLoc,
+                 llvm::ArrayRef<ParmVarDecl *> Params,
+                 llvm::Optional<unsigned> ManglingNumber,
+                 Decl *ContextDecl) {
+  // C++11 [expr.prim.lambda]p5:
+  //   The closure type for a lambda-expression has a public inline function 
+  //   call operator (13.5.4) whose parameters and return type are described by
+  //   the lambda-expression's parameter-declaration-clause and 
+  //   trailing-return-type respectively.
+  DeclarationName MethodName
+    = Context.DeclarationNames.getCXXOperatorName(OO_Call);
+  DeclarationNameLoc MethodNameLoc;
+  MethodNameLoc.CXXOperatorName.BeginOpNameLoc
+    = IntroducerRange.getBegin().getRawEncoding();
+  MethodNameLoc.CXXOperatorName.EndOpNameLoc
+    = IntroducerRange.getEnd().getRawEncoding();
+  CXXMethodDecl *Method
+    = CXXMethodDecl::Create(Context, Class, EndLoc,
+                            DeclarationNameInfo(MethodName, 
+                                                IntroducerRange.getBegin(),
+                                                MethodNameLoc),
+                            MethodType->getType(), MethodType,
+                            /*isStatic=*/false,
+                            SC_None,
+                            /*isInline=*/true,
+                            /*isConstExpr=*/false,
+                            EndLoc);
+  Method->setAccess(AS_public);
+  
+  // Temporarily set the lexical declaration context to the current
+  // context, so that the Scope stack matches the lexical nesting.
+  Method->setLexicalDeclContext(CurContext);  
+  
+  // Add parameters.
+  if (!Params.empty()) {
+    Method->setParams(Params);
+    CheckParmsForFunctionDef(const_cast<ParmVarDecl **>(Params.begin()),
+                             const_cast<ParmVarDecl **>(Params.end()),
+                             /*CheckParameterNames=*/false);
+    
+    for (CXXMethodDecl::param_iterator P = Method->param_begin(), 
+                                    PEnd = Method->param_end();
+         P != PEnd; ++P)
+      (*P)->setOwningFunction(Method);
+  }
+  
+  // If we don't already have a mangling number for this lambda expression,
+  // allocate one now.
+  if (!ManglingNumber) {
+    ContextDecl = ExprEvalContexts.back().LambdaContextDecl;
+    
+    enum ContextKind {
+      Normal,
+      DefaultArgument,
+      DataMember,
+      StaticDataMember
+    } Kind = Normal;
+    
+    // Default arguments of member function parameters that appear in a class
+    // definition, as well as the initializers of data members, receive special
+    // treatment. Identify them.
+    if (ContextDecl) {
+      if (ParmVarDecl *Param = dyn_cast<ParmVarDecl>(ContextDecl)) {
+        if (const DeclContext *LexicalDC
+            = Param->getDeclContext()->getLexicalParent())
+          if (LexicalDC->isRecord())
+            Kind = DefaultArgument;
+      } else if (VarDecl *Var = dyn_cast<VarDecl>(ContextDecl)) {
+        if (Var->getDeclContext()->isRecord())
+          Kind = StaticDataMember;
+      } else if (isa<FieldDecl>(ContextDecl)) {
+        Kind = DataMember;
+      }
+    }        
+    
+    switch (Kind) {
+      case Normal:
+        if (CurContext->isDependentContext() || isInInlineFunction(CurContext))
+          ManglingNumber = Context.getLambdaManglingNumber(Method);
+        else
+          ManglingNumber = 0;
+        
+        // There is no special context for this lambda.
+        ContextDecl = 0;        
+        break;
+        
+      case StaticDataMember:
+        if (!CurContext->isDependentContext()) {
+          ManglingNumber = 0;
+          ContextDecl = 0;
+          break;
+        }
+        // Fall through to assign a mangling number.
+        
+      case DataMember:
+      case DefaultArgument:
+        ManglingNumber = ExprEvalContexts.back().getLambdaMangleContext()
+                           .getManglingNumber(Method);
+        break;
+    }
+  }
+
+  Class->setLambdaMangling(*ManglingNumber, ContextDecl);
+  return Method;
+}
+
+LambdaScopeInfo *Sema::enterLambdaScope(CXXMethodDecl *CallOperator,
+                                        SourceRange IntroducerRange,
+                                        LambdaCaptureDefault CaptureDefault,
+                                        bool ExplicitParams,
+                                        bool ExplicitResultType,
+                                        bool Mutable) {
+  PushLambdaScope(CallOperator->getParent(), CallOperator);
+  LambdaScopeInfo *LSI = getCurLambda();
+  if (CaptureDefault == LCD_ByCopy)
+    LSI->ImpCaptureStyle = LambdaScopeInfo::ImpCap_LambdaByval;
+  else if (CaptureDefault == LCD_ByRef)
+    LSI->ImpCaptureStyle = LambdaScopeInfo::ImpCap_LambdaByref;
+  LSI->IntroducerRange = IntroducerRange;
+  LSI->ExplicitParams = ExplicitParams;
+  LSI->Mutable = Mutable;
+
+  if (ExplicitResultType) {
+    LSI->ReturnType = CallOperator->getResultType();
+    
+    if (!LSI->ReturnType->isDependentType() &&
+        !LSI->ReturnType->isVoidType()) {
+      if (RequireCompleteType(CallOperator->getLocStart(), LSI->ReturnType,
+                              diag::err_lambda_incomplete_result)) {
+        // Do nothing.
+      } else if (LSI->ReturnType->isObjCObjectOrInterfaceType()) {
+        Diag(CallOperator->getLocStart(), diag::err_lambda_objc_object_result)
+          << LSI->ReturnType;
+      }
+    }
+  } else {
+    LSI->HasImplicitReturnType = true;
+  }
+
+  return LSI;
+}
+
+void Sema::finishLambdaExplicitCaptures(LambdaScopeInfo *LSI) {
+  LSI->finishedExplicitCaptures();
+}
+
+void Sema::addLambdaParameters(CXXMethodDecl *CallOperator, Scope *CurScope) {  
+  // Introduce our parameters into the function scope
+  for (unsigned p = 0, NumParams = CallOperator->getNumParams(); 
+       p < NumParams; ++p) {
+    ParmVarDecl *Param = CallOperator->getParamDecl(p);
+    
+    // If this has an identifier, add it to the scope stack.
+    if (CurScope && Param->getIdentifier()) {
+      CheckShadow(CurScope, Param);
+      
+      PushOnScopeChains(Param, CurScope);
+    }
+  }
+}
+
+void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro,
+                                        Declarator &ParamInfo,
+                                        Scope *CurScope) {
+  // Determine if we're within a context where we know that the lambda will
+  // be dependent, because there are template parameters in scope.
+  bool KnownDependent = false;
+  if (Scope *TmplScope = CurScope->getTemplateParamParent())
+    if (!TmplScope->decl_empty())
+      KnownDependent = true;
+  
+  CXXRecordDecl *Class = createLambdaClosureType(Intro.Range, KnownDependent);
+  
+  // Determine the signature of the call operator.
+  TypeSourceInfo *MethodTyInfo;
+  bool ExplicitParams = true;
+  bool ExplicitResultType = true;
+  SourceLocation EndLoc;
+  llvm::ArrayRef<ParmVarDecl *> Params;
+  if (ParamInfo.getNumTypeObjects() == 0) {
+    // C++11 [expr.prim.lambda]p4:
+    //   If a lambda-expression does not include a lambda-declarator, it is as 
+    //   if the lambda-declarator were ().
+    FunctionProtoType::ExtProtoInfo EPI;
+    EPI.HasTrailingReturn = true;
+    EPI.TypeQuals |= DeclSpec::TQ_const;
+    QualType MethodTy = Context.getFunctionType(Context.DependentTy,
+                                                /*Args=*/0, /*NumArgs=*/0, EPI);
+    MethodTyInfo = Context.getTrivialTypeSourceInfo(MethodTy);
+    ExplicitParams = false;
+    ExplicitResultType = false;
+    EndLoc = Intro.Range.getEnd();
+  } else {
+    assert(ParamInfo.isFunctionDeclarator() &&
+           "lambda-declarator is a function");
+    DeclaratorChunk::FunctionTypeInfo &FTI = ParamInfo.getFunctionTypeInfo();
+    
+    // C++11 [expr.prim.lambda]p5:
+    //   This function call operator is declared const (9.3.1) if and only if 
+    //   the lambda-expression's parameter-declaration-clause is not followed 
+    //   by mutable. It is neither virtual nor declared volatile. [...]
+    if (!FTI.hasMutableQualifier())
+      FTI.TypeQuals |= DeclSpec::TQ_const;
+    
+    MethodTyInfo = GetTypeForDeclarator(ParamInfo, CurScope);
+    assert(MethodTyInfo && "no type from lambda-declarator");
+    EndLoc = ParamInfo.getSourceRange().getEnd();
+    
+    ExplicitResultType
+      = MethodTyInfo->getType()->getAs<FunctionType>()->getResultType() 
+                                                        != Context.DependentTy;
+    
+    TypeLoc TL = MethodTyInfo->getTypeLoc();
+    FunctionProtoTypeLoc Proto = cast<FunctionProtoTypeLoc>(TL);
+    Params = llvm::ArrayRef<ParmVarDecl *>(Proto.getParmArray(), 
+                                           Proto.getNumArgs());
+  }
+  
+  CXXMethodDecl *Method = startLambdaDefinition(Class, Intro.Range, 
+                                                MethodTyInfo, EndLoc, Params);
+  
+  if (ExplicitParams)
+    CheckCXXDefaultArguments(Method);
+  
+  // Attributes on the lambda apply to the method.  
+  ProcessDeclAttributes(CurScope, Method, ParamInfo);
+  
+  // Introduce the function call operator as the current declaration context.
+  PushDeclContext(CurScope, Method);
+    
+  // Introduce the lambda scope.
+  LambdaScopeInfo *LSI
+    = enterLambdaScope(Method, Intro.Range, Intro.Default, ExplicitParams,
+                       ExplicitResultType,
+                       (Method->getTypeQualifiers() & Qualifiers::Const) == 0);
+ 
+  // Handle explicit captures.
+  SourceLocation PrevCaptureLoc
+    = Intro.Default == LCD_None? Intro.Range.getBegin() : Intro.DefaultLoc;
+  for (llvm::SmallVector<LambdaCapture, 4>::const_iterator
+         C = Intro.Captures.begin(), 
+         E = Intro.Captures.end(); 
+       C != E; 
+       PrevCaptureLoc = C->Loc, ++C) {
+    if (C->Kind == LCK_This) {
+      // C++11 [expr.prim.lambda]p8:
+      //   An identifier or this shall not appear more than once in a 
+      //   lambda-capture.
+      if (LSI->isCXXThisCaptured()) {
+        Diag(C->Loc, diag::err_capture_more_than_once) 
+          << "'this'"
+          << SourceRange(LSI->getCXXThisCapture().getLocation())
+          << FixItHint::CreateRemoval(
+               SourceRange(PP.getLocForEndOfToken(PrevCaptureLoc), C->Loc));
+        continue;
+      }
+
+      // C++11 [expr.prim.lambda]p8:
+      //   If a lambda-capture includes a capture-default that is =, the 
+      //   lambda-capture shall not contain this [...].
+      if (Intro.Default == LCD_ByCopy) {
+        Diag(C->Loc, diag::err_this_capture_with_copy_default)
+          << FixItHint::CreateRemoval(
+               SourceRange(PP.getLocForEndOfToken(PrevCaptureLoc), C->Loc));
+        continue;
+      }
+
+      // C++11 [expr.prim.lambda]p12:
+      //   If this is captured by a local lambda expression, its nearest
+      //   enclosing function shall be a non-static member function.
+      QualType ThisCaptureType = getCurrentThisType();
+      if (ThisCaptureType.isNull()) {
+        Diag(C->Loc, diag::err_this_capture) << true;
+        continue;
+      }
+      
+      CheckCXXThisCapture(C->Loc, /*Explicit=*/true);
+      continue;
+    }
+
+    assert(C->Id && "missing identifier for capture");
+
+    // C++11 [expr.prim.lambda]p8:
+    //   If a lambda-capture includes a capture-default that is &, the 
+    //   identifiers in the lambda-capture shall not be preceded by &.
+    //   If a lambda-capture includes a capture-default that is =, [...]
+    //   each identifier it contains shall be preceded by &.
+    if (C->Kind == LCK_ByRef && Intro.Default == LCD_ByRef) {
+      Diag(C->Loc, diag::err_reference_capture_with_reference_default)
+        << FixItHint::CreateRemoval(
+             SourceRange(PP.getLocForEndOfToken(PrevCaptureLoc), C->Loc));
+      continue;
+    } else if (C->Kind == LCK_ByCopy && Intro.Default == LCD_ByCopy) {
+      Diag(C->Loc, diag::err_copy_capture_with_copy_default)
+        << FixItHint::CreateRemoval(
+             SourceRange(PP.getLocForEndOfToken(PrevCaptureLoc), C->Loc));
+      continue;
+    }
+
+    DeclarationNameInfo Name(C->Id, C->Loc);
+    LookupResult R(*this, Name, LookupOrdinaryName);
+    LookupName(R, CurScope);
+    if (R.isAmbiguous())
+      continue;
+    if (R.empty()) {
+      // FIXME: Disable corrections that would add qualification?
+      CXXScopeSpec ScopeSpec;
+      DeclFilterCCC<VarDecl> Validator;
+      if (DiagnoseEmptyLookup(CurScope, ScopeSpec, R, Validator))
+        continue;
+    }
+
+    // C++11 [expr.prim.lambda]p10:
+    //   The identifiers in a capture-list are looked up using the usual rules
+    //   for unqualified name lookup (3.4.1); each such lookup shall find a 
+    //   variable with automatic storage duration declared in the reaching 
+    //   scope of the local lambda expression.
+    // 
+    // Note that the 'reaching scope' check happens in tryCaptureVariable().
+    VarDecl *Var = R.getAsSingle<VarDecl>();
+    if (!Var) {
+      Diag(C->Loc, diag::err_capture_does_not_name_variable) << C->Id;
+      continue;
+    }
+
+    if (!Var->hasLocalStorage()) {
+      Diag(C->Loc, diag::err_capture_non_automatic_variable) << C->Id;
+      Diag(Var->getLocation(), diag::note_previous_decl) << C->Id;
+      continue;
+    }
+
+    // C++11 [expr.prim.lambda]p8:
+    //   An identifier or this shall not appear more than once in a 
+    //   lambda-capture.
+    if (LSI->isCaptured(Var)) {
+      Diag(C->Loc, diag::err_capture_more_than_once) 
+        << C->Id
+        << SourceRange(LSI->getCapture(Var).getLocation())
+        << FixItHint::CreateRemoval(
+             SourceRange(PP.getLocForEndOfToken(PrevCaptureLoc), C->Loc));
+      continue;
+    }
+
+    // C++11 [expr.prim.lambda]p23:
+    //   A capture followed by an ellipsis is a pack expansion (14.5.3).
+    SourceLocation EllipsisLoc;
+    if (C->EllipsisLoc.isValid()) {
+      if (Var->isParameterPack()) {
+        EllipsisLoc = C->EllipsisLoc;
+      } else {
+        Diag(C->EllipsisLoc, diag::err_pack_expansion_without_parameter_packs)
+          << SourceRange(C->Loc);
+        
+        // Just ignore the ellipsis.
+      }
+    } else if (Var->isParameterPack()) {
+      Diag(C->Loc, diag::err_lambda_unexpanded_pack);
+      continue;
+    }
+    
+    TryCaptureKind Kind = C->Kind == LCK_ByRef ? TryCapture_ExplicitByRef :
+                                                 TryCapture_ExplicitByVal;
+    tryCaptureVariable(Var, C->Loc, Kind, EllipsisLoc);
+  }
+  finishLambdaExplicitCaptures(LSI);
+
+  // Add lambda parameters into scope.
+  addLambdaParameters(Method, CurScope);
+
+  // Enter a new evaluation context to insulate the lambda from any
+  // cleanups from the enclosing full-expression.
+  PushExpressionEvaluationContext(PotentiallyEvaluated);  
+}
+
+void Sema::ActOnLambdaError(SourceLocation StartLoc, Scope *CurScope,
+                            bool IsInstantiation) {
+  // Leave the expression-evaluation context.
+  DiscardCleanupsInEvaluationContext();
+  PopExpressionEvaluationContext();
+
+  // Leave the context of the lambda.
+  if (!IsInstantiation)
+    PopDeclContext();
+
+  // Finalize the lambda.
+  LambdaScopeInfo *LSI = getCurLambda();
+  CXXRecordDecl *Class = LSI->Lambda;
+  Class->setInvalidDecl();
+  SmallVector<Decl*, 4> Fields(Class->field_begin(), Class->field_end());
+  ActOnFields(0, Class->getLocation(), Class, Fields, 
+              SourceLocation(), SourceLocation(), 0);
+  CheckCompletedCXXClass(Class);
+
+  PopFunctionScopeInfo();
+}
+
+/// \brief Add a lambda's conversion to function pointer, as described in
+/// C++11 [expr.prim.lambda]p6.
+static void addFunctionPointerConversion(Sema &S, 
+                                         SourceRange IntroducerRange,
+                                         CXXRecordDecl *Class,
+                                         CXXMethodDecl *CallOperator) {
+  // Add the conversion to function pointer.
+  const FunctionProtoType *Proto
+    = CallOperator->getType()->getAs<FunctionProtoType>(); 
+  QualType FunctionPtrTy;
+  QualType FunctionTy;
+  {
+    FunctionProtoType::ExtProtoInfo ExtInfo = Proto->getExtProtoInfo();
+    ExtInfo.TypeQuals = 0;
+    FunctionTy = S.Context.getFunctionType(Proto->getResultType(),
+                                           Proto->arg_type_begin(),
+                                           Proto->getNumArgs(),
+                                           ExtInfo);
+    FunctionPtrTy = S.Context.getPointerType(FunctionTy);
+  }
+  
+  FunctionProtoType::ExtProtoInfo ExtInfo;
+  ExtInfo.TypeQuals = Qualifiers::Const;
+  QualType ConvTy = S.Context.getFunctionType(FunctionPtrTy, 0, 0, ExtInfo);
+  
+  SourceLocation Loc = IntroducerRange.getBegin();
+  DeclarationName Name
+    = S.Context.DeclarationNames.getCXXConversionFunctionName(
+        S.Context.getCanonicalType(FunctionPtrTy));
+  DeclarationNameLoc NameLoc;
+  NameLoc.NamedType.TInfo = S.Context.getTrivialTypeSourceInfo(FunctionPtrTy,
+                                                               Loc);
+  CXXConversionDecl *Conversion 
+    = CXXConversionDecl::Create(S.Context, Class, Loc, 
+                                DeclarationNameInfo(Name, Loc, NameLoc),
+                                ConvTy, 
+                                S.Context.getTrivialTypeSourceInfo(ConvTy, 
+                                                                   Loc),
+                                /*isInline=*/false, /*isExplicit=*/false,
+                                /*isConstexpr=*/false, 
+                                CallOperator->getBody()->getLocEnd());
+  Conversion->setAccess(AS_public);
+  Conversion->setImplicit(true);
+  Class->addDecl(Conversion);
+  
+  // Add a non-static member function "__invoke" that will be the result of
+  // the conversion.
+  Name = &S.Context.Idents.get("__invoke");
+  CXXMethodDecl *Invoke
+    = CXXMethodDecl::Create(S.Context, Class, Loc, 
+                            DeclarationNameInfo(Name, Loc), FunctionTy, 
+                            CallOperator->getTypeSourceInfo(),
+                            /*IsStatic=*/true, SC_Static, /*IsInline=*/true,
+                            /*IsConstexpr=*/false, 
+                            CallOperator->getBody()->getLocEnd());
+  SmallVector<ParmVarDecl *, 4> InvokeParams;
+  for (unsigned I = 0, N = CallOperator->getNumParams(); I != N; ++I) {
+    ParmVarDecl *From = CallOperator->getParamDecl(I);
+    InvokeParams.push_back(ParmVarDecl::Create(S.Context, Invoke,
+                                               From->getLocStart(),
+                                               From->getLocation(),
+                                               From->getIdentifier(),
+                                               From->getType(),
+                                               From->getTypeSourceInfo(),
+                                               From->getStorageClass(),
+                                               From->getStorageClassAsWritten(),
+                                               /*DefaultArg=*/0));
+  }
+  Invoke->setParams(InvokeParams);
+  Invoke->setAccess(AS_private);
+  Invoke->setImplicit(true);
+  Class->addDecl(Invoke);
+}
+
+/// \brief Add a lambda's conversion to block pointer.
+static void addBlockPointerConversion(Sema &S, 
+                                      SourceRange IntroducerRange,
+                                      CXXRecordDecl *Class,
+                                      CXXMethodDecl *CallOperator) {
+  const FunctionProtoType *Proto
+    = CallOperator->getType()->getAs<FunctionProtoType>(); 
+  QualType BlockPtrTy;
+  {
+    FunctionProtoType::ExtProtoInfo ExtInfo = Proto->getExtProtoInfo();
+    ExtInfo.TypeQuals = 0;
+    QualType FunctionTy
+      = S.Context.getFunctionType(Proto->getResultType(),
+                                  Proto->arg_type_begin(),
+                                  Proto->getNumArgs(),
+                                  ExtInfo);
+    BlockPtrTy = S.Context.getBlockPointerType(FunctionTy);
+  }
+  
+  FunctionProtoType::ExtProtoInfo ExtInfo;
+  ExtInfo.TypeQuals = Qualifiers::Const;
+  QualType ConvTy = S.Context.getFunctionType(BlockPtrTy, 0, 0, ExtInfo);
+  
+  SourceLocation Loc = IntroducerRange.getBegin();
+  DeclarationName Name
+    = S.Context.DeclarationNames.getCXXConversionFunctionName(
+        S.Context.getCanonicalType(BlockPtrTy));
+  DeclarationNameLoc NameLoc;
+  NameLoc.NamedType.TInfo = S.Context.getTrivialTypeSourceInfo(BlockPtrTy, Loc);
+  CXXConversionDecl *Conversion 
+    = CXXConversionDecl::Create(S.Context, Class, Loc, 
+                                DeclarationNameInfo(Name, Loc, NameLoc),
+                                ConvTy, 
+                                S.Context.getTrivialTypeSourceInfo(ConvTy, Loc),
+                                /*isInline=*/false, /*isExplicit=*/false,
+                                /*isConstexpr=*/false, 
+                                CallOperator->getBody()->getLocEnd());
+  Conversion->setAccess(AS_public);
+  Conversion->setImplicit(true);
+  Class->addDecl(Conversion);
+}
+         
+ExprResult Sema::ActOnLambdaExpr(SourceLocation StartLoc, Stmt *Body, 
+                                 Scope *CurScope, 
+                                 bool IsInstantiation) {
+  // Collect information from the lambda scope.
+  llvm::SmallVector<LambdaExpr::Capture, 4> Captures;
+  llvm::SmallVector<Expr *, 4> CaptureInits;
+  LambdaCaptureDefault CaptureDefault;
+  CXXRecordDecl *Class;
+  CXXMethodDecl *CallOperator;
+  SourceRange IntroducerRange;
+  bool ExplicitParams;
+  bool ExplicitResultType;
+  bool LambdaExprNeedsCleanups;
+  llvm::SmallVector<VarDecl *, 4> ArrayIndexVars;
+  llvm::SmallVector<unsigned, 4> ArrayIndexStarts;
+  {
+    LambdaScopeInfo *LSI = getCurLambda();
+    CallOperator = LSI->CallOperator;
+    Class = LSI->Lambda;
+    IntroducerRange = LSI->IntroducerRange;
+    ExplicitParams = LSI->ExplicitParams;
+    ExplicitResultType = !LSI->HasImplicitReturnType;
+    LambdaExprNeedsCleanups = LSI->ExprNeedsCleanups;
+    ArrayIndexVars.swap(LSI->ArrayIndexVars);
+    ArrayIndexStarts.swap(LSI->ArrayIndexStarts);
+    
+    // Translate captures.
+    for (unsigned I = 0, N = LSI->Captures.size(); I != N; ++I) {
+      LambdaScopeInfo::Capture From = LSI->Captures[I];
+      assert(!From.isBlockCapture() && "Cannot capture __block variables");
+      bool IsImplicit = I >= LSI->NumExplicitCaptures;
+
+      // Handle 'this' capture.
+      if (From.isThisCapture()) {
+        Captures.push_back(LambdaExpr::Capture(From.getLocation(),
+                                               IsImplicit,
+                                               LCK_This));
+        CaptureInits.push_back(new (Context) CXXThisExpr(From.getLocation(),
+                                                         getCurrentThisType(),
+                                                         /*isImplicit=*/true));
+        continue;
+      }
+
+      VarDecl *Var = From.getVariable();
+      LambdaCaptureKind Kind = From.isCopyCapture()? LCK_ByCopy : LCK_ByRef;
+      Captures.push_back(LambdaExpr::Capture(From.getLocation(), IsImplicit, 
+                                             Kind, Var, From.getEllipsisLoc()));
+      CaptureInits.push_back(From.getCopyExpr());
+    }
+
+    switch (LSI->ImpCaptureStyle) {
+    case CapturingScopeInfo::ImpCap_None:
+      CaptureDefault = LCD_None;
+      break;
+
+    case CapturingScopeInfo::ImpCap_LambdaByval:
+      CaptureDefault = LCD_ByCopy;
+      break;
+
+    case CapturingScopeInfo::ImpCap_LambdaByref:
+      CaptureDefault = LCD_ByRef;
+      break;
+
+    case CapturingScopeInfo::ImpCap_Block:
+      llvm_unreachable("block capture in lambda");
+      break;
+    }
+
+    // C++11 [expr.prim.lambda]p4:
+    //   If a lambda-expression does not include a
+    //   trailing-return-type, it is as if the trailing-return-type
+    //   denotes the following type:
+    // FIXME: Assumes current resolution to core issue 975.
+    if (LSI->HasImplicitReturnType) {
+      //   - if there are no return statements in the
+      //     compound-statement, or all return statements return
+      //     either an expression of type void or no expression or
+      //     braced-init-list, the type void;
+      if (LSI->ReturnType.isNull()) {
+        LSI->ReturnType = Context.VoidTy;
+      } else {
+        // C++11 [expr.prim.lambda]p4:
+        //   - if the compound-statement is of the form
+        //
+        //       { attribute-specifier-seq[opt] return expression ; }
+        //
+        //     the type of the returned expression after
+        //     lvalue-to-rvalue conversion (4.1), array-to-pointer
+        //     conver- sion (4.2), and function-to-pointer conversion
+        //     (4.3);
+        //
+        // Since we're accepting the resolution to a post-C++11 core
+        // issue with a non-trivial extension, provide a warning (by
+        // default).
+        CompoundStmt *CompoundBody = cast<CompoundStmt>(Body);
+        if (!(CompoundBody->size() == 1 &&
+              isa<ReturnStmt>(*CompoundBody->body_begin())) &&
+            !Context.hasSameType(LSI->ReturnType, Context.VoidTy))
+          Diag(IntroducerRange.getBegin(), 
+               diag::ext_lambda_implies_void_return);
+      }
+
+      // Create a function type with the inferred return type.
+      const FunctionProtoType *Proto
+        = CallOperator->getType()->getAs<FunctionProtoType>();
+      QualType FunctionTy
+        = Context.getFunctionType(LSI->ReturnType,
+                                  Proto->arg_type_begin(),
+                                  Proto->getNumArgs(),
+                                  Proto->getExtProtoInfo());
+      CallOperator->setType(FunctionTy);
+    }
+
+    // C++ [expr.prim.lambda]p7:
+    //   The lambda-expression's compound-statement yields the
+    //   function-body (8.4) of the function call operator [...].
+    ActOnFinishFunctionBody(CallOperator, Body, IsInstantiation);
+    CallOperator->setLexicalDeclContext(Class);
+    Class->addDecl(CallOperator);
+    PopExpressionEvaluationContext();
+
+    // C++11 [expr.prim.lambda]p6:
+    //   The closure type for a lambda-expression with no lambda-capture
+    //   has a public non-virtual non-explicit const conversion function
+    //   to pointer to function having the same parameter and return
+    //   types as the closure type's function call operator.
+    if (Captures.empty() && CaptureDefault == LCD_None)
+      addFunctionPointerConversion(*this, IntroducerRange, Class,
+                                   CallOperator);
+
+    // Objective-C++:
+    //   The closure type for a lambda-expression has a public non-virtual
+    //   non-explicit const conversion function to a block pointer having the
+    //   same parameter and return types as the closure type's function call
+    //   operator.
+    if (getLangOpts().Blocks && getLangOpts().ObjC1)
+      addBlockPointerConversion(*this, IntroducerRange, Class, CallOperator);
+    
+    // Finalize the lambda class.
+    SmallVector<Decl*, 4> Fields(Class->field_begin(), Class->field_end());
+    ActOnFields(0, Class->getLocation(), Class, Fields, 
+                SourceLocation(), SourceLocation(), 0);
+    CheckCompletedCXXClass(Class);
+  }
+
+  if (LambdaExprNeedsCleanups)
+    ExprNeedsCleanups = true;
+  
+  LambdaExpr *Lambda = LambdaExpr::Create(Context, Class, IntroducerRange, 
+                                          CaptureDefault, Captures, 
+                                          ExplicitParams, ExplicitResultType,
+                                          CaptureInits, ArrayIndexVars, 
+                                          ArrayIndexStarts, Body->getLocEnd());
+
+  // C++11 [expr.prim.lambda]p2:
+  //   A lambda-expression shall not appear in an unevaluated operand
+  //   (Clause 5).
+  if (!CurContext->isDependentContext()) {
+    switch (ExprEvalContexts.back().Context) {
+    case Unevaluated:
+      // We don't actually diagnose this case immediately, because we
+      // could be within a context where we might find out later that
+      // the expression is potentially evaluated (e.g., for typeid).
+      ExprEvalContexts.back().Lambdas.push_back(Lambda);
+      break;
+
+    case ConstantEvaluated:
+    case PotentiallyEvaluated:
+    case PotentiallyEvaluatedIfUsed:
+      break;
+    }
+  }
+  
+  return MaybeBindToTemporary(Lambda);
+}
+
+ExprResult Sema::BuildBlockForLambdaConversion(SourceLocation CurrentLocation,
+                                               SourceLocation ConvLocation,
+                                               CXXConversionDecl *Conv,
+                                               Expr *Src) {
+  // Make sure that the lambda call operator is marked used.
+  CXXRecordDecl *Lambda = Conv->getParent();
+  CXXMethodDecl *CallOperator 
+    = cast<CXXMethodDecl>(
+        *Lambda->lookup(
+          Context.DeclarationNames.getCXXOperatorName(OO_Call)).first);
+  CallOperator->setReferenced();
+  CallOperator->setUsed();
+
+  ExprResult Init = PerformCopyInitialization(
+                      InitializedEntity::InitializeBlock(ConvLocation, 
+                                                         Src->getType(), 
+                                                         /*NRVO=*/false),
+                      CurrentLocation, Src);
+  if (!Init.isInvalid())
+    Init = ActOnFinishFullExpr(Init.take());
+  
+  if (Init.isInvalid())
+    return ExprError();
+  
+  // Create the new block to be returned.
+  BlockDecl *Block = BlockDecl::Create(Context, CurContext, ConvLocation);
+
+  // Set the type information.
+  Block->setSignatureAsWritten(CallOperator->getTypeSourceInfo());
+  Block->setIsVariadic(CallOperator->isVariadic());
+  Block->setBlockMissingReturnType(false);
+
+  // Add parameters.
+  SmallVector<ParmVarDecl *, 4> BlockParams;
+  for (unsigned I = 0, N = CallOperator->getNumParams(); I != N; ++I) {
+    ParmVarDecl *From = CallOperator->getParamDecl(I);
+    BlockParams.push_back(ParmVarDecl::Create(Context, Block,
+                                              From->getLocStart(),
+                                              From->getLocation(),
+                                              From->getIdentifier(),
+                                              From->getType(),
+                                              From->getTypeSourceInfo(),
+                                              From->getStorageClass(),
+                                            From->getStorageClassAsWritten(),
+                                              /*DefaultArg=*/0));
+  }
+  Block->setParams(BlockParams);
+
+  Block->setIsConversionFromLambda(true);
+
+  // Add capture. The capture uses a fake variable, which doesn't correspond
+  // to any actual memory location. However, the initializer copy-initializes
+  // the lambda object.
+  TypeSourceInfo *CapVarTSI =
+      Context.getTrivialTypeSourceInfo(Src->getType());
+  VarDecl *CapVar = VarDecl::Create(Context, Block, ConvLocation,
+                                    ConvLocation, 0,
+                                    Src->getType(), CapVarTSI,
+                                    SC_None, SC_None);
+  BlockDecl::Capture Capture(/*Variable=*/CapVar, /*ByRef=*/false,
+                             /*Nested=*/false, /*Copy=*/Init.take());
+  Block->setCaptures(Context, &Capture, &Capture + 1, 
+                     /*CapturesCXXThis=*/false);
+
+  // Add a fake function body to the block. IR generation is responsible
+  // for filling in the actual body, which cannot be expressed as an AST.
+  Block->setBody(new (Context) CompoundStmt(Context, 0, 0, 
+                                            ConvLocation,
+                                            ConvLocation));
+
+  // Create the block literal expression.
+  Expr *BuildBlock = new (Context) BlockExpr(Block, Conv->getConversionType());
+  ExprCleanupObjects.push_back(Block);
+  ExprNeedsCleanups = true;
+
+  return BuildBlock;
+}
diff --git a/clang/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp
new file mode 100644
index 0000000..9f5138b
--- /dev/null
+++ b/clang/lib/Sema/SemaLookup.cpp
@@ -0,0 +1,4060 @@
+//===--------------------- SemaLookup.cpp - Name Lookup  ------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+//  This file implements name lookup for C, C++, Objective-C, and
+//  Objective-C++.
+//
+//===----------------------------------------------------------------------===//
+#include "clang/Sema/Sema.h"
+#include "clang/Sema/SemaInternal.h"
+#include "clang/Sema/Lookup.h"
+#include "clang/Sema/Overload.h"
+#include "clang/Sema/DeclSpec.h"
+#include "clang/Sema/Scope.h"
+#include "clang/Sema/ScopeInfo.h"
+#include "clang/Sema/TemplateDeduction.h"
+#include "clang/Sema/ExternalSemaSource.h"
+#include "clang/Sema/TypoCorrection.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/CXXInheritance.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclCXX.h"
+#include "clang/AST/DeclLookups.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/AST/DeclTemplate.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/ExprCXX.h"
+#include "clang/Basic/Builtins.h"
+#include "clang/Basic/LangOptions.h"
+#include "llvm/ADT/SetVector.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/ADT/TinyPtrVector.h"
+#include "llvm/ADT/edit_distance.h"
+#include "llvm/Support/ErrorHandling.h"
+#include <algorithm>
+#include <iterator>
+#include <limits>
+#include <list>
+#include <map>
+#include <set>
+#include <utility>
+#include <vector>
+
+using namespace clang;
+using namespace sema;
+
+namespace {
+  class UnqualUsingEntry {
+    const DeclContext *Nominated;
+    const DeclContext *CommonAncestor;
+
+  public:
+    UnqualUsingEntry(const DeclContext *Nominated,
+                     const DeclContext *CommonAncestor)
+      : Nominated(Nominated), CommonAncestor(CommonAncestor) {
+    }
+
+    const DeclContext *getCommonAncestor() const {
+      return CommonAncestor;
+    }
+
+    const DeclContext *getNominatedNamespace() const {
+      return Nominated;
+    }
+
+    // Sort by the pointer value of the common ancestor.
+    struct Comparator {
+      bool operator()(const UnqualUsingEntry &L, const UnqualUsingEntry &R) {
+        return L.getCommonAncestor() < R.getCommonAncestor();
+      }
+
+      bool operator()(const UnqualUsingEntry &E, const DeclContext *DC) {
+        return E.getCommonAncestor() < DC;
+      }
+
+      bool operator()(const DeclContext *DC, const UnqualUsingEntry &E) {
+        return DC < E.getCommonAncestor();
+      }
+    };
+  };
+
+  /// A collection of using directives, as used by C++ unqualified
+  /// lookup.
+  class UnqualUsingDirectiveSet {
+    typedef SmallVector<UnqualUsingEntry, 8> ListTy;
+
+    ListTy list;
+    llvm::SmallPtrSet<DeclContext*, 8> visited;
+
+  public:
+    UnqualUsingDirectiveSet() {}
+
+    void visitScopeChain(Scope *S, Scope *InnermostFileScope) {
+      // C++ [namespace.udir]p1:
+      //   During unqualified name lookup, the names appear as if they
+      //   were declared in the nearest enclosing namespace which contains
+      //   both the using-directive and the nominated namespace.
+      DeclContext *InnermostFileDC
+        = static_cast<DeclContext*>(InnermostFileScope->getEntity());
+      assert(InnermostFileDC && InnermostFileDC->isFileContext());
+
+      for (; S; S = S->getParent()) {
+        // C++ [namespace.udir]p1:
+        //   A using-directive shall not appear in class scope, but may
+        //   appear in namespace scope or in block scope.
+        DeclContext *Ctx = static_cast<DeclContext*>(S->getEntity());
+        if (Ctx && Ctx->isFileContext()) {
+          visit(Ctx, Ctx);
+        } else if (!Ctx || Ctx->isFunctionOrMethod()) {
+          Scope::udir_iterator I = S->using_directives_begin(),
+                             End = S->using_directives_end();
+          for (; I != End; ++I)
+            visit(*I, InnermostFileDC);
+        }
+      }
+    }
+
+    // Visits a context and collect all of its using directives
+    // recursively.  Treats all using directives as if they were
+    // declared in the context.
+    //
+    // A given context is only every visited once, so it is important
+    // that contexts be visited from the inside out in order to get
+    // the effective DCs right.
+    void visit(DeclContext *DC, DeclContext *EffectiveDC) {
+      if (!visited.insert(DC))
+        return;
+
+      addUsingDirectives(DC, EffectiveDC);
+    }
+
+    // Visits a using directive and collects all of its using
+    // directives recursively.  Treats all using directives as if they
+    // were declared in the effective DC.
+    void visit(UsingDirectiveDecl *UD, DeclContext *EffectiveDC) {
+      DeclContext *NS = UD->getNominatedNamespace();
+      if (!visited.insert(NS))
+        return;
+
+      addUsingDirective(UD, EffectiveDC);
+      addUsingDirectives(NS, EffectiveDC);
+    }
+
+    // Adds all the using directives in a context (and those nominated
+    // by its using directives, transitively) as if they appeared in
+    // the given effective context.
+    void addUsingDirectives(DeclContext *DC, DeclContext *EffectiveDC) {
+      SmallVector<DeclContext*,4> queue;
+      while (true) {
+        DeclContext::udir_iterator I, End;
+        for (llvm::tie(I, End) = DC->getUsingDirectives(); I != End; ++I) {
+          UsingDirectiveDecl *UD = *I;
+          DeclContext *NS = UD->getNominatedNamespace();
+          if (visited.insert(NS)) {
+            addUsingDirective(UD, EffectiveDC);
+            queue.push_back(NS);
+          }
+        }
+
+        if (queue.empty())
+          return;
+
+        DC = queue.back();
+        queue.pop_back();
+      }
+    }
+
+    // Add a using directive as if it had been declared in the given
+    // context.  This helps implement C++ [namespace.udir]p3:
+    //   The using-directive is transitive: if a scope contains a
+    //   using-directive that nominates a second namespace that itself
+    //   contains using-directives, the effect is as if the
+    //   using-directives from the second namespace also appeared in
+    //   the first.
+    void addUsingDirective(UsingDirectiveDecl *UD, DeclContext *EffectiveDC) {
+      // Find the common ancestor between the effective context and
+      // the nominated namespace.
+      DeclContext *Common = UD->getNominatedNamespace();
+      while (!Common->Encloses(EffectiveDC))
+        Common = Common->getParent();
+      Common = Common->getPrimaryContext();
+
+      list.push_back(UnqualUsingEntry(UD->getNominatedNamespace(), Common));
+    }
+
+    void done() {
+      std::sort(list.begin(), list.end(), UnqualUsingEntry::Comparator());
+    }
+
+    typedef ListTy::const_iterator const_iterator;
+
+    const_iterator begin() const { return list.begin(); }
+    const_iterator end() const { return list.end(); }
+
+    std::pair<const_iterator,const_iterator>
+    getNamespacesFor(DeclContext *DC) const {
+      return std::equal_range(begin(), end(), DC->getPrimaryContext(),
+                              UnqualUsingEntry::Comparator());
+    }
+  };
+}
+
+// Retrieve the set of identifier namespaces that correspond to a
+// specific kind of name lookup.
+static inline unsigned getIDNS(Sema::LookupNameKind NameKind,
+                               bool CPlusPlus,
+                               bool Redeclaration) {
+  unsigned IDNS = 0;
+  switch (NameKind) {
+  case Sema::LookupObjCImplicitSelfParam:
+  case Sema::LookupOrdinaryName:
+  case Sema::LookupRedeclarationWithLinkage:
+    IDNS = Decl::IDNS_Ordinary;
+    if (CPlusPlus) {
+      IDNS |= Decl::IDNS_Tag | Decl::IDNS_Member | Decl::IDNS_Namespace;
+      if (Redeclaration)
+        IDNS |= Decl::IDNS_TagFriend | Decl::IDNS_OrdinaryFriend;
+    }
+    break;
+
+  case Sema::LookupOperatorName:
+    // Operator lookup is its own crazy thing;  it is not the same
+    // as (e.g.) looking up an operator name for redeclaration.
+    assert(!Redeclaration && "cannot do redeclaration operator lookup");
+    IDNS = Decl::IDNS_NonMemberOperator;
+    break;
+
+  case Sema::LookupTagName:
+    if (CPlusPlus) {
+      IDNS = Decl::IDNS_Type;
+
+      // When looking for a redeclaration of a tag name, we add:
+      // 1) TagFriend to find undeclared friend decls
+      // 2) Namespace because they can't "overload" with tag decls.
+      // 3) Tag because it includes class templates, which can't
+      //    "overload" with tag decls.
+      if (Redeclaration)
+        IDNS |= Decl::IDNS_Tag | Decl::IDNS_TagFriend | Decl::IDNS_Namespace;
+    } else {
+      IDNS = Decl::IDNS_Tag;
+    }
+    break;
+  case Sema::LookupLabel:
+    IDNS = Decl::IDNS_Label;
+    break;
+      
+  case Sema::LookupMemberName:
+    IDNS = Decl::IDNS_Member;
+    if (CPlusPlus)
+      IDNS |= Decl::IDNS_Tag | Decl::IDNS_Ordinary;
+    break;
+
+  case Sema::LookupNestedNameSpecifierName:
+    IDNS = Decl::IDNS_Type | Decl::IDNS_Namespace;
+    break;
+
+  case Sema::LookupNamespaceName:
+    IDNS = Decl::IDNS_Namespace;
+    break;
+
+  case Sema::LookupUsingDeclName:
+    IDNS = Decl::IDNS_Ordinary | Decl::IDNS_Tag
+         | Decl::IDNS_Member | Decl::IDNS_Using;
+    break;
+
+  case Sema::LookupObjCProtocolName:
+    IDNS = Decl::IDNS_ObjCProtocol;
+    break;
+
+  case Sema::LookupAnyName:
+    IDNS = Decl::IDNS_Ordinary | Decl::IDNS_Tag | Decl::IDNS_Member
+      | Decl::IDNS_Using | Decl::IDNS_Namespace | Decl::IDNS_ObjCProtocol
+      | Decl::IDNS_Type;
+    break;
+  }
+  return IDNS;
+}
+
+void LookupResult::configure() {
+  IDNS = getIDNS(LookupKind, SemaRef.getLangOpts().CPlusPlus,
+                 isForRedeclaration());
+
+  // If we're looking for one of the allocation or deallocation
+  // operators, make sure that the implicitly-declared new and delete
+  // operators can be found.
+  if (!isForRedeclaration()) {
+    switch (NameInfo.getName().getCXXOverloadedOperator()) {
+    case OO_New:
+    case OO_Delete:
+    case OO_Array_New:
+    case OO_Array_Delete:
+      SemaRef.DeclareGlobalNewDelete();
+      break;
+
+    default:
+      break;
+    }
+  }
+}
+
+void LookupResult::sanityImpl() const {
+  // Note that this function is never called by NDEBUG builds. See
+  // LookupResult::sanity().
+  assert(ResultKind != NotFound || Decls.size() == 0);
+  assert(ResultKind != Found || Decls.size() == 1);
+  assert(ResultKind != FoundOverloaded || Decls.size() > 1 ||
+         (Decls.size() == 1 &&
+          isa<FunctionTemplateDecl>((*begin())->getUnderlyingDecl())));
+  assert(ResultKind != FoundUnresolvedValue || sanityCheckUnresolved());
+  assert(ResultKind != Ambiguous || Decls.size() > 1 ||
+         (Decls.size() == 1 && (Ambiguity == AmbiguousBaseSubobjects ||
+                                Ambiguity == AmbiguousBaseSubobjectTypes)));
+  assert((Paths != NULL) == (ResultKind == Ambiguous &&
+                             (Ambiguity == AmbiguousBaseSubobjectTypes ||
+                              Ambiguity == AmbiguousBaseSubobjects)));
+}
+
+// Necessary because CXXBasePaths is not complete in Sema.h
+void LookupResult::deletePaths(CXXBasePaths *Paths) {
+  delete Paths;
+}
+
+static NamedDecl *getVisibleDecl(NamedDecl *D);
+
+NamedDecl *LookupResult::getAcceptableDeclSlow(NamedDecl *D) const {
+  return getVisibleDecl(D);
+}
+
+/// Resolves the result kind of this lookup.
+void LookupResult::resolveKind() {
+  unsigned N = Decls.size();
+
+  // Fast case: no possible ambiguity.
+  if (N == 0) {
+    assert(ResultKind == NotFound || ResultKind == NotFoundInCurrentInstantiation);
+    return;
+  }
+
+  // If there's a single decl, we need to examine it to decide what
+  // kind of lookup this is.
+  if (N == 1) {
+    NamedDecl *D = (*Decls.begin())->getUnderlyingDecl();
+    if (isa<FunctionTemplateDecl>(D))
+      ResultKind = FoundOverloaded;
+    else if (isa<UnresolvedUsingValueDecl>(D))
+      ResultKind = FoundUnresolvedValue;
+    return;
+  }
+
+  // Don't do any extra resolution if we've already resolved as ambiguous.
+  if (ResultKind == Ambiguous) return;
+
+  llvm::SmallPtrSet<NamedDecl*, 16> Unique;
+  llvm::SmallPtrSet<QualType, 16> UniqueTypes;
+
+  bool Ambiguous = false;
+  bool HasTag = false, HasFunction = false, HasNonFunction = false;
+  bool HasFunctionTemplate = false, HasUnresolved = false;
+
+  unsigned UniqueTagIndex = 0;
+
+  unsigned I = 0;
+  while (I < N) {
+    NamedDecl *D = Decls[I]->getUnderlyingDecl();
+    D = cast<NamedDecl>(D->getCanonicalDecl());
+
+    // Redeclarations of types via typedef can occur both within a scope
+    // and, through using declarations and directives, across scopes. There is
+    // no ambiguity if they all refer to the same type, so unique based on the
+    // canonical type.
+    if (TypeDecl *TD = dyn_cast<TypeDecl>(D)) {
+      if (!TD->getDeclContext()->isRecord()) {
+        QualType T = SemaRef.Context.getTypeDeclType(TD);
+        if (!UniqueTypes.insert(SemaRef.Context.getCanonicalType(T))) {
+          // The type is not unique; pull something off the back and continue
+          // at this index.
+          Decls[I] = Decls[--N];
+          continue;
+        }
+      }
+    }
+
+    if (!Unique.insert(D)) {
+      // If it's not unique, pull something off the back (and
+      // continue at this index).
+      Decls[I] = Decls[--N];
+      continue;
+    }
+
+    // Otherwise, do some decl type analysis and then continue.
+
+    if (isa<UnresolvedUsingValueDecl>(D)) {
+      HasUnresolved = true;
+    } else if (isa<TagDecl>(D)) {
+      if (HasTag)
+        Ambiguous = true;
+      UniqueTagIndex = I;
+      HasTag = true;
+    } else if (isa<FunctionTemplateDecl>(D)) {
+      HasFunction = true;
+      HasFunctionTemplate = true;
+    } else if (isa<FunctionDecl>(D)) {
+      HasFunction = true;
+    } else {
+      if (HasNonFunction)
+        Ambiguous = true;
+      HasNonFunction = true;
+    }
+    I++;
+  }
+
+  // C++ [basic.scope.hiding]p2:
+  //   A class name or enumeration name can be hidden by the name of
+  //   an object, function, or enumerator declared in the same
+  //   scope. If a class or enumeration name and an object, function,
+  //   or enumerator are declared in the same scope (in any order)
+  //   with the same name, the class or enumeration name is hidden
+  //   wherever the object, function, or enumerator name is visible.
+  // But it's still an error if there are distinct tag types found,
+  // even if they're not visible. (ref?)
+  if (HideTags && HasTag && !Ambiguous &&
+      (HasFunction || HasNonFunction || HasUnresolved)) {
+    if (Decls[UniqueTagIndex]->getDeclContext()->getRedeclContext()->Equals(
+         Decls[UniqueTagIndex? 0 : N-1]->getDeclContext()->getRedeclContext()))
+      Decls[UniqueTagIndex] = Decls[--N];
+    else
+      Ambiguous = true;
+  }
+
+  Decls.set_size(N);
+
+  if (HasNonFunction && (HasFunction || HasUnresolved))
+    Ambiguous = true;
+
+  if (Ambiguous)
+    setAmbiguous(LookupResult::AmbiguousReference);
+  else if (HasUnresolved)
+    ResultKind = LookupResult::FoundUnresolvedValue;
+  else if (N > 1 || HasFunctionTemplate)
+    ResultKind = LookupResult::FoundOverloaded;
+  else
+    ResultKind = LookupResult::Found;
+}
+
+void LookupResult::addDeclsFromBasePaths(const CXXBasePaths &P) {
+  CXXBasePaths::const_paths_iterator I, E;
+  DeclContext::lookup_iterator DI, DE;
+  for (I = P.begin(), E = P.end(); I != E; ++I)
+    for (llvm::tie(DI,DE) = I->Decls; DI != DE; ++DI)
+      addDecl(*DI);
+}
+
+void LookupResult::setAmbiguousBaseSubobjects(CXXBasePaths &P) {
+  Paths = new CXXBasePaths;
+  Paths->swap(P);
+  addDeclsFromBasePaths(*Paths);
+  resolveKind();
+  setAmbiguous(AmbiguousBaseSubobjects);
+}
+
+void LookupResult::setAmbiguousBaseSubobjectTypes(CXXBasePaths &P) {
+  Paths = new CXXBasePaths;
+  Paths->swap(P);
+  addDeclsFromBasePaths(*Paths);
+  resolveKind();
+  setAmbiguous(AmbiguousBaseSubobjectTypes);
+}
+
+void LookupResult::print(raw_ostream &Out) {
+  Out << Decls.size() << " result(s)";
+  if (isAmbiguous()) Out << ", ambiguous";
+  if (Paths) Out << ", base paths present";
+
+  for (iterator I = begin(), E = end(); I != E; ++I) {
+    Out << "\n";
+    (*I)->print(Out, 2);
+  }
+}
+
+/// \brief Lookup a builtin function, when name lookup would otherwise
+/// fail.
+static bool LookupBuiltin(Sema &S, LookupResult &R) {
+  Sema::LookupNameKind NameKind = R.getLookupKind();
+
+  // If we didn't find a use of this identifier, and if the identifier
+  // corresponds to a compiler builtin, create the decl object for the builtin
+  // now, injecting it into translation unit scope, and return it.
+  if (NameKind == Sema::LookupOrdinaryName ||
+      NameKind == Sema::LookupRedeclarationWithLinkage) {
+    IdentifierInfo *II = R.getLookupName().getAsIdentifierInfo();
+    if (II) {
+      // If this is a builtin on this (or all) targets, create the decl.
+      if (unsigned BuiltinID = II->getBuiltinID()) {
+        // In C++, we don't have any predefined library functions like
+        // 'malloc'. Instead, we'll just error.
+        if (S.getLangOpts().CPlusPlus &&
+            S.Context.BuiltinInfo.isPredefinedLibFunction(BuiltinID))
+          return false;
+
+        if (NamedDecl *D = S.LazilyCreateBuiltin((IdentifierInfo *)II,
+                                                 BuiltinID, S.TUScope,
+                                                 R.isForRedeclaration(),
+                                                 R.getNameLoc())) {
+          R.addDecl(D);
+          return true;
+        }
+
+        if (R.isForRedeclaration()) {
+          // If we're redeclaring this function anyway, forget that
+          // this was a builtin at all.
+          S.Context.BuiltinInfo.ForgetBuiltin(BuiltinID, S.Context.Idents);
+        }
+
+        return false;
+      }
+    }
+  }
+
+  return false;
+}
+
+/// \brief Determine whether we can declare a special member function within
+/// the class at this point.
+static bool CanDeclareSpecialMemberFunction(ASTContext &Context,
+                                            const CXXRecordDecl *Class) {
+  // We need to have a definition for the class.
+  if (!Class->getDefinition() || Class->isDependentContext())
+    return false;
+
+  // We can't be in the middle of defining the class.
+  if (const RecordType *RecordTy
+                        = Context.getTypeDeclType(Class)->getAs<RecordType>())
+    return !RecordTy->isBeingDefined();
+
+  return false;
+}
+
+void Sema::ForceDeclarationOfImplicitMembers(CXXRecordDecl *Class) {
+  if (!CanDeclareSpecialMemberFunction(Context, Class))
+    return;
+
+  // If the default constructor has not yet been declared, do so now.
+  if (Class->needsImplicitDefaultConstructor())
+    DeclareImplicitDefaultConstructor(Class);
+
+  // If the copy constructor has not yet been declared, do so now.
+  if (!Class->hasDeclaredCopyConstructor())
+    DeclareImplicitCopyConstructor(Class);
+
+  // If the copy assignment operator has not yet been declared, do so now.
+  if (!Class->hasDeclaredCopyAssignment())
+    DeclareImplicitCopyAssignment(Class);
+
+  if (getLangOpts().CPlusPlus0x) {
+    // If the move constructor has not yet been declared, do so now.
+    if (Class->needsImplicitMoveConstructor())
+      DeclareImplicitMoveConstructor(Class); // might not actually do it
+
+    // If the move assignment operator has not yet been declared, do so now.
+    if (Class->needsImplicitMoveAssignment())
+      DeclareImplicitMoveAssignment(Class); // might not actually do it
+  }
+
+  // If the destructor has not yet been declared, do so now.
+  if (!Class->hasDeclaredDestructor())
+    DeclareImplicitDestructor(Class);
+}
+
+/// \brief Determine whether this is the name of an implicitly-declared
+/// special member function.
+static bool isImplicitlyDeclaredMemberFunctionName(DeclarationName Name) {
+  switch (Name.getNameKind()) {
+  case DeclarationName::CXXConstructorName:
+  case DeclarationName::CXXDestructorName:
+    return true;
+
+  case DeclarationName::CXXOperatorName:
+    return Name.getCXXOverloadedOperator() == OO_Equal;
+
+  default:
+    break;
+  }
+
+  return false;
+}
+
+/// \brief If there are any implicit member functions with the given name
+/// that need to be declared in the given declaration context, do so.
+static void DeclareImplicitMemberFunctionsWithName(Sema &S,
+                                                   DeclarationName Name,
+                                                   const DeclContext *DC) {
+  if (!DC)
+    return;
+
+  switch (Name.getNameKind()) {
+  case DeclarationName::CXXConstructorName:
+    if (const CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(DC))
+      if (Record->getDefinition() &&
+          CanDeclareSpecialMemberFunction(S.Context, Record)) {
+        CXXRecordDecl *Class = const_cast<CXXRecordDecl *>(Record);
+        if (Record->needsImplicitDefaultConstructor())
+          S.DeclareImplicitDefaultConstructor(Class);
+        if (!Record->hasDeclaredCopyConstructor())
+          S.DeclareImplicitCopyConstructor(Class);
+        if (S.getLangOpts().CPlusPlus0x &&
+            Record->needsImplicitMoveConstructor())
+          S.DeclareImplicitMoveConstructor(Class);
+      }
+    break;
+
+  case DeclarationName::CXXDestructorName:
+    if (const CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(DC))
+      if (Record->getDefinition() && !Record->hasDeclaredDestructor() &&
+          CanDeclareSpecialMemberFunction(S.Context, Record))
+        S.DeclareImplicitDestructor(const_cast<CXXRecordDecl *>(Record));
+    break;
+
+  case DeclarationName::CXXOperatorName:
+    if (Name.getCXXOverloadedOperator() != OO_Equal)
+      break;
+
+    if (const CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(DC)) {
+      if (Record->getDefinition() &&
+          CanDeclareSpecialMemberFunction(S.Context, Record)) {
+        CXXRecordDecl *Class = const_cast<CXXRecordDecl *>(Record);
+        if (!Record->hasDeclaredCopyAssignment())
+          S.DeclareImplicitCopyAssignment(Class);
+        if (S.getLangOpts().CPlusPlus0x &&
+            Record->needsImplicitMoveAssignment())
+          S.DeclareImplicitMoveAssignment(Class);
+      }
+    }
+    break;
+
+  default:
+    break;
+  }
+}
+
+// Adds all qualifying matches for a name within a decl context to the
+// given lookup result.  Returns true if any matches were found.
+static bool LookupDirect(Sema &S, LookupResult &R, const DeclContext *DC) {
+  bool Found = false;
+
+  // Lazily declare C++ special member functions.
+  if (S.getLangOpts().CPlusPlus)
+    DeclareImplicitMemberFunctionsWithName(S, R.getLookupName(), DC);
+
+  // Perform lookup into this declaration context.
+  DeclContext::lookup_const_iterator I, E;
+  for (llvm::tie(I, E) = DC->lookup(R.getLookupName()); I != E; ++I) {
+    NamedDecl *D = *I;
+    if ((D = R.getAcceptableDecl(D))) {
+      R.addDecl(D);
+      Found = true;
+    }
+  }
+
+  if (!Found && DC->isTranslationUnit() && LookupBuiltin(S, R))
+    return true;
+
+  if (R.getLookupName().getNameKind()
+        != DeclarationName::CXXConversionFunctionName ||
+      R.getLookupName().getCXXNameType()->isDependentType() ||
+      !isa<CXXRecordDecl>(DC))
+    return Found;
+
+  // C++ [temp.mem]p6:
+  //   A specialization of a conversion function template is not found by
+  //   name lookup. Instead, any conversion function templates visible in the
+  //   context of the use are considered. [...]
+  const CXXRecordDecl *Record = cast<CXXRecordDecl>(DC);
+  if (!Record->isCompleteDefinition())
+    return Found;
+
+  const UnresolvedSetImpl *Unresolved = Record->getConversionFunctions();
+  for (UnresolvedSetImpl::iterator U = Unresolved->begin(),
+         UEnd = Unresolved->end(); U != UEnd; ++U) {
+    FunctionTemplateDecl *ConvTemplate = dyn_cast<FunctionTemplateDecl>(*U);
+    if (!ConvTemplate)
+      continue;
+
+    // When we're performing lookup for the purposes of redeclaration, just
+    // add the conversion function template. When we deduce template
+    // arguments for specializations, we'll end up unifying the return
+    // type of the new declaration with the type of the function template.
+    if (R.isForRedeclaration()) {
+      R.addDecl(ConvTemplate);
+      Found = true;
+      continue;
+    }
+
+    // C++ [temp.mem]p6:
+    //   [...] For each such operator, if argument deduction succeeds
+    //   (14.9.2.3), the resulting specialization is used as if found by
+    //   name lookup.
+    //
+    // When referencing a conversion function for any purpose other than
+    // a redeclaration (such that we'll be building an expression with the
+    // result), perform template argument deduction and place the
+    // specialization into the result set. We do this to avoid forcing all
+    // callers to perform special deduction for conversion functions.
+    TemplateDeductionInfo Info(R.getSema().Context, R.getNameLoc());
+    FunctionDecl *Specialization = 0;
+
+    const FunctionProtoType *ConvProto
+      = ConvTemplate->getTemplatedDecl()->getType()->getAs<FunctionProtoType>();
+    assert(ConvProto && "Nonsensical conversion function template type");
+
+    // Compute the type of the function that we would expect the conversion
+    // function to have, if it were to match the name given.
+    // FIXME: Calling convention!
+    FunctionProtoType::ExtProtoInfo EPI = ConvProto->getExtProtoInfo();
+    EPI.ExtInfo = EPI.ExtInfo.withCallingConv(CC_Default);
+    EPI.ExceptionSpecType = EST_None;
+    EPI.NumExceptions = 0;
+    QualType ExpectedType
+      = R.getSema().Context.getFunctionType(R.getLookupName().getCXXNameType(),
+                                            0, 0, EPI);
+
+    // Perform template argument deduction against the type that we would
+    // expect the function to have.
+    if (R.getSema().DeduceTemplateArguments(ConvTemplate, 0, ExpectedType,
+                                            Specialization, Info)
+          == Sema::TDK_Success) {
+      R.addDecl(Specialization);
+      Found = true;
+    }
+  }
+
+  return Found;
+}
+
+// Performs C++ unqualified lookup into the given file context.
+static bool
+CppNamespaceLookup(Sema &S, LookupResult &R, ASTContext &Context,
+                   DeclContext *NS, UnqualUsingDirectiveSet &UDirs) {
+
+  assert(NS && NS->isFileContext() && "CppNamespaceLookup() requires namespace!");
+
+  // Perform direct name lookup into the LookupCtx.
+  bool Found = LookupDirect(S, R, NS);
+
+  // Perform direct name lookup into the namespaces nominated by the
+  // using directives whose common ancestor is this namespace.
+  UnqualUsingDirectiveSet::const_iterator UI, UEnd;
+  llvm::tie(UI, UEnd) = UDirs.getNamespacesFor(NS);
+
+  for (; UI != UEnd; ++UI)
+    if (LookupDirect(S, R, UI->getNominatedNamespace()))
+      Found = true;
+
+  R.resolveKind();
+
+  return Found;
+}
+
+static bool isNamespaceOrTranslationUnitScope(Scope *S) {
+  if (DeclContext *Ctx = static_cast<DeclContext*>(S->getEntity()))
+    return Ctx->isFileContext();
+  return false;
+}
+
+// Find the next outer declaration context from this scope. This
+// routine actually returns the semantic outer context, which may
+// differ from the lexical context (encoded directly in the Scope
+// stack) when we are parsing a member of a class template. In this
+// case, the second element of the pair will be true, to indicate that
+// name lookup should continue searching in this semantic context when
+// it leaves the current template parameter scope.
+static std::pair<DeclContext *, bool> findOuterContext(Scope *S) {
+  DeclContext *DC = static_cast<DeclContext *>(S->getEntity());
+  DeclContext *Lexical = 0;
+  for (Scope *OuterS = S->getParent(); OuterS;
+       OuterS = OuterS->getParent()) {
+    if (OuterS->getEntity()) {
+      Lexical = static_cast<DeclContext *>(OuterS->getEntity());
+      break;
+    }
+  }
+
+  // C++ [temp.local]p8:
+  //   In the definition of a member of a class template that appears
+  //   outside of the namespace containing the class template
+  //   definition, the name of a template-parameter hides the name of
+  //   a member of this namespace.
+  //
+  // Example:
+  //
+  //   namespace N {
+  //     class C { };
+  //
+  //     template<class T> class B {
+  //       void f(T);
+  //     };
+  //   }
+  //
+  //   template<class C> void N::B<C>::f(C) {
+  //     C b;  // C is the template parameter, not N::C
+  //   }
+  //
+  // In this example, the lexical context we return is the
+  // TranslationUnit, while the semantic context is the namespace N.
+  if (!Lexical || !DC || !S->getParent() ||
+      !S->getParent()->isTemplateParamScope())
+    return std::make_pair(Lexical, false);
+
+  // Find the outermost template parameter scope.
+  // For the example, this is the scope for the template parameters of
+  // template<class C>.
+  Scope *OutermostTemplateScope = S->getParent();
+  while (OutermostTemplateScope->getParent() &&
+         OutermostTemplateScope->getParent()->isTemplateParamScope())
+    OutermostTemplateScope = OutermostTemplateScope->getParent();
+
+  // Find the namespace context in which the original scope occurs. In
+  // the example, this is namespace N.
+  DeclContext *Semantic = DC;
+  while (!Semantic->isFileContext())
+    Semantic = Semantic->getParent();
+
+  // Find the declaration context just outside of the template
+  // parameter scope. This is the context in which the template is
+  // being lexically declaration (a namespace context). In the
+  // example, this is the global scope.
+  if (Lexical->isFileContext() && !Lexical->Equals(Semantic) &&
+      Lexical->Encloses(Semantic))
+    return std::make_pair(Semantic, true);
+
+  return std::make_pair(Lexical, false);
+}
+
+bool Sema::CppLookupName(LookupResult &R, Scope *S) {
+  assert(getLangOpts().CPlusPlus && "Can perform only C++ lookup");
+
+  DeclarationName Name = R.getLookupName();
+
+  // If this is the name of an implicitly-declared special member function,
+  // go through the scope stack to implicitly declare
+  if (isImplicitlyDeclaredMemberFunctionName(Name)) {
+    for (Scope *PreS = S; PreS; PreS = PreS->getParent())
+      if (DeclContext *DC = static_cast<DeclContext *>(PreS->getEntity()))
+        DeclareImplicitMemberFunctionsWithName(*this, Name, DC);
+  }
+
+  // Implicitly declare member functions with the name we're looking for, if in
+  // fact we are in a scope where it matters.
+
+  Scope *Initial = S;
+  IdentifierResolver::iterator
+    I = IdResolver.begin(Name),
+    IEnd = IdResolver.end();
+
+  // First we lookup local scope.
+  // We don't consider using-directives, as per 7.3.4.p1 [namespace.udir]
+  // ...During unqualified name lookup (3.4.1), the names appear as if
+  // they were declared in the nearest enclosing namespace which contains
+  // both the using-directive and the nominated namespace.
+  // [Note: in this context, "contains" means "contains directly or
+  // indirectly".
+  //
+  // For example:
+  // namespace A { int i; }
+  // void foo() {
+  //   int i;
+  //   {
+  //     using namespace A;
+  //     ++i; // finds local 'i', A::i appears at global scope
+  //   }
+  // }
+  //
+  DeclContext *OutsideOfTemplateParamDC = 0;
+  for (; S && !isNamespaceOrTranslationUnitScope(S); S = S->getParent()) {
+    DeclContext *Ctx = static_cast<DeclContext*>(S->getEntity());
+
+    // Check whether the IdResolver has anything in this scope.
+    bool Found = false;
+    for (; I != IEnd && S->isDeclScope(*I); ++I) {
+      if (NamedDecl *ND = R.getAcceptableDecl(*I)) {
+        Found = true;
+        R.addDecl(ND);
+      }
+    }
+    if (Found) {
+      R.resolveKind();
+      if (S->isClassScope())
+        if (CXXRecordDecl *Record = dyn_cast_or_null<CXXRecordDecl>(Ctx))
+          R.setNamingClass(Record);
+      return true;
+    }
+
+    if (!Ctx && S->isTemplateParamScope() && OutsideOfTemplateParamDC &&
+        S->getParent() && !S->getParent()->isTemplateParamScope()) {
+      // We've just searched the last template parameter scope and
+      // found nothing, so look into the the contexts between the
+      // lexical and semantic declaration contexts returned by
+      // findOuterContext(). This implements the name lookup behavior
+      // of C++ [temp.local]p8.
+      Ctx = OutsideOfTemplateParamDC;
+      OutsideOfTemplateParamDC = 0;
+    }
+
+    if (Ctx) {
+      DeclContext *OuterCtx;
+      bool SearchAfterTemplateScope;
+      llvm::tie(OuterCtx, SearchAfterTemplateScope) = findOuterContext(S);
+      if (SearchAfterTemplateScope)
+        OutsideOfTemplateParamDC = OuterCtx;
+
+      for (; Ctx && !Ctx->Equals(OuterCtx); Ctx = Ctx->getLookupParent()) {
+        // We do not directly look into transparent contexts, since
+        // those entities will be found in the nearest enclosing
+        // non-transparent context.
+        if (Ctx->isTransparentContext())
+          continue;
+
+        // We do not look directly into function or method contexts,
+        // since all of the local variables and parameters of the
+        // function/method are present within the Scope.
+        if (Ctx->isFunctionOrMethod()) {
+          // If we have an Objective-C instance method, look for ivars
+          // in the corresponding interface.
+          if (ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(Ctx)) {
+            if (Method->isInstanceMethod() && Name.getAsIdentifierInfo())
+              if (ObjCInterfaceDecl *Class = Method->getClassInterface()) {
+                ObjCInterfaceDecl *ClassDeclared;
+                if (ObjCIvarDecl *Ivar = Class->lookupInstanceVariable(
+                                                 Name.getAsIdentifierInfo(),
+                                                             ClassDeclared)) {
+                  if (NamedDecl *ND = R.getAcceptableDecl(Ivar)) {
+                    R.addDecl(ND);
+                    R.resolveKind();
+                    return true;
+                  }
+                }
+              }
+          }
+
+          continue;
+        }
+
+        // Perform qualified name lookup into this context.
+        // FIXME: In some cases, we know that every name that could be found by
+        // this qualified name lookup will also be on the identifier chain. For
+        // example, inside a class without any base classes, we never need to
+        // perform qualified lookup because all of the members are on top of the
+        // identifier chain.
+        if (LookupQualifiedName(R, Ctx, /*InUnqualifiedLookup=*/true))
+          return true;
+      }
+    }
+  }
+
+  // Stop if we ran out of scopes.
+  // FIXME:  This really, really shouldn't be happening.
+  if (!S) return false;
+
+  // If we are looking for members, no need to look into global/namespace scope.
+  if (R.getLookupKind() == LookupMemberName)
+    return false;
+
+  // Collect UsingDirectiveDecls in all scopes, and recursively all
+  // nominated namespaces by those using-directives.
+  //
+  // FIXME: Cache this sorted list in Scope structure, and DeclContext, so we
+  // don't build it for each lookup!
+
+  UnqualUsingDirectiveSet UDirs;
+  UDirs.visitScopeChain(Initial, S);
+  UDirs.done();
+
+  // Lookup namespace scope, and global scope.
+  // Unqualified name lookup in C++ requires looking into scopes
+  // that aren't strictly lexical, and therefore we walk through the
+  // context as well as walking through the scopes.
+
+  for (; S; S = S->getParent()) {
+    // Check whether the IdResolver has anything in this scope.
+    bool Found = false;
+    for (; I != IEnd && S->isDeclScope(*I); ++I) {
+      if (NamedDecl *ND = R.getAcceptableDecl(*I)) {
+        // We found something.  Look for anything else in our scope
+        // with this same name and in an acceptable identifier
+        // namespace, so that we can construct an overload set if we
+        // need to.
+        Found = true;
+        R.addDecl(ND);
+      }
+    }
+
+    if (Found && S->isTemplateParamScope()) {
+      R.resolveKind();
+      return true;
+    }
+
+    DeclContext *Ctx = static_cast<DeclContext *>(S->getEntity());
+    if (!Ctx && S->isTemplateParamScope() && OutsideOfTemplateParamDC &&
+        S->getParent() && !S->getParent()->isTemplateParamScope()) {
+      // We've just searched the last template parameter scope and
+      // found nothing, so look into the the contexts between the
+      // lexical and semantic declaration contexts returned by
+      // findOuterContext(). This implements the name lookup behavior
+      // of C++ [temp.local]p8.
+      Ctx = OutsideOfTemplateParamDC;
+      OutsideOfTemplateParamDC = 0;
+    }
+
+    if (Ctx) {
+      DeclContext *OuterCtx;
+      bool SearchAfterTemplateScope;
+      llvm::tie(OuterCtx, SearchAfterTemplateScope) = findOuterContext(S);
+      if (SearchAfterTemplateScope)
+        OutsideOfTemplateParamDC = OuterCtx;
+
+      for (; Ctx && !Ctx->Equals(OuterCtx); Ctx = Ctx->getLookupParent()) {
+        // We do not directly look into transparent contexts, since
+        // those entities will be found in the nearest enclosing
+        // non-transparent context.
+        if (Ctx->isTransparentContext())
+          continue;
+
+        // If we have a context, and it's not a context stashed in the
+        // template parameter scope for an out-of-line definition, also
+        // look into that context.
+        if (!(Found && S && S->isTemplateParamScope())) {
+          assert(Ctx->isFileContext() &&
+              "We should have been looking only at file context here already.");
+
+          // Look into context considering using-directives.
+          if (CppNamespaceLookup(*this, R, Context, Ctx, UDirs))
+            Found = true;
+        }
+
+        if (Found) {
+          R.resolveKind();
+          return true;
+        }
+
+        if (R.isForRedeclaration() && !Ctx->isTransparentContext())
+          return false;
+      }
+    }
+
+    if (R.isForRedeclaration() && Ctx && !Ctx->isTransparentContext())
+      return false;
+  }
+
+  return !R.empty();
+}
+
+/// \brief Retrieve the visible declaration corresponding to D, if any.
+///
+/// This routine determines whether the declaration D is visible in the current
+/// module, with the current imports. If not, it checks whether any
+/// redeclaration of D is visible, and if so, returns that declaration.
+/// 
+/// \returns D, or a visible previous declaration of D, whichever is more recent
+/// and visible. If no declaration of D is visible, returns null.
+static NamedDecl *getVisibleDecl(NamedDecl *D) {
+  if (LookupResult::isVisible(D))
+    return D;
+  
+  for (Decl::redecl_iterator RD = D->redecls_begin(), RDEnd = D->redecls_end();
+       RD != RDEnd; ++RD) {
+    if (NamedDecl *ND = dyn_cast<NamedDecl>(*RD)) {
+      if (LookupResult::isVisible(ND))
+        return ND;
+    }
+  }
+  
+  return 0;
+}
+
+/// @brief Perform unqualified name lookup starting from a given
+/// scope.
+///
+/// Unqualified name lookup (C++ [basic.lookup.unqual], C99 6.2.1) is
+/// used to find names within the current scope. For example, 'x' in
+/// @code
+/// int x;
+/// int f() {
+///   return x; // unqualified name look finds 'x' in the global scope
+/// }
+/// @endcode
+///
+/// Different lookup criteria can find different names. For example, a
+/// particular scope can have both a struct and a function of the same
+/// name, and each can be found by certain lookup criteria. For more
+/// information about lookup criteria, see the documentation for the
+/// class LookupCriteria.
+///
+/// @param S        The scope from which unqualified name lookup will
+/// begin. If the lookup criteria permits, name lookup may also search
+/// in the parent scopes.
+///
+/// @param Name     The name of the entity that we are searching for.
+///
+/// @param Loc      If provided, the source location where we're performing
+/// name lookup. At present, this is only used to produce diagnostics when
+/// C library functions (like "malloc") are implicitly declared.
+///
+/// @returns The result of name lookup, which includes zero or more
+/// declarations and possibly additional information used to diagnose
+/// ambiguities.
+bool Sema::LookupName(LookupResult &R, Scope *S, bool AllowBuiltinCreation) {
+  DeclarationName Name = R.getLookupName();
+  if (!Name) return false;
+
+  LookupNameKind NameKind = R.getLookupKind();
+
+  if (!getLangOpts().CPlusPlus) {
+    // Unqualified name lookup in C/Objective-C is purely lexical, so
+    // search in the declarations attached to the name.
+    if (NameKind == Sema::LookupRedeclarationWithLinkage) {
+      // Find the nearest non-transparent declaration scope.
+      while (!(S->getFlags() & Scope::DeclScope) ||
+             (S->getEntity() &&
+              static_cast<DeclContext *>(S->getEntity())
+                ->isTransparentContext()))
+        S = S->getParent();
+    }
+
+    unsigned IDNS = R.getIdentifierNamespace();
+
+    // Scan up the scope chain looking for a decl that matches this
+    // identifier that is in the appropriate namespace.  This search
+    // should not take long, as shadowing of names is uncommon, and
+    // deep shadowing is extremely uncommon.
+    bool LeftStartingScope = false;
+
+    for (IdentifierResolver::iterator I = IdResolver.begin(Name),
+                                   IEnd = IdResolver.end();
+         I != IEnd; ++I)
+      if ((*I)->isInIdentifierNamespace(IDNS)) {
+        if (NameKind == LookupRedeclarationWithLinkage) {
+          // Determine whether this (or a previous) declaration is
+          // out-of-scope.
+          if (!LeftStartingScope && !S->isDeclScope(*I))
+            LeftStartingScope = true;
+
+          // If we found something outside of our starting scope that
+          // does not have linkage, skip it.
+          if (LeftStartingScope && !((*I)->hasLinkage()))
+            continue;
+        }
+        else if (NameKind == LookupObjCImplicitSelfParam &&
+                 !isa<ImplicitParamDecl>(*I))
+          continue;
+        
+        // If this declaration is module-private and it came from an AST
+        // file, we can't see it.
+        NamedDecl *D = R.isHiddenDeclarationVisible()? *I : getVisibleDecl(*I);
+        if (!D)
+          continue;
+                
+        R.addDecl(D);
+
+        // Check whether there are any other declarations with the same name
+        // and in the same scope.
+        if (I != IEnd) {
+          // Find the scope in which this declaration was declared (if it
+          // actually exists in a Scope).
+          while (S && !S->isDeclScope(D))
+            S = S->getParent();
+          
+          // If the scope containing the declaration is the translation unit,
+          // then we'll need to perform our checks based on the matching
+          // DeclContexts rather than matching scopes.
+          if (S && isNamespaceOrTranslationUnitScope(S))
+            S = 0;
+
+          // Compute the DeclContext, if we need it.
+          DeclContext *DC = 0;
+          if (!S)
+            DC = (*I)->getDeclContext()->getRedeclContext();
+            
+          IdentifierResolver::iterator LastI = I;
+          for (++LastI; LastI != IEnd; ++LastI) {
+            if (S) {
+              // Match based on scope.
+              if (!S->isDeclScope(*LastI))
+                break;
+            } else {
+              // Match based on DeclContext.
+              DeclContext *LastDC 
+                = (*LastI)->getDeclContext()->getRedeclContext();
+              if (!LastDC->Equals(DC))
+                break;
+            }
+            
+            // If the declaration isn't in the right namespace, skip it.
+            if (!(*LastI)->isInIdentifierNamespace(IDNS))
+              continue;
+                        
+            D = R.isHiddenDeclarationVisible()? *LastI : getVisibleDecl(*LastI);
+            if (D)
+              R.addDecl(D);
+          }
+
+          R.resolveKind();
+        }
+        return true;
+      }
+  } else {
+    // Perform C++ unqualified name lookup.
+    if (CppLookupName(R, S))
+      return true;
+  }
+
+  // If we didn't find a use of this identifier, and if the identifier
+  // corresponds to a compiler builtin, create the decl object for the builtin
+  // now, injecting it into translation unit scope, and return it.
+  if (AllowBuiltinCreation && LookupBuiltin(*this, R))
+    return true;
+
+  // If we didn't find a use of this identifier, the ExternalSource 
+  // may be able to handle the situation. 
+  // Note: some lookup failures are expected!
+  // See e.g. R.isForRedeclaration().
+  return (ExternalSource && ExternalSource->LookupUnqualified(R, S));
+}
+
+/// @brief Perform qualified name lookup in the namespaces nominated by
+/// using directives by the given context.
+///
+/// C++98 [namespace.qual]p2:
+///   Given X::m (where X is a user-declared namespace), or given ::m
+///   (where X is the global namespace), let S be the set of all
+///   declarations of m in X and in the transitive closure of all
+///   namespaces nominated by using-directives in X and its used
+///   namespaces, except that using-directives are ignored in any
+///   namespace, including X, directly containing one or more
+///   declarations of m. No namespace is searched more than once in
+///   the lookup of a name. If S is the empty set, the program is
+///   ill-formed. Otherwise, if S has exactly one member, or if the
+///   context of the reference is a using-declaration
+///   (namespace.udecl), S is the required set of declarations of
+///   m. Otherwise if the use of m is not one that allows a unique
+///   declaration to be chosen from S, the program is ill-formed.
+/// C++98 [namespace.qual]p5:
+///   During the lookup of a qualified namespace member name, if the
+///   lookup finds more than one declaration of the member, and if one
+///   declaration introduces a class name or enumeration name and the
+///   other declarations either introduce the same object, the same
+///   enumerator or a set of functions, the non-type name hides the
+///   class or enumeration name if and only if the declarations are
+///   from the same namespace; otherwise (the declarations are from
+///   different namespaces), the program is ill-formed.
+static bool LookupQualifiedNameInUsingDirectives(Sema &S, LookupResult &R,
+                                                 DeclContext *StartDC) {
+  assert(StartDC->isFileContext() && "start context is not a file context");
+
+  DeclContext::udir_iterator I = StartDC->using_directives_begin();
+  DeclContext::udir_iterator E = StartDC->using_directives_end();
+
+  if (I == E) return false;
+
+  // We have at least added all these contexts to the queue.
+  llvm::SmallPtrSet<DeclContext*, 8> Visited;
+  Visited.insert(StartDC);
+
+  // We have not yet looked into these namespaces, much less added
+  // their "using-children" to the queue.
+  SmallVector<NamespaceDecl*, 8> Queue;
+
+  // We have already looked into the initial namespace; seed the queue
+  // with its using-children.
+  for (; I != E; ++I) {
+    NamespaceDecl *ND = (*I)->getNominatedNamespace()->getOriginalNamespace();
+    if (Visited.insert(ND))
+      Queue.push_back(ND);
+  }
+
+  // The easiest way to implement the restriction in [namespace.qual]p5
+  // is to check whether any of the individual results found a tag
+  // and, if so, to declare an ambiguity if the final result is not
+  // a tag.
+  bool FoundTag = false;
+  bool FoundNonTag = false;
+
+  LookupResult LocalR(LookupResult::Temporary, R);
+
+  bool Found = false;
+  while (!Queue.empty()) {
+    NamespaceDecl *ND = Queue.back();
+    Queue.pop_back();
+
+    // We go through some convolutions here to avoid copying results
+    // between LookupResults.
+    bool UseLocal = !R.empty();
+    LookupResult &DirectR = UseLocal ? LocalR : R;
+    bool FoundDirect = LookupDirect(S, DirectR, ND);
+
+    if (FoundDirect) {
+      // First do any local hiding.
+      DirectR.resolveKind();
+
+      // If the local result is a tag, remember that.
+      if (DirectR.isSingleTagDecl())
+        FoundTag = true;
+      else
+        FoundNonTag = true;
+
+      // Append the local results to the total results if necessary.
+      if (UseLocal) {
+        R.addAllDecls(LocalR);
+        LocalR.clear();
+      }
+    }
+
+    // If we find names in this namespace, ignore its using directives.
+    if (FoundDirect) {
+      Found = true;
+      continue;
+    }
+
+    for (llvm::tie(I,E) = ND->getUsingDirectives(); I != E; ++I) {
+      NamespaceDecl *Nom = (*I)->getNominatedNamespace();
+      if (Visited.insert(Nom))
+        Queue.push_back(Nom);
+    }
+  }
+
+  if (Found) {
+    if (FoundTag && FoundNonTag)
+      R.setAmbiguousQualifiedTagHiding();
+    else
+      R.resolveKind();
+  }
+
+  return Found;
+}
+
+/// \brief Callback that looks for any member of a class with the given name.
+static bool LookupAnyMember(const CXXBaseSpecifier *Specifier,
+                            CXXBasePath &Path,
+                            void *Name) {
+  RecordDecl *BaseRecord = Specifier->getType()->getAs<RecordType>()->getDecl();
+
+  DeclarationName N = DeclarationName::getFromOpaquePtr(Name);
+  Path.Decls = BaseRecord->lookup(N);
+  return Path.Decls.first != Path.Decls.second;
+}
+
+/// \brief Determine whether the given set of member declarations contains only
+/// static members, nested types, and enumerators.
+template<typename InputIterator>
+static bool HasOnlyStaticMembers(InputIterator First, InputIterator Last) {
+  Decl *D = (*First)->getUnderlyingDecl();
+  if (isa<VarDecl>(D) || isa<TypeDecl>(D) || isa<EnumConstantDecl>(D))
+    return true;
+
+  if (isa<CXXMethodDecl>(D)) {
+    // Determine whether all of the methods are static.
+    bool AllMethodsAreStatic = true;
+    for(; First != Last; ++First) {
+      D = (*First)->getUnderlyingDecl();
+
+      if (!isa<CXXMethodDecl>(D)) {
+        assert(isa<TagDecl>(D) && "Non-function must be a tag decl");
+        break;
+      }
+
+      if (!cast<CXXMethodDecl>(D)->isStatic()) {
+        AllMethodsAreStatic = false;
+        break;
+      }
+    }
+
+    if (AllMethodsAreStatic)
+      return true;
+  }
+
+  return false;
+}
+
+/// \brief Perform qualified name lookup into a given context.
+///
+/// Qualified name lookup (C++ [basic.lookup.qual]) is used to find
+/// names when the context of those names is explicit specified, e.g.,
+/// "std::vector" or "x->member", or as part of unqualified name lookup.
+///
+/// Different lookup criteria can find different names. For example, a
+/// particular scope can have both a struct and a function of the same
+/// name, and each can be found by certain lookup criteria. For more
+/// information about lookup criteria, see the documentation for the
+/// class LookupCriteria.
+///
+/// \param R captures both the lookup criteria and any lookup results found.
+///
+/// \param LookupCtx The context in which qualified name lookup will
+/// search. If the lookup criteria permits, name lookup may also search
+/// in the parent contexts or (for C++ classes) base classes.
+///
+/// \param InUnqualifiedLookup true if this is qualified name lookup that
+/// occurs as part of unqualified name lookup.
+///
+/// \returns true if lookup succeeded, false if it failed.
+bool Sema::LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx,
+                               bool InUnqualifiedLookup) {
+  assert(LookupCtx && "Sema::LookupQualifiedName requires a lookup context");
+
+  if (!R.getLookupName())
+    return false;
+
+  // Make sure that the declaration context is complete.
+  assert((!isa<TagDecl>(LookupCtx) ||
+          LookupCtx->isDependentContext() ||
+          cast<TagDecl>(LookupCtx)->isCompleteDefinition() ||
+          cast<TagDecl>(LookupCtx)->isBeingDefined()) &&
+         "Declaration context must already be complete!");
+
+  // Perform qualified name lookup into the LookupCtx.
+  if (LookupDirect(*this, R, LookupCtx)) {
+    R.resolveKind();
+    if (isa<CXXRecordDecl>(LookupCtx))
+      R.setNamingClass(cast<CXXRecordDecl>(LookupCtx));
+    return true;
+  }
+
+  // Don't descend into implied contexts for redeclarations.
+  // C++98 [namespace.qual]p6:
+  //   In a declaration for a namespace member in which the
+  //   declarator-id is a qualified-id, given that the qualified-id
+  //   for the namespace member has the form
+  //     nested-name-specifier unqualified-id
+  //   the unqualified-id shall name a member of the namespace
+  //   designated by the nested-name-specifier.
+  // See also [class.mfct]p5 and [class.static.data]p2.
+  if (R.isForRedeclaration())
+    return false;
+
+  // If this is a namespace, look it up in the implied namespaces.
+  if (LookupCtx->isFileContext())
+    return LookupQualifiedNameInUsingDirectives(*this, R, LookupCtx);
+
+  // If this isn't a C++ class, we aren't allowed to look into base
+  // classes, we're done.
+  CXXRecordDecl *LookupRec = dyn_cast<CXXRecordDecl>(LookupCtx);
+  if (!LookupRec || !LookupRec->getDefinition())
+    return false;
+
+  // If we're performing qualified name lookup into a dependent class,
+  // then we are actually looking into a current instantiation. If we have any
+  // dependent base classes, then we either have to delay lookup until
+  // template instantiation time (at which point all bases will be available)
+  // or we have to fail.
+  if (!InUnqualifiedLookup && LookupRec->isDependentContext() &&
+      LookupRec->hasAnyDependentBases()) {
+    R.setNotFoundInCurrentInstantiation();
+    return false;
+  }
+
+  // Perform lookup into our base classes.
+  CXXBasePaths Paths;
+  Paths.setOrigin(LookupRec);
+
+  // Look for this member in our base classes
+  CXXRecordDecl::BaseMatchesCallback *BaseCallback = 0;
+  switch (R.getLookupKind()) {
+    case LookupObjCImplicitSelfParam:
+    case LookupOrdinaryName:
+    case LookupMemberName:
+    case LookupRedeclarationWithLinkage:
+      BaseCallback = &CXXRecordDecl::FindOrdinaryMember;
+      break;
+
+    case LookupTagName:
+      BaseCallback = &CXXRecordDecl::FindTagMember;
+      break;
+
+    case LookupAnyName:
+      BaseCallback = &LookupAnyMember;
+      break;
+
+    case LookupUsingDeclName:
+      // This lookup is for redeclarations only.
+
+    case LookupOperatorName:
+    case LookupNamespaceName:
+    case LookupObjCProtocolName:
+    case LookupLabel:
+      // These lookups will never find a member in a C++ class (or base class).
+      return false;
+
+    case LookupNestedNameSpecifierName:
+      BaseCallback = &CXXRecordDecl::FindNestedNameSpecifierMember;
+      break;
+  }
+
+  if (!LookupRec->lookupInBases(BaseCallback,
+                                R.getLookupName().getAsOpaquePtr(), Paths))
+    return false;
+
+  R.setNamingClass(LookupRec);
+
+  // C++ [class.member.lookup]p2:
+  //   [...] If the resulting set of declarations are not all from
+  //   sub-objects of the same type, or the set has a nonstatic member
+  //   and includes members from distinct sub-objects, there is an
+  //   ambiguity and the program is ill-formed. Otherwise that set is
+  //   the result of the lookup.
+  QualType SubobjectType;
+  int SubobjectNumber = 0;
+  AccessSpecifier SubobjectAccess = AS_none;
+
+  for (CXXBasePaths::paths_iterator Path = Paths.begin(), PathEnd = Paths.end();
+       Path != PathEnd; ++Path) {
+    const CXXBasePathElement &PathElement = Path->back();
+
+    // Pick the best (i.e. most permissive i.e. numerically lowest) access
+    // across all paths.
+    SubobjectAccess = std::min(SubobjectAccess, Path->Access);
+
+    // Determine whether we're looking at a distinct sub-object or not.
+    if (SubobjectType.isNull()) {
+      // This is the first subobject we've looked at. Record its type.
+      SubobjectType = Context.getCanonicalType(PathElement.Base->getType());
+      SubobjectNumber = PathElement.SubobjectNumber;
+      continue;
+    }
+
+    if (SubobjectType
+                 != Context.getCanonicalType(PathElement.Base->getType())) {
+      // We found members of the given name in two subobjects of
+      // different types. If the declaration sets aren't the same, this
+      // this lookup is ambiguous.
+      if (HasOnlyStaticMembers(Path->Decls.first, Path->Decls.second)) {
+        CXXBasePaths::paths_iterator FirstPath = Paths.begin();
+        DeclContext::lookup_iterator FirstD = FirstPath->Decls.first;
+        DeclContext::lookup_iterator CurrentD = Path->Decls.first;
+
+        while (FirstD != FirstPath->Decls.second &&
+               CurrentD != Path->Decls.second) {
+         if ((*FirstD)->getUnderlyingDecl()->getCanonicalDecl() !=
+             (*CurrentD)->getUnderlyingDecl()->getCanonicalDecl())
+           break;
+
+          ++FirstD;
+          ++CurrentD;
+        }
+
+        if (FirstD == FirstPath->Decls.second &&
+            CurrentD == Path->Decls.second)
+          continue;
+      }
+
+      R.setAmbiguousBaseSubobjectTypes(Paths);
+      return true;
+    }
+
+    if (SubobjectNumber != PathElement.SubobjectNumber) {
+      // We have a different subobject of the same type.
+
+      // C++ [class.member.lookup]p5:
+      //   A static member, a nested type or an enumerator defined in
+      //   a base class T can unambiguously be found even if an object
+      //   has more than one base class subobject of type T.
+      if (HasOnlyStaticMembers(Path->Decls.first, Path->Decls.second))
+        continue;
+
+      // We have found a nonstatic member name in multiple, distinct
+      // subobjects. Name lookup is ambiguous.
+      R.setAmbiguousBaseSubobjects(Paths);
+      return true;
+    }
+  }
+
+  // Lookup in a base class succeeded; return these results.
+
+  DeclContext::lookup_iterator I, E;
+  for (llvm::tie(I,E) = Paths.front().Decls; I != E; ++I) {
+    NamedDecl *D = *I;
+    AccessSpecifier AS = CXXRecordDecl::MergeAccess(SubobjectAccess,
+                                                    D->getAccess());
+    R.addDecl(D, AS);
+  }
+  R.resolveKind();
+  return true;
+}
+
+/// @brief Performs name lookup for a name that was parsed in the
+/// source code, and may contain a C++ scope specifier.
+///
+/// This routine is a convenience routine meant to be called from
+/// contexts that receive a name and an optional C++ scope specifier
+/// (e.g., "N::M::x"). It will then perform either qualified or
+/// unqualified name lookup (with LookupQualifiedName or LookupName,
+/// respectively) on the given name and return those results.
+///
+/// @param S        The scope from which unqualified name lookup will
+/// begin.
+///
+/// @param SS       An optional C++ scope-specifier, e.g., "::N::M".
+///
+/// @param EnteringContext Indicates whether we are going to enter the
+/// context of the scope-specifier SS (if present).
+///
+/// @returns True if any decls were found (but possibly ambiguous)
+bool Sema::LookupParsedName(LookupResult &R, Scope *S, CXXScopeSpec *SS,
+                            bool AllowBuiltinCreation, bool EnteringContext) {
+  if (SS && SS->isInvalid()) {
+    // When the scope specifier is invalid, don't even look for
+    // anything.
+    return false;
+  }
+
+  if (SS && SS->isSet()) {
+    if (DeclContext *DC = computeDeclContext(*SS, EnteringContext)) {
+      // We have resolved the scope specifier to a particular declaration
+      // contex, and will perform name lookup in that context.
+      if (!DC->isDependentContext() && RequireCompleteDeclContext(*SS, DC))
+        return false;
+
+      R.setContextRange(SS->getRange());
+      return LookupQualifiedName(R, DC);
+    }
+
+    // We could not resolve the scope specified to a specific declaration
+    // context, which means that SS refers to an unknown specialization.
+    // Name lookup can't find anything in this case.
+    R.setNotFoundInCurrentInstantiation();
+    R.setContextRange(SS->getRange());
+    return false;
+  }
+
+  // Perform unqualified name lookup starting in the given scope.
+  return LookupName(R, S, AllowBuiltinCreation);
+}
+
+
+/// @brief Produce a diagnostic describing the ambiguity that resulted
+/// from name lookup.
+///
+/// @param Result       The ambiguous name lookup result.
+///
+/// @param Name         The name of the entity that name lookup was
+/// searching for.
+///
+/// @param NameLoc      The location of the name within the source code.
+///
+/// @param LookupRange  A source range that provides more
+/// source-location information concerning the lookup itself. For
+/// example, this range might highlight a nested-name-specifier that
+/// precedes the name.
+///
+/// @returns true
+bool Sema::DiagnoseAmbiguousLookup(LookupResult &Result) {
+  assert(Result.isAmbiguous() && "Lookup result must be ambiguous");
+
+  DeclarationName Name = Result.getLookupName();
+  SourceLocation NameLoc = Result.getNameLoc();
+  SourceRange LookupRange = Result.getContextRange();
+
+  switch (Result.getAmbiguityKind()) {
+  case LookupResult::AmbiguousBaseSubobjects: {
+    CXXBasePaths *Paths = Result.getBasePaths();
+    QualType SubobjectType = Paths->front().back().Base->getType();
+    Diag(NameLoc, diag::err_ambiguous_member_multiple_subobjects)
+      << Name << SubobjectType << getAmbiguousPathsDisplayString(*Paths)
+      << LookupRange;
+
+    DeclContext::lookup_iterator Found = Paths->front().Decls.first;
+    while (isa<CXXMethodDecl>(*Found) &&
+           cast<CXXMethodDecl>(*Found)->isStatic())
+      ++Found;
+
+    Diag((*Found)->getLocation(), diag::note_ambiguous_member_found);
+
+    return true;
+  }
+
+  case LookupResult::AmbiguousBaseSubobjectTypes: {
+    Diag(NameLoc, diag::err_ambiguous_member_multiple_subobject_types)
+      << Name << LookupRange;
+
+    CXXBasePaths *Paths = Result.getBasePaths();
+    std::set<Decl *> DeclsPrinted;
+    for (CXXBasePaths::paths_iterator Path = Paths->begin(),
+                                      PathEnd = Paths->end();
+         Path != PathEnd; ++Path) {
+      Decl *D = *Path->Decls.first;
+      if (DeclsPrinted.insert(D).second)
+        Diag(D->getLocation(), diag::note_ambiguous_member_found);
+    }
+
+    return true;
+  }
+
+  case LookupResult::AmbiguousTagHiding: {
+    Diag(NameLoc, diag::err_ambiguous_tag_hiding) << Name << LookupRange;
+
+    llvm::SmallPtrSet<NamedDecl*,8> TagDecls;
+
+    LookupResult::iterator DI, DE = Result.end();
+    for (DI = Result.begin(); DI != DE; ++DI)
+      if (TagDecl *TD = dyn_cast<TagDecl>(*DI)) {
+        TagDecls.insert(TD);
+        Diag(TD->getLocation(), diag::note_hidden_tag);
+      }
+
+    for (DI = Result.begin(); DI != DE; ++DI)
+      if (!isa<TagDecl>(*DI))
+        Diag((*DI)->getLocation(), diag::note_hiding_object);
+
+    // For recovery purposes, go ahead and implement the hiding.
+    LookupResult::Filter F = Result.makeFilter();
+    while (F.hasNext()) {
+      if (TagDecls.count(F.next()))
+        F.erase();
+    }
+    F.done();
+
+    return true;
+  }
+
+  case LookupResult::AmbiguousReference: {
+    Diag(NameLoc, diag::err_ambiguous_reference) << Name << LookupRange;
+
+    LookupResult::iterator DI = Result.begin(), DE = Result.end();
+    for (; DI != DE; ++DI)
+      Diag((*DI)->getLocation(), diag::note_ambiguous_candidate) << *DI;
+
+    return true;
+  }
+  }
+
+  llvm_unreachable("unknown ambiguity kind");
+}
+
+namespace {
+  struct AssociatedLookup {
+    AssociatedLookup(Sema &S,
+                     Sema::AssociatedNamespaceSet &Namespaces,
+                     Sema::AssociatedClassSet &Classes)
+      : S(S), Namespaces(Namespaces), Classes(Classes) {
+    }
+
+    Sema &S;
+    Sema::AssociatedNamespaceSet &Namespaces;
+    Sema::AssociatedClassSet &Classes;
+  };
+}
+
+static void
+addAssociatedClassesAndNamespaces(AssociatedLookup &Result, QualType T);
+
+static void CollectEnclosingNamespace(Sema::AssociatedNamespaceSet &Namespaces,
+                                      DeclContext *Ctx) {
+  // Add the associated namespace for this class.
+
+  // We don't use DeclContext::getEnclosingNamespaceContext() as this may
+  // be a locally scoped record.
+
+  // We skip out of inline namespaces. The innermost non-inline namespace
+  // contains all names of all its nested inline namespaces anyway, so we can
+  // replace the entire inline namespace tree with its root.
+  while (Ctx->isRecord() || Ctx->isTransparentContext() ||
+         Ctx->isInlineNamespace())
+    Ctx = Ctx->getParent();
+
+  if (Ctx->isFileContext())
+    Namespaces.insert(Ctx->getPrimaryContext());
+}
+
+// \brief Add the associated classes and namespaces for argument-dependent
+// lookup that involves a template argument (C++ [basic.lookup.koenig]p2).
+static void
+addAssociatedClassesAndNamespaces(AssociatedLookup &Result,
+                                  const TemplateArgument &Arg) {
+  // C++ [basic.lookup.koenig]p2, last bullet:
+  //   -- [...] ;
+  switch (Arg.getKind()) {
+    case TemplateArgument::Null:
+      break;
+
+    case TemplateArgument::Type:
+      // [...] the namespaces and classes associated with the types of the
+      // template arguments provided for template type parameters (excluding
+      // template template parameters)
+      addAssociatedClassesAndNamespaces(Result, Arg.getAsType());
+      break;
+
+    case TemplateArgument::Template:
+    case TemplateArgument::TemplateExpansion: {
+      // [...] the namespaces in which any template template arguments are
+      // defined; and the classes in which any member templates used as
+      // template template arguments are defined.
+      TemplateName Template = Arg.getAsTemplateOrTemplatePattern();
+      if (ClassTemplateDecl *ClassTemplate
+                 = dyn_cast<ClassTemplateDecl>(Template.getAsTemplateDecl())) {
+        DeclContext *Ctx = ClassTemplate->getDeclContext();
+        if (CXXRecordDecl *EnclosingClass = dyn_cast<CXXRecordDecl>(Ctx))
+          Result.Classes.insert(EnclosingClass);
+        // Add the associated namespace for this class.
+        CollectEnclosingNamespace(Result.Namespaces, Ctx);
+      }
+      break;
+    }
+
+    case TemplateArgument::Declaration:
+    case TemplateArgument::Integral:
+    case TemplateArgument::Expression:
+      // [Note: non-type template arguments do not contribute to the set of
+      //  associated namespaces. ]
+      break;
+
+    case TemplateArgument::Pack:
+      for (TemplateArgument::pack_iterator P = Arg.pack_begin(),
+                                        PEnd = Arg.pack_end();
+           P != PEnd; ++P)
+        addAssociatedClassesAndNamespaces(Result, *P);
+      break;
+  }
+}
+
+// \brief Add the associated classes and namespaces for
+// argument-dependent lookup with an argument of class type
+// (C++ [basic.lookup.koenig]p2).
+static void
+addAssociatedClassesAndNamespaces(AssociatedLookup &Result,
+                                  CXXRecordDecl *Class) {
+
+  // Just silently ignore anything whose name is __va_list_tag.
+  if (Class->getDeclName() == Result.S.VAListTagName)
+    return;
+
+  // C++ [basic.lookup.koenig]p2:
+  //   [...]
+  //     -- If T is a class type (including unions), its associated
+  //        classes are: the class itself; the class of which it is a
+  //        member, if any; and its direct and indirect base
+  //        classes. Its associated namespaces are the namespaces in
+  //        which its associated classes are defined.
+
+  // Add the class of which it is a member, if any.
+  DeclContext *Ctx = Class->getDeclContext();
+  if (CXXRecordDecl *EnclosingClass = dyn_cast<CXXRecordDecl>(Ctx))
+    Result.Classes.insert(EnclosingClass);
+  // Add the associated namespace for this class.
+  CollectEnclosingNamespace(Result.Namespaces, Ctx);
+
+  // Add the class itself. If we've already seen this class, we don't
+  // need to visit base classes.
+  if (!Result.Classes.insert(Class))
+    return;
+
+  // -- If T is a template-id, its associated namespaces and classes are
+  //    the namespace in which the template is defined; for member
+  //    templates, the member template's class; the namespaces and classes
+  //    associated with the types of the template arguments provided for
+  //    template type parameters (excluding template template parameters); the
+  //    namespaces in which any template template arguments are defined; and
+  //    the classes in which any member templates used as template template
+  //    arguments are defined. [Note: non-type template arguments do not
+  //    contribute to the set of associated namespaces. ]
+  if (ClassTemplateSpecializationDecl *Spec
+        = dyn_cast<ClassTemplateSpecializationDecl>(Class)) {
+    DeclContext *Ctx = Spec->getSpecializedTemplate()->getDeclContext();
+    if (CXXRecordDecl *EnclosingClass = dyn_cast<CXXRecordDecl>(Ctx))
+      Result.Classes.insert(EnclosingClass);
+    // Add the associated namespace for this class.
+    CollectEnclosingNamespace(Result.Namespaces, Ctx);
+
+    const TemplateArgumentList &TemplateArgs = Spec->getTemplateArgs();
+    for (unsigned I = 0, N = TemplateArgs.size(); I != N; ++I)
+      addAssociatedClassesAndNamespaces(Result, TemplateArgs[I]);
+  }
+
+  // Only recurse into base classes for complete types.
+  if (!Class->hasDefinition()) {
+    // FIXME: we might need to instantiate templates here
+    return;
+  }
+
+  // Add direct and indirect base classes along with their associated
+  // namespaces.
+  SmallVector<CXXRecordDecl *, 32> Bases;
+  Bases.push_back(Class);
+  while (!Bases.empty()) {
+    // Pop this class off the stack.
+    Class = Bases.back();
+    Bases.pop_back();
+
+    // Visit the base classes.
+    for (CXXRecordDecl::base_class_iterator Base = Class->bases_begin(),
+                                         BaseEnd = Class->bases_end();
+         Base != BaseEnd; ++Base) {
+      const RecordType *BaseType = Base->getType()->getAs<RecordType>();
+      // In dependent contexts, we do ADL twice, and the first time around,
+      // the base type might be a dependent TemplateSpecializationType, or a
+      // TemplateTypeParmType. If that happens, simply ignore it.
+      // FIXME: If we want to support export, we probably need to add the
+      // namespace of the template in a TemplateSpecializationType, or even
+      // the classes and namespaces of known non-dependent arguments.
+      if (!BaseType)
+        continue;
+      CXXRecordDecl *BaseDecl = cast<CXXRecordDecl>(BaseType->getDecl());
+      if (Result.Classes.insert(BaseDecl)) {
+        // Find the associated namespace for this base class.
+        DeclContext *BaseCtx = BaseDecl->getDeclContext();
+        CollectEnclosingNamespace(Result.Namespaces, BaseCtx);
+
+        // Make sure we visit the bases of this base class.
+        if (BaseDecl->bases_begin() != BaseDecl->bases_end())
+          Bases.push_back(BaseDecl);
+      }
+    }
+  }
+}
+
+// \brief Add the associated classes and namespaces for
+// argument-dependent lookup with an argument of type T
+// (C++ [basic.lookup.koenig]p2).
+static void
+addAssociatedClassesAndNamespaces(AssociatedLookup &Result, QualType Ty) {
+  // C++ [basic.lookup.koenig]p2:
+  //
+  //   For each argument type T in the function call, there is a set
+  //   of zero or more associated namespaces and a set of zero or more
+  //   associated classes to be considered. The sets of namespaces and
+  //   classes is determined entirely by the types of the function
+  //   arguments (and the namespace of any template template
+  //   argument). Typedef names and using-declarations used to specify
+  //   the types do not contribute to this set. The sets of namespaces
+  //   and classes are determined in the following way:
+
+  SmallVector<const Type *, 16> Queue;
+  const Type *T = Ty->getCanonicalTypeInternal().getTypePtr();
+
+  while (true) {
+    switch (T->getTypeClass()) {
+
+#define TYPE(Class, Base)
+#define DEPENDENT_TYPE(Class, Base) case Type::Class:
+#define NON_CANONICAL_TYPE(Class, Base) case Type::Class:
+#define NON_CANONICAL_UNLESS_DEPENDENT_TYPE(Class, Base) case Type::Class:
+#define ABSTRACT_TYPE(Class, Base)
+#include "clang/AST/TypeNodes.def"
+      // T is canonical.  We can also ignore dependent types because
+      // we don't need to do ADL at the definition point, but if we
+      // wanted to implement template export (or if we find some other
+      // use for associated classes and namespaces...) this would be
+      // wrong.
+      break;
+
+    //    -- If T is a pointer to U or an array of U, its associated
+    //       namespaces and classes are those associated with U.
+    case Type::Pointer:
+      T = cast<PointerType>(T)->getPointeeType().getTypePtr();
+      continue;
+    case Type::ConstantArray:
+    case Type::IncompleteArray:
+    case Type::VariableArray:
+      T = cast<ArrayType>(T)->getElementType().getTypePtr();
+      continue;
+
+    //     -- If T is a fundamental type, its associated sets of
+    //        namespaces and classes are both empty.
+    case Type::Builtin:
+      break;
+
+    //     -- If T is a class type (including unions), its associated
+    //        classes are: the class itself; the class of which it is a
+    //        member, if any; and its direct and indirect base
+    //        classes. Its associated namespaces are the namespaces in
+    //        which its associated classes are defined.
+    case Type::Record: {
+      CXXRecordDecl *Class
+        = cast<CXXRecordDecl>(cast<RecordType>(T)->getDecl());
+      addAssociatedClassesAndNamespaces(Result, Class);
+      break;
+    }
+
+    //     -- If T is an enumeration type, its associated namespace is
+    //        the namespace in which it is defined. If it is class
+    //        member, its associated class is the member's class; else
+    //        it has no associated class.
+    case Type::Enum: {
+      EnumDecl *Enum = cast<EnumType>(T)->getDecl();
+
+      DeclContext *Ctx = Enum->getDeclContext();
+      if (CXXRecordDecl *EnclosingClass = dyn_cast<CXXRecordDecl>(Ctx))
+        Result.Classes.insert(EnclosingClass);
+
+      // Add the associated namespace for this class.
+      CollectEnclosingNamespace(Result.Namespaces, Ctx);
+
+      break;
+    }
+
+    //     -- If T is a function type, its associated namespaces and
+    //        classes are those associated with the function parameter
+    //        types and those associated with the return type.
+    case Type::FunctionProto: {
+      const FunctionProtoType *Proto = cast<FunctionProtoType>(T);
+      for (FunctionProtoType::arg_type_iterator Arg = Proto->arg_type_begin(),
+                                             ArgEnd = Proto->arg_type_end();
+             Arg != ArgEnd; ++Arg)
+        Queue.push_back(Arg->getTypePtr());
+      // fallthrough
+    }
+    case Type::FunctionNoProto: {
+      const FunctionType *FnType = cast<FunctionType>(T);
+      T = FnType->getResultType().getTypePtr();
+      continue;
+    }
+
+    //     -- If T is a pointer to a member function of a class X, its
+    //        associated namespaces and classes are those associated
+    //        with the function parameter types and return type,
+    //        together with those associated with X.
+    //
+    //     -- If T is a pointer to a data member of class X, its
+    //        associated namespaces and classes are those associated
+    //        with the member type together with those associated with
+    //        X.
+    case Type::MemberPointer: {
+      const MemberPointerType *MemberPtr = cast<MemberPointerType>(T);
+
+      // Queue up the class type into which this points.
+      Queue.push_back(MemberPtr->getClass());
+
+      // And directly continue with the pointee type.
+      T = MemberPtr->getPointeeType().getTypePtr();
+      continue;
+    }
+
+    // As an extension, treat this like a normal pointer.
+    case Type::BlockPointer:
+      T = cast<BlockPointerType>(T)->getPointeeType().getTypePtr();
+      continue;
+
+    // References aren't covered by the standard, but that's such an
+    // obvious defect that we cover them anyway.
+    case Type::LValueReference:
+    case Type::RValueReference:
+      T = cast<ReferenceType>(T)->getPointeeType().getTypePtr();
+      continue;
+
+    // These are fundamental types.
+    case Type::Vector:
+    case Type::ExtVector:
+    case Type::Complex:
+      break;
+
+    // If T is an Objective-C object or interface type, or a pointer to an 
+    // object or interface type, the associated namespace is the global
+    // namespace.
+    case Type::ObjCObject:
+    case Type::ObjCInterface:
+    case Type::ObjCObjectPointer:
+      Result.Namespaces.insert(Result.S.Context.getTranslationUnitDecl());
+      break;
+
+    // Atomic types are just wrappers; use the associations of the
+    // contained type.
+    case Type::Atomic:
+      T = cast<AtomicType>(T)->getValueType().getTypePtr();
+      continue;
+    }
+
+    if (Queue.empty()) break;
+    T = Queue.back();
+    Queue.pop_back();
+  }
+}
+
+/// \brief Find the associated classes and namespaces for
+/// argument-dependent lookup for a call with the given set of
+/// arguments.
+///
+/// This routine computes the sets of associated classes and associated
+/// namespaces searched by argument-dependent lookup
+/// (C++ [basic.lookup.argdep]) for a given set of arguments.
+void
+Sema::FindAssociatedClassesAndNamespaces(llvm::ArrayRef<Expr *> Args,
+                                 AssociatedNamespaceSet &AssociatedNamespaces,
+                                 AssociatedClassSet &AssociatedClasses) {
+  AssociatedNamespaces.clear();
+  AssociatedClasses.clear();
+
+  AssociatedLookup Result(*this, AssociatedNamespaces, AssociatedClasses);
+
+  // C++ [basic.lookup.koenig]p2:
+  //   For each argument type T in the function call, there is a set
+  //   of zero or more associated namespaces and a set of zero or more
+  //   associated classes to be considered. The sets of namespaces and
+  //   classes is determined entirely by the types of the function
+  //   arguments (and the namespace of any template template
+  //   argument).
+  for (unsigned ArgIdx = 0; ArgIdx != Args.size(); ++ArgIdx) {
+    Expr *Arg = Args[ArgIdx];
+
+    if (Arg->getType() != Context.OverloadTy) {
+      addAssociatedClassesAndNamespaces(Result, Arg->getType());
+      continue;
+    }
+
+    // [...] In addition, if the argument is the name or address of a
+    // set of overloaded functions and/or function templates, its
+    // associated classes and namespaces are the union of those
+    // associated with each of the members of the set: the namespace
+    // in which the function or function template is defined and the
+    // classes and namespaces associated with its (non-dependent)
+    // parameter types and return type.
+    Arg = Arg->IgnoreParens();
+    if (UnaryOperator *unaryOp = dyn_cast<UnaryOperator>(Arg))
+      if (unaryOp->getOpcode() == UO_AddrOf)
+        Arg = unaryOp->getSubExpr();
+
+    UnresolvedLookupExpr *ULE = dyn_cast<UnresolvedLookupExpr>(Arg);
+    if (!ULE) continue;
+
+    for (UnresolvedSetIterator I = ULE->decls_begin(), E = ULE->decls_end();
+           I != E; ++I) {
+      // Look through any using declarations to find the underlying function.
+      NamedDecl *Fn = (*I)->getUnderlyingDecl();
+
+      FunctionDecl *FDecl = dyn_cast<FunctionDecl>(Fn);
+      if (!FDecl)
+        FDecl = cast<FunctionTemplateDecl>(Fn)->getTemplatedDecl();
+
+      // Add the classes and namespaces associated with the parameter
+      // types and return type of this function.
+      addAssociatedClassesAndNamespaces(Result, FDecl->getType());
+    }
+  }
+}
+
+/// IsAcceptableNonMemberOperatorCandidate - Determine whether Fn is
+/// an acceptable non-member overloaded operator for a call whose
+/// arguments have types T1 (and, if non-empty, T2). This routine
+/// implements the check in C++ [over.match.oper]p3b2 concerning
+/// enumeration types.
+static bool
+IsAcceptableNonMemberOperatorCandidate(FunctionDecl *Fn,
+                                       QualType T1, QualType T2,
+                                       ASTContext &Context) {
+  if (T1->isDependentType() || (!T2.isNull() && T2->isDependentType()))
+    return true;
+
+  if (T1->isRecordType() || (!T2.isNull() && T2->isRecordType()))
+    return true;
+
+  const FunctionProtoType *Proto = Fn->getType()->getAs<FunctionProtoType>();
+  if (Proto->getNumArgs() < 1)
+    return false;
+
+  if (T1->isEnumeralType()) {
+    QualType ArgType = Proto->getArgType(0).getNonReferenceType();
+    if (Context.hasSameUnqualifiedType(T1, ArgType))
+      return true;
+  }
+
+  if (Proto->getNumArgs() < 2)
+    return false;
+
+  if (!T2.isNull() && T2->isEnumeralType()) {
+    QualType ArgType = Proto->getArgType(1).getNonReferenceType();
+    if (Context.hasSameUnqualifiedType(T2, ArgType))
+      return true;
+  }
+
+  return false;
+}
+
+NamedDecl *Sema::LookupSingleName(Scope *S, DeclarationName Name,
+                                  SourceLocation Loc,
+                                  LookupNameKind NameKind,
+                                  RedeclarationKind Redecl) {
+  LookupResult R(*this, Name, Loc, NameKind, Redecl);
+  LookupName(R, S);
+  return R.getAsSingle<NamedDecl>();
+}
+
+/// \brief Find the protocol with the given name, if any.
+ObjCProtocolDecl *Sema::LookupProtocol(IdentifierInfo *II,
+                                       SourceLocation IdLoc,
+                                       RedeclarationKind Redecl) {
+  Decl *D = LookupSingleName(TUScope, II, IdLoc,
+                             LookupObjCProtocolName, Redecl);
+  return cast_or_null<ObjCProtocolDecl>(D);
+}
+
+void Sema::LookupOverloadedOperatorName(OverloadedOperatorKind Op, Scope *S,
+                                        QualType T1, QualType T2,
+                                        UnresolvedSetImpl &Functions) {
+  // C++ [over.match.oper]p3:
+  //     -- The set of non-member candidates is the result of the
+  //        unqualified lookup of operator@ in the context of the
+  //        expression according to the usual rules for name lookup in
+  //        unqualified function calls (3.4.2) except that all member
+  //        functions are ignored. However, if no operand has a class
+  //        type, only those non-member functions in the lookup set
+  //        that have a first parameter of type T1 or "reference to
+  //        (possibly cv-qualified) T1", when T1 is an enumeration
+  //        type, or (if there is a right operand) a second parameter
+  //        of type T2 or "reference to (possibly cv-qualified) T2",
+  //        when T2 is an enumeration type, are candidate functions.
+  DeclarationName OpName = Context.DeclarationNames.getCXXOperatorName(Op);
+  LookupResult Operators(*this, OpName, SourceLocation(), LookupOperatorName);
+  LookupName(Operators, S);
+
+  assert(!Operators.isAmbiguous() && "Operator lookup cannot be ambiguous");
+
+  if (Operators.empty())
+    return;
+
+  for (LookupResult::iterator Op = Operators.begin(), OpEnd = Operators.end();
+       Op != OpEnd; ++Op) {
+    NamedDecl *Found = (*Op)->getUnderlyingDecl();
+    if (FunctionDecl *FD = dyn_cast<FunctionDecl>(Found)) {
+      if (IsAcceptableNonMemberOperatorCandidate(FD, T1, T2, Context))
+        Functions.addDecl(*Op, Op.getAccess()); // FIXME: canonical FD
+    } else if (FunctionTemplateDecl *FunTmpl
+                 = dyn_cast<FunctionTemplateDecl>(Found)) {
+      // FIXME: friend operators?
+      // FIXME: do we need to check IsAcceptableNonMemberOperatorCandidate,
+      // later?
+      if (!FunTmpl->getDeclContext()->isRecord())
+        Functions.addDecl(*Op, Op.getAccess());
+    }
+  }
+}
+
+Sema::SpecialMemberOverloadResult *Sema::LookupSpecialMember(CXXRecordDecl *RD,
+                                                            CXXSpecialMember SM,
+                                                            bool ConstArg,
+                                                            bool VolatileArg,
+                                                            bool RValueThis,
+                                                            bool ConstThis,
+                                                            bool VolatileThis) {
+  RD = RD->getDefinition();
+  assert((RD && !RD->isBeingDefined()) &&
+         "doing special member lookup into record that isn't fully complete");
+  if (RValueThis || ConstThis || VolatileThis)
+    assert((SM == CXXCopyAssignment || SM == CXXMoveAssignment) &&
+           "constructors and destructors always have unqualified lvalue this");
+  if (ConstArg || VolatileArg)
+    assert((SM != CXXDefaultConstructor && SM != CXXDestructor) &&
+           "parameter-less special members can't have qualified arguments");
+
+  llvm::FoldingSetNodeID ID;
+  ID.AddPointer(RD);
+  ID.AddInteger(SM);
+  ID.AddInteger(ConstArg);
+  ID.AddInteger(VolatileArg);
+  ID.AddInteger(RValueThis);
+  ID.AddInteger(ConstThis);
+  ID.AddInteger(VolatileThis);
+
+  void *InsertPoint;
+  SpecialMemberOverloadResult *Result =
+    SpecialMemberCache.FindNodeOrInsertPos(ID, InsertPoint);
+
+  // This was already cached
+  if (Result)
+    return Result;
+
+  Result = BumpAlloc.Allocate<SpecialMemberOverloadResult>();
+  Result = new (Result) SpecialMemberOverloadResult(ID);
+  SpecialMemberCache.InsertNode(Result, InsertPoint);
+
+  if (SM == CXXDestructor) {
+    if (!RD->hasDeclaredDestructor())
+      DeclareImplicitDestructor(RD);
+    CXXDestructorDecl *DD = RD->getDestructor();
+    assert(DD && "record without a destructor");
+    Result->setMethod(DD);
+    Result->setKind(DD->isDeleted() ?
+                    SpecialMemberOverloadResult::NoMemberOrDeleted :
+                    SpecialMemberOverloadResult::Success);
+    return Result;
+  }
+
+  // Prepare for overload resolution. Here we construct a synthetic argument
+  // if necessary and make sure that implicit functions are declared.
+  CanQualType CanTy = Context.getCanonicalType(Context.getTagDeclType(RD));
+  DeclarationName Name;
+  Expr *Arg = 0;
+  unsigned NumArgs;
+
+  QualType ArgType = CanTy;
+  ExprValueKind VK = VK_LValue;
+
+  if (SM == CXXDefaultConstructor) {
+    Name = Context.DeclarationNames.getCXXConstructorName(CanTy);
+    NumArgs = 0;
+    if (RD->needsImplicitDefaultConstructor())
+      DeclareImplicitDefaultConstructor(RD);
+  } else {
+    if (SM == CXXCopyConstructor || SM == CXXMoveConstructor) {
+      Name = Context.DeclarationNames.getCXXConstructorName(CanTy);
+      if (!RD->hasDeclaredCopyConstructor())
+        DeclareImplicitCopyConstructor(RD);
+      if (getLangOpts().CPlusPlus0x && RD->needsImplicitMoveConstructor())
+        DeclareImplicitMoveConstructor(RD);
+    } else {
+      Name = Context.DeclarationNames.getCXXOperatorName(OO_Equal);
+      if (!RD->hasDeclaredCopyAssignment())
+        DeclareImplicitCopyAssignment(RD);
+      if (getLangOpts().CPlusPlus0x && RD->needsImplicitMoveAssignment())
+        DeclareImplicitMoveAssignment(RD);
+    }
+
+    if (ConstArg)
+      ArgType.addConst();
+    if (VolatileArg)
+      ArgType.addVolatile();
+
+    // This isn't /really/ specified by the standard, but it's implied
+    // we should be working from an RValue in the case of move to ensure
+    // that we prefer to bind to rvalue references, and an LValue in the
+    // case of copy to ensure we don't bind to rvalue references.
+    // Possibly an XValue is actually correct in the case of move, but
+    // there is no semantic difference for class types in this restricted
+    // case.
+    if (SM == CXXCopyConstructor || SM == CXXCopyAssignment)
+      VK = VK_LValue;
+    else
+      VK = VK_RValue;
+  }
+
+  OpaqueValueExpr FakeArg(SourceLocation(), ArgType, VK);
+
+  if (SM != CXXDefaultConstructor) {
+    NumArgs = 1;
+    Arg = &FakeArg;
+  }
+
+  // Create the object argument
+  QualType ThisTy = CanTy;
+  if (ConstThis)
+    ThisTy.addConst();
+  if (VolatileThis)
+    ThisTy.addVolatile();
+  Expr::Classification Classification =
+    OpaqueValueExpr(SourceLocation(), ThisTy,
+                    RValueThis ? VK_RValue : VK_LValue).Classify(Context);
+
+  // Now we perform lookup on the name we computed earlier and do overload
+  // resolution. Lookup is only performed directly into the class since there
+  // will always be a (possibly implicit) declaration to shadow any others.
+  OverloadCandidateSet OCS((SourceLocation()));
+  DeclContext::lookup_iterator I, E;
+
+  llvm::tie(I, E) = RD->lookup(Name);
+  assert((I != E) &&
+         "lookup for a constructor or assignment operator was empty");
+  for ( ; I != E; ++I) {
+    Decl *Cand = *I;
+
+    if (Cand->isInvalidDecl())
+      continue;
+
+    if (UsingShadowDecl *U = dyn_cast<UsingShadowDecl>(Cand)) {
+      // FIXME: [namespace.udecl]p15 says that we should only consider a
+      // using declaration here if it does not match a declaration in the
+      // derived class. We do not implement this correctly in other cases
+      // either.
+      Cand = U->getTargetDecl();
+
+      if (Cand->isInvalidDecl())
+        continue;
+    }
+
+    if (CXXMethodDecl *M = dyn_cast<CXXMethodDecl>(Cand)) {
+      if (SM == CXXCopyAssignment || SM == CXXMoveAssignment)
+        AddMethodCandidate(M, DeclAccessPair::make(M, AS_public), RD, ThisTy,
+                           Classification, llvm::makeArrayRef(&Arg, NumArgs),
+                           OCS, true);
+      else
+        AddOverloadCandidate(M, DeclAccessPair::make(M, AS_public),
+                             llvm::makeArrayRef(&Arg, NumArgs), OCS, true);
+    } else if (FunctionTemplateDecl *Tmpl =
+                 dyn_cast<FunctionTemplateDecl>(Cand)) {
+      if (SM == CXXCopyAssignment || SM == CXXMoveAssignment)
+        AddMethodTemplateCandidate(Tmpl, DeclAccessPair::make(Tmpl, AS_public),
+                                   RD, 0, ThisTy, Classification,
+                                   llvm::makeArrayRef(&Arg, NumArgs),
+                                   OCS, true);
+      else
+        AddTemplateOverloadCandidate(Tmpl, DeclAccessPair::make(Tmpl, AS_public),
+                                     0, llvm::makeArrayRef(&Arg, NumArgs),
+                                     OCS, true);
+    } else {
+      assert(isa<UsingDecl>(Cand) && "illegal Kind of operator = Decl");
+    }
+  }
+
+  OverloadCandidateSet::iterator Best;
+  switch (OCS.BestViableFunction(*this, SourceLocation(), Best)) {
+    case OR_Success:
+      Result->setMethod(cast<CXXMethodDecl>(Best->Function));
+      Result->setKind(SpecialMemberOverloadResult::Success);
+      break;
+
+    case OR_Deleted:
+      Result->setMethod(cast<CXXMethodDecl>(Best->Function));
+      Result->setKind(SpecialMemberOverloadResult::NoMemberOrDeleted);
+      break;
+
+    case OR_Ambiguous:
+      Result->setMethod(0);
+      Result->setKind(SpecialMemberOverloadResult::Ambiguous);
+      break;
+
+    case OR_No_Viable_Function:
+      Result->setMethod(0);
+      Result->setKind(SpecialMemberOverloadResult::NoMemberOrDeleted);
+      break;
+  }
+
+  return Result;
+}
+
+/// \brief Look up the default constructor for the given class.
+CXXConstructorDecl *Sema::LookupDefaultConstructor(CXXRecordDecl *Class) {
+  SpecialMemberOverloadResult *Result =
+    LookupSpecialMember(Class, CXXDefaultConstructor, false, false, false,
+                        false, false);
+
+  return cast_or_null<CXXConstructorDecl>(Result->getMethod());
+}
+
+/// \brief Look up the copying constructor for the given class.
+CXXConstructorDecl *Sema::LookupCopyingConstructor(CXXRecordDecl *Class,
+                                                   unsigned Quals) {
+  assert(!(Quals & ~(Qualifiers::Const | Qualifiers::Volatile)) &&
+         "non-const, non-volatile qualifiers for copy ctor arg");
+  SpecialMemberOverloadResult *Result =
+    LookupSpecialMember(Class, CXXCopyConstructor, Quals & Qualifiers::Const,
+                        Quals & Qualifiers::Volatile, false, false, false);
+
+  return cast_or_null<CXXConstructorDecl>(Result->getMethod());
+}
+
+/// \brief Look up the moving constructor for the given class.
+CXXConstructorDecl *Sema::LookupMovingConstructor(CXXRecordDecl *Class) {
+  SpecialMemberOverloadResult *Result =
+    LookupSpecialMember(Class, CXXMoveConstructor, false,
+                        false, false, false, false);
+
+  return cast_or_null<CXXConstructorDecl>(Result->getMethod());
+}
+
+/// \brief Look up the constructors for the given class.
+DeclContext::lookup_result Sema::LookupConstructors(CXXRecordDecl *Class) {
+  // If the implicit constructors have not yet been declared, do so now.
+  if (CanDeclareSpecialMemberFunction(Context, Class)) {
+    if (Class->needsImplicitDefaultConstructor())
+      DeclareImplicitDefaultConstructor(Class);
+    if (!Class->hasDeclaredCopyConstructor())
+      DeclareImplicitCopyConstructor(Class);
+    if (getLangOpts().CPlusPlus0x && Class->needsImplicitMoveConstructor())
+      DeclareImplicitMoveConstructor(Class);
+  }
+
+  CanQualType T = Context.getCanonicalType(Context.getTypeDeclType(Class));
+  DeclarationName Name = Context.DeclarationNames.getCXXConstructorName(T);
+  return Class->lookup(Name);
+}
+
+/// \brief Look up the copying assignment operator for the given class.
+CXXMethodDecl *Sema::LookupCopyingAssignment(CXXRecordDecl *Class,
+                                             unsigned Quals, bool RValueThis,
+                                             unsigned ThisQuals) {
+  assert(!(Quals & ~(Qualifiers::Const | Qualifiers::Volatile)) &&
+         "non-const, non-volatile qualifiers for copy assignment arg");
+  assert(!(ThisQuals & ~(Qualifiers::Const | Qualifiers::Volatile)) &&
+         "non-const, non-volatile qualifiers for copy assignment this");
+  SpecialMemberOverloadResult *Result =
+    LookupSpecialMember(Class, CXXCopyAssignment, Quals & Qualifiers::Const,
+                        Quals & Qualifiers::Volatile, RValueThis,
+                        ThisQuals & Qualifiers::Const,
+                        ThisQuals & Qualifiers::Volatile);
+
+  return Result->getMethod();
+}
+
+/// \brief Look up the moving assignment operator for the given class.
+CXXMethodDecl *Sema::LookupMovingAssignment(CXXRecordDecl *Class,
+                                            bool RValueThis,
+                                            unsigned ThisQuals) {
+  assert(!(ThisQuals & ~(Qualifiers::Const | Qualifiers::Volatile)) &&
+         "non-const, non-volatile qualifiers for copy assignment this");
+  SpecialMemberOverloadResult *Result =
+    LookupSpecialMember(Class, CXXMoveAssignment, false, false, RValueThis,
+                        ThisQuals & Qualifiers::Const,
+                        ThisQuals & Qualifiers::Volatile);
+
+  return Result->getMethod();
+}
+
+/// \brief Look for the destructor of the given class.
+///
+/// During semantic analysis, this routine should be used in lieu of
+/// CXXRecordDecl::getDestructor().
+///
+/// \returns The destructor for this class.
+CXXDestructorDecl *Sema::LookupDestructor(CXXRecordDecl *Class) {
+  return cast<CXXDestructorDecl>(LookupSpecialMember(Class, CXXDestructor,
+                                                     false, false, false,
+                                                     false, false)->getMethod());
+}
+
+/// LookupLiteralOperator - Determine which literal operator should be used for
+/// a user-defined literal, per C++11 [lex.ext].
+///
+/// Normal overload resolution is not used to select which literal operator to
+/// call for a user-defined literal. Look up the provided literal operator name,
+/// and filter the results to the appropriate set for the given argument types.
+Sema::LiteralOperatorLookupResult
+Sema::LookupLiteralOperator(Scope *S, LookupResult &R,
+                            ArrayRef<QualType> ArgTys,
+                            bool AllowRawAndTemplate) {
+  LookupName(R, S);
+  assert(R.getResultKind() != LookupResult::Ambiguous &&
+         "literal operator lookup can't be ambiguous");
+
+  // Filter the lookup results appropriately.
+  LookupResult::Filter F = R.makeFilter();
+
+  bool FoundTemplate = false;
+  bool FoundRaw = false;
+  bool FoundExactMatch = false;
+
+  while (F.hasNext()) {
+    Decl *D = F.next();
+    if (UsingShadowDecl *USD = dyn_cast<UsingShadowDecl>(D))
+      D = USD->getTargetDecl();
+
+    bool IsTemplate = isa<FunctionTemplateDecl>(D);
+    bool IsRaw = false;
+    bool IsExactMatch = false;
+
+    if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
+      if (FD->getNumParams() == 1 &&
+          FD->getParamDecl(0)->getType()->getAs<PointerType>())
+        IsRaw = true;
+      else {
+        IsExactMatch = true;
+        for (unsigned ArgIdx = 0; ArgIdx != ArgTys.size(); ++ArgIdx) {
+          QualType ParamTy = FD->getParamDecl(ArgIdx)->getType();
+          if (!Context.hasSameUnqualifiedType(ArgTys[ArgIdx], ParamTy)) {
+            IsExactMatch = false;
+            break;
+          }
+        }
+      }
+    }
+
+    if (IsExactMatch) {
+      FoundExactMatch = true;
+      AllowRawAndTemplate = false;
+      if (FoundRaw || FoundTemplate) {
+        // Go through again and remove the raw and template decls we've
+        // already found.
+        F.restart();
+        FoundRaw = FoundTemplate = false;
+      }
+    } else if (AllowRawAndTemplate && (IsTemplate || IsRaw)) {
+      FoundTemplate |= IsTemplate;
+      FoundRaw |= IsRaw;
+    } else {
+      F.erase();
+    }
+  }
+
+  F.done();
+
+  // C++11 [lex.ext]p3, p4: If S contains a literal operator with a matching
+  // parameter type, that is used in preference to a raw literal operator
+  // or literal operator template.
+  if (FoundExactMatch)
+    return LOLR_Cooked;
+
+  // C++11 [lex.ext]p3, p4: S shall contain a raw literal operator or a literal
+  // operator template, but not both.
+  if (FoundRaw && FoundTemplate) {
+    Diag(R.getNameLoc(), diag::err_ovl_ambiguous_call) << R.getLookupName();
+    for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I) {
+      Decl *D = *I;
+      if (UsingShadowDecl *USD = dyn_cast<UsingShadowDecl>(D))
+        D = USD->getTargetDecl();
+      if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(D))
+        D = FunTmpl->getTemplatedDecl();
+      NoteOverloadCandidate(cast<FunctionDecl>(D));
+    }
+    return LOLR_Error;
+  }
+
+  if (FoundRaw)
+    return LOLR_Raw;
+
+  if (FoundTemplate)
+    return LOLR_Template;
+
+  // Didn't find anything we could use.
+  Diag(R.getNameLoc(), diag::err_ovl_no_viable_literal_operator)
+    << R.getLookupName() << (int)ArgTys.size() << ArgTys[0]
+    << (ArgTys.size() == 2 ? ArgTys[1] : QualType()) << AllowRawAndTemplate;
+  return LOLR_Error;
+}
+
+void ADLResult::insert(NamedDecl *New) {
+  NamedDecl *&Old = Decls[cast<NamedDecl>(New->getCanonicalDecl())];
+
+  // If we haven't yet seen a decl for this key, or the last decl
+  // was exactly this one, we're done.
+  if (Old == 0 || Old == New) {
+    Old = New;
+    return;
+  }
+
+  // Otherwise, decide which is a more recent redeclaration.
+  FunctionDecl *OldFD, *NewFD;
+  if (isa<FunctionTemplateDecl>(New)) {
+    OldFD = cast<FunctionTemplateDecl>(Old)->getTemplatedDecl();
+    NewFD = cast<FunctionTemplateDecl>(New)->getTemplatedDecl();
+  } else {
+    OldFD = cast<FunctionDecl>(Old);
+    NewFD = cast<FunctionDecl>(New);
+  }
+
+  FunctionDecl *Cursor = NewFD;
+  while (true) {
+    Cursor = Cursor->getPreviousDecl();
+
+    // If we got to the end without finding OldFD, OldFD is the newer
+    // declaration;  leave things as they are.
+    if (!Cursor) return;
+
+    // If we do find OldFD, then NewFD is newer.
+    if (Cursor == OldFD) break;
+
+    // Otherwise, keep looking.
+  }
+
+  Old = New;
+}
+
+void Sema::ArgumentDependentLookup(DeclarationName Name, bool Operator,
+                                   SourceLocation Loc,
+                                   llvm::ArrayRef<Expr *> Args,
+                                   ADLResult &Result,
+                                   bool StdNamespaceIsAssociated) {
+  // Find all of the associated namespaces and classes based on the
+  // arguments we have.
+  AssociatedNamespaceSet AssociatedNamespaces;
+  AssociatedClassSet AssociatedClasses;
+  FindAssociatedClassesAndNamespaces(Args,
+                                     AssociatedNamespaces,
+                                     AssociatedClasses);
+  if (StdNamespaceIsAssociated && StdNamespace)
+    AssociatedNamespaces.insert(getStdNamespace());
+
+  QualType T1, T2;
+  if (Operator) {
+    T1 = Args[0]->getType();
+    if (Args.size() >= 2)
+      T2 = Args[1]->getType();
+  }
+
+  // Try to complete all associated classes, in case they contain a
+  // declaration of a friend function.
+  for (AssociatedClassSet::iterator C = AssociatedClasses.begin(),
+                                    CEnd = AssociatedClasses.end();
+       C != CEnd; ++C)
+    RequireCompleteType(Loc, Context.getRecordType(*C), 0);
+
+  // C++ [basic.lookup.argdep]p3:
+  //   Let X be the lookup set produced by unqualified lookup (3.4.1)
+  //   and let Y be the lookup set produced by argument dependent
+  //   lookup (defined as follows). If X contains [...] then Y is
+  //   empty. Otherwise Y is the set of declarations found in the
+  //   namespaces associated with the argument types as described
+  //   below. The set of declarations found by the lookup of the name
+  //   is the union of X and Y.
+  //
+  // Here, we compute Y and add its members to the overloaded
+  // candidate set.
+  for (AssociatedNamespaceSet::iterator NS = AssociatedNamespaces.begin(),
+                                     NSEnd = AssociatedNamespaces.end();
+       NS != NSEnd; ++NS) {
+    //   When considering an associated namespace, the lookup is the
+    //   same as the lookup performed when the associated namespace is
+    //   used as a qualifier (3.4.3.2) except that:
+    //
+    //     -- Any using-directives in the associated namespace are
+    //        ignored.
+    //
+    //     -- Any namespace-scope friend functions declared in
+    //        associated classes are visible within their respective
+    //        namespaces even if they are not visible during an ordinary
+    //        lookup (11.4).
+    DeclContext::lookup_iterator I, E;
+    for (llvm::tie(I, E) = (*NS)->lookup(Name); I != E; ++I) {
+      NamedDecl *D = *I;
+      // If the only declaration here is an ordinary friend, consider
+      // it only if it was declared in an associated classes.
+      if (D->getIdentifierNamespace() == Decl::IDNS_OrdinaryFriend) {
+        DeclContext *LexDC = D->getLexicalDeclContext();
+        if (!AssociatedClasses.count(cast<CXXRecordDecl>(LexDC)))
+          continue;
+      }
+
+      if (isa<UsingShadowDecl>(D))
+        D = cast<UsingShadowDecl>(D)->getTargetDecl();
+
+      if (isa<FunctionDecl>(D)) {
+        if (Operator &&
+            !IsAcceptableNonMemberOperatorCandidate(cast<FunctionDecl>(D),
+                                                    T1, T2, Context))
+          continue;
+      } else if (!isa<FunctionTemplateDecl>(D))
+        continue;
+
+      Result.insert(D);
+    }
+  }
+}
+
+//----------------------------------------------------------------------------
+// Search for all visible declarations.
+//----------------------------------------------------------------------------
+VisibleDeclConsumer::~VisibleDeclConsumer() { }
+
+namespace {
+
+class ShadowContextRAII;
+
+class VisibleDeclsRecord {
+public:
+  /// \brief An entry in the shadow map, which is optimized to store a
+  /// single declaration (the common case) but can also store a list
+  /// of declarations.
+  typedef llvm::TinyPtrVector<NamedDecl*> ShadowMapEntry;
+
+private:
+  /// \brief A mapping from declaration names to the declarations that have
+  /// this name within a particular scope.
+  typedef llvm::DenseMap<DeclarationName, ShadowMapEntry> ShadowMap;
+
+  /// \brief A list of shadow maps, which is used to model name hiding.
+  std::list<ShadowMap> ShadowMaps;
+
+  /// \brief The declaration contexts we have already visited.
+  llvm::SmallPtrSet<DeclContext *, 8> VisitedContexts;
+
+  friend class ShadowContextRAII;
+
+public:
+  /// \brief Determine whether we have already visited this context
+  /// (and, if not, note that we are going to visit that context now).
+  bool visitedContext(DeclContext *Ctx) {
+    return !VisitedContexts.insert(Ctx);
+  }
+
+  bool alreadyVisitedContext(DeclContext *Ctx) {
+    return VisitedContexts.count(Ctx);
+  }
+
+  /// \brief Determine whether the given declaration is hidden in the
+  /// current scope.
+  ///
+  /// \returns the declaration that hides the given declaration, or
+  /// NULL if no such declaration exists.
+  NamedDecl *checkHidden(NamedDecl *ND);
+
+  /// \brief Add a declaration to the current shadow map.
+  void add(NamedDecl *ND) {
+    ShadowMaps.back()[ND->getDeclName()].push_back(ND);
+  }
+};
+
+/// \brief RAII object that records when we've entered a shadow context.
+class ShadowContextRAII {
+  VisibleDeclsRecord &Visible;
+
+  typedef VisibleDeclsRecord::ShadowMap ShadowMap;
+
+public:
+  ShadowContextRAII(VisibleDeclsRecord &Visible) : Visible(Visible) {
+    Visible.ShadowMaps.push_back(ShadowMap());
+  }
+
+  ~ShadowContextRAII() {
+    Visible.ShadowMaps.pop_back();
+  }
+};
+
+} // end anonymous namespace
+
+NamedDecl *VisibleDeclsRecord::checkHidden(NamedDecl *ND) {
+  // Look through using declarations.
+  ND = ND->getUnderlyingDecl();
+
+  unsigned IDNS = ND->getIdentifierNamespace();
+  std::list<ShadowMap>::reverse_iterator SM = ShadowMaps.rbegin();
+  for (std::list<ShadowMap>::reverse_iterator SMEnd = ShadowMaps.rend();
+       SM != SMEnd; ++SM) {
+    ShadowMap::iterator Pos = SM->find(ND->getDeclName());
+    if (Pos == SM->end())
+      continue;
+
+    for (ShadowMapEntry::iterator I = Pos->second.begin(),
+                               IEnd = Pos->second.end();
+         I != IEnd; ++I) {
+      // A tag declaration does not hide a non-tag declaration.
+      if ((*I)->hasTagIdentifierNamespace() &&
+          (IDNS & (Decl::IDNS_Member | Decl::IDNS_Ordinary |
+                   Decl::IDNS_ObjCProtocol)))
+        continue;
+
+      // Protocols are in distinct namespaces from everything else.
+      if ((((*I)->getIdentifierNamespace() & Decl::IDNS_ObjCProtocol)
+           || (IDNS & Decl::IDNS_ObjCProtocol)) &&
+          (*I)->getIdentifierNamespace() != IDNS)
+        continue;
+
+      // Functions and function templates in the same scope overload
+      // rather than hide.  FIXME: Look for hiding based on function
+      // signatures!
+      if ((*I)->isFunctionOrFunctionTemplate() &&
+          ND->isFunctionOrFunctionTemplate() &&
+          SM == ShadowMaps.rbegin())
+        continue;
+
+      // We've found a declaration that hides this one.
+      return *I;
+    }
+  }
+
+  return 0;
+}
+
+static void LookupVisibleDecls(DeclContext *Ctx, LookupResult &Result,
+                               bool QualifiedNameLookup,
+                               bool InBaseClass,
+                               VisibleDeclConsumer &Consumer,
+                               VisibleDeclsRecord &Visited) {
+  if (!Ctx)
+    return;
+
+  // Make sure we don't visit the same context twice.
+  if (Visited.visitedContext(Ctx->getPrimaryContext()))
+    return;
+
+  if (CXXRecordDecl *Class = dyn_cast<CXXRecordDecl>(Ctx))
+    Result.getSema().ForceDeclarationOfImplicitMembers(Class);
+
+  // Enumerate all of the results in this context.
+  for (DeclContext::all_lookups_iterator L = Ctx->lookups_begin(),
+                                      LEnd = Ctx->lookups_end();
+       L != LEnd; ++L) {
+    for (DeclContext::lookup_result R = *L; R.first != R.second; ++R.first) {
+      if (NamedDecl *ND = dyn_cast<NamedDecl>(*R.first)) {
+        if ((ND = Result.getAcceptableDecl(ND))) {
+          Consumer.FoundDecl(ND, Visited.checkHidden(ND), Ctx, InBaseClass);
+          Visited.add(ND);
+        }
+      }
+    }
+  }
+
+  // Traverse using directives for qualified name lookup.
+  if (QualifiedNameLookup) {
+    ShadowContextRAII Shadow(Visited);
+    DeclContext::udir_iterator I, E;
+    for (llvm::tie(I, E) = Ctx->getUsingDirectives(); I != E; ++I) {
+      LookupVisibleDecls((*I)->getNominatedNamespace(), Result,
+                         QualifiedNameLookup, InBaseClass, Consumer, Visited);
+    }
+  }
+
+  // Traverse the contexts of inherited C++ classes.
+  if (CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(Ctx)) {
+    if (!Record->hasDefinition())
+      return;
+
+    for (CXXRecordDecl::base_class_iterator B = Record->bases_begin(),
+                                         BEnd = Record->bases_end();
+         B != BEnd; ++B) {
+      QualType BaseType = B->getType();
+
+      // Don't look into dependent bases, because name lookup can't look
+      // there anyway.
+      if (BaseType->isDependentType())
+        continue;
+
+      const RecordType *Record = BaseType->getAs<RecordType>();
+      if (!Record)
+        continue;
+
+      // FIXME: It would be nice to be able to determine whether referencing
+      // a particular member would be ambiguous. For example, given
+      //
+      //   struct A { int member; };
+      //   struct B { int member; };
+      //   struct C : A, B { };
+      //
+      //   void f(C *c) { c->### }
+      //
+      // accessing 'member' would result in an ambiguity. However, we
+      // could be smart enough to qualify the member with the base
+      // class, e.g.,
+      //
+      //   c->B::member
+      //
+      // or
+      //
+      //   c->A::member
+
+      // Find results in this base class (and its bases).
+      ShadowContextRAII Shadow(Visited);
+      LookupVisibleDecls(Record->getDecl(), Result, QualifiedNameLookup,
+                         true, Consumer, Visited);
+    }
+  }
+
+  // Traverse the contexts of Objective-C classes.
+  if (ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Ctx)) {
+    // Traverse categories.
+    for (ObjCCategoryDecl *Category = IFace->getCategoryList();
+         Category; Category = Category->getNextClassCategory()) {
+      ShadowContextRAII Shadow(Visited);
+      LookupVisibleDecls(Category, Result, QualifiedNameLookup, false,
+                         Consumer, Visited);
+    }
+
+    // Traverse protocols.
+    for (ObjCInterfaceDecl::all_protocol_iterator
+         I = IFace->all_referenced_protocol_begin(),
+         E = IFace->all_referenced_protocol_end(); I != E; ++I) {
+      ShadowContextRAII Shadow(Visited);
+      LookupVisibleDecls(*I, Result, QualifiedNameLookup, false, Consumer,
+                         Visited);
+    }
+
+    // Traverse the superclass.
+    if (IFace->getSuperClass()) {
+      ShadowContextRAII Shadow(Visited);
+      LookupVisibleDecls(IFace->getSuperClass(), Result, QualifiedNameLookup,
+                         true, Consumer, Visited);
+    }
+
+    // If there is an implementation, traverse it. We do this to find
+    // synthesized ivars.
+    if (IFace->getImplementation()) {
+      ShadowContextRAII Shadow(Visited);
+      LookupVisibleDecls(IFace->getImplementation(), Result,
+                         QualifiedNameLookup, InBaseClass, Consumer, Visited);
+    }
+  } else if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Ctx)) {
+    for (ObjCProtocolDecl::protocol_iterator I = Protocol->protocol_begin(),
+           E = Protocol->protocol_end(); I != E; ++I) {
+      ShadowContextRAII Shadow(Visited);
+      LookupVisibleDecls(*I, Result, QualifiedNameLookup, false, Consumer,
+                         Visited);
+    }
+  } else if (ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(Ctx)) {
+    for (ObjCCategoryDecl::protocol_iterator I = Category->protocol_begin(),
+           E = Category->protocol_end(); I != E; ++I) {
+      ShadowContextRAII Shadow(Visited);
+      LookupVisibleDecls(*I, Result, QualifiedNameLookup, false, Consumer,
+                         Visited);
+    }
+
+    // If there is an implementation, traverse it.
+    if (Category->getImplementation()) {
+      ShadowContextRAII Shadow(Visited);
+      LookupVisibleDecls(Category->getImplementation(), Result,
+                         QualifiedNameLookup, true, Consumer, Visited);
+    }
+  }
+}
+
+static void LookupVisibleDecls(Scope *S, LookupResult &Result,
+                               UnqualUsingDirectiveSet &UDirs,
+                               VisibleDeclConsumer &Consumer,
+                               VisibleDeclsRecord &Visited) {
+  if (!S)
+    return;
+
+  if (!S->getEntity() ||
+      (!S->getParent() &&
+       !Visited.alreadyVisitedContext((DeclContext *)S->getEntity())) ||
+      ((DeclContext *)S->getEntity())->isFunctionOrMethod()) {
+    // Walk through the declarations in this Scope.
+    for (Scope::decl_iterator D = S->decl_begin(), DEnd = S->decl_end();
+         D != DEnd; ++D) {
+      if (NamedDecl *ND = dyn_cast<NamedDecl>(*D))
+        if ((ND = Result.getAcceptableDecl(ND))) {
+          Consumer.FoundDecl(ND, Visited.checkHidden(ND), 0, false);
+          Visited.add(ND);
+        }
+    }
+  }
+
+  // FIXME: C++ [temp.local]p8
+  DeclContext *Entity = 0;
+  if (S->getEntity()) {
+    // Look into this scope's declaration context, along with any of its
+    // parent lookup contexts (e.g., enclosing classes), up to the point
+    // where we hit the context stored in the next outer scope.
+    Entity = (DeclContext *)S->getEntity();
+    DeclContext *OuterCtx = findOuterContext(S).first; // FIXME
+
+    for (DeclContext *Ctx = Entity; Ctx && !Ctx->Equals(OuterCtx);
+         Ctx = Ctx->getLookupParent()) {
+      if (ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(Ctx)) {
+        if (Method->isInstanceMethod()) {
+          // For instance methods, look for ivars in the method's interface.
+          LookupResult IvarResult(Result.getSema(), Result.getLookupName(),
+                                  Result.getNameLoc(), Sema::LookupMemberName);
+          if (ObjCInterfaceDecl *IFace = Method->getClassInterface()) {
+            LookupVisibleDecls(IFace, IvarResult, /*QualifiedNameLookup=*/false,
+                               /*InBaseClass=*/false, Consumer, Visited);              
+          }
+        }
+
+        // We've already performed all of the name lookup that we need
+        // to for Objective-C methods; the next context will be the
+        // outer scope.
+        break;
+      }
+
+      if (Ctx->isFunctionOrMethod())
+        continue;
+
+      LookupVisibleDecls(Ctx, Result, /*QualifiedNameLookup=*/false,
+                         /*InBaseClass=*/false, Consumer, Visited);
+    }
+  } else if (!S->getParent()) {
+    // Look into the translation unit scope. We walk through the translation
+    // unit's declaration context, because the Scope itself won't have all of
+    // the declarations if we loaded a precompiled header.
+    // FIXME: We would like the translation unit's Scope object to point to the
+    // translation unit, so we don't need this special "if" branch. However,
+    // doing so would force the normal C++ name-lookup code to look into the
+    // translation unit decl when the IdentifierInfo chains would suffice.
+    // Once we fix that problem (which is part of a more general "don't look
+    // in DeclContexts unless we have to" optimization), we can eliminate this.
+    Entity = Result.getSema().Context.getTranslationUnitDecl();
+    LookupVisibleDecls(Entity, Result, /*QualifiedNameLookup=*/false,
+                       /*InBaseClass=*/false, Consumer, Visited);
+  }
+
+  if (Entity) {
+    // Lookup visible declarations in any namespaces found by using
+    // directives.
+    UnqualUsingDirectiveSet::const_iterator UI, UEnd;
+    llvm::tie(UI, UEnd) = UDirs.getNamespacesFor(Entity);
+    for (; UI != UEnd; ++UI)
+      LookupVisibleDecls(const_cast<DeclContext *>(UI->getNominatedNamespace()),
+                         Result, /*QualifiedNameLookup=*/false,
+                         /*InBaseClass=*/false, Consumer, Visited);
+  }
+
+  // Lookup names in the parent scope.
+  ShadowContextRAII Shadow(Visited);
+  LookupVisibleDecls(S->getParent(), Result, UDirs, Consumer, Visited);
+}
+
+void Sema::LookupVisibleDecls(Scope *S, LookupNameKind Kind,
+                              VisibleDeclConsumer &Consumer,
+                              bool IncludeGlobalScope) {
+  // Determine the set of using directives available during
+  // unqualified name lookup.
+  Scope *Initial = S;
+  UnqualUsingDirectiveSet UDirs;
+  if (getLangOpts().CPlusPlus) {
+    // Find the first namespace or translation-unit scope.
+    while (S && !isNamespaceOrTranslationUnitScope(S))
+      S = S->getParent();
+
+    UDirs.visitScopeChain(Initial, S);
+  }
+  UDirs.done();
+
+  // Look for visible declarations.
+  LookupResult Result(*this, DeclarationName(), SourceLocation(), Kind);
+  VisibleDeclsRecord Visited;
+  if (!IncludeGlobalScope)
+    Visited.visitedContext(Context.getTranslationUnitDecl());
+  ShadowContextRAII Shadow(Visited);
+  ::LookupVisibleDecls(Initial, Result, UDirs, Consumer, Visited);
+}
+
+void Sema::LookupVisibleDecls(DeclContext *Ctx, LookupNameKind Kind,
+                              VisibleDeclConsumer &Consumer,
+                              bool IncludeGlobalScope) {
+  LookupResult Result(*this, DeclarationName(), SourceLocation(), Kind);
+  VisibleDeclsRecord Visited;
+  if (!IncludeGlobalScope)
+    Visited.visitedContext(Context.getTranslationUnitDecl());
+  ShadowContextRAII Shadow(Visited);
+  ::LookupVisibleDecls(Ctx, Result, /*QualifiedNameLookup=*/true,
+                       /*InBaseClass=*/false, Consumer, Visited);
+}
+
+/// LookupOrCreateLabel - Do a name lookup of a label with the specified name.
+/// If GnuLabelLoc is a valid source location, then this is a definition
+/// of an __label__ label name, otherwise it is a normal label definition
+/// or use.
+LabelDecl *Sema::LookupOrCreateLabel(IdentifierInfo *II, SourceLocation Loc,
+                                     SourceLocation GnuLabelLoc) {
+  // Do a lookup to see if we have a label with this name already.
+  NamedDecl *Res = 0;
+
+  if (GnuLabelLoc.isValid()) {
+    // Local label definitions always shadow existing labels.
+    Res = LabelDecl::Create(Context, CurContext, Loc, II, GnuLabelLoc);
+    Scope *S = CurScope;
+    PushOnScopeChains(Res, S, true);
+    return cast<LabelDecl>(Res);
+  }
+
+  // Not a GNU local label.
+  Res = LookupSingleName(CurScope, II, Loc, LookupLabel, NotForRedeclaration);
+  // If we found a label, check to see if it is in the same context as us.
+  // When in a Block, we don't want to reuse a label in an enclosing function.
+  if (Res && Res->getDeclContext() != CurContext)
+    Res = 0;
+  if (Res == 0) {
+    // If not forward referenced or defined already, create the backing decl.
+    Res = LabelDecl::Create(Context, CurContext, Loc, II);
+    Scope *S = CurScope->getFnParent();
+    assert(S && "Not in a function?");
+    PushOnScopeChains(Res, S, true);
+  }
+  return cast<LabelDecl>(Res);
+}
+
+//===----------------------------------------------------------------------===//
+// Typo correction
+//===----------------------------------------------------------------------===//
+
+namespace {
+
+typedef llvm::StringMap<TypoCorrection, llvm::BumpPtrAllocator> TypoResultsMap;
+typedef std::map<unsigned, TypoResultsMap> TypoEditDistanceMap;
+
+static const unsigned MaxTypoDistanceResultSets = 5;
+
+class TypoCorrectionConsumer : public VisibleDeclConsumer {
+  /// \brief The name written that is a typo in the source.
+  StringRef Typo;
+
+  /// \brief The results found that have the smallest edit distance
+  /// found (so far) with the typo name.
+  ///
+  /// The pointer value being set to the current DeclContext indicates
+  /// whether there is a keyword with this name.
+  TypoEditDistanceMap BestResults;
+
+  Sema &SemaRef;
+
+public:
+  explicit TypoCorrectionConsumer(Sema &SemaRef, IdentifierInfo *Typo)
+    : Typo(Typo->getName()),
+      SemaRef(SemaRef) { }
+
+  virtual void FoundDecl(NamedDecl *ND, NamedDecl *Hiding, DeclContext *Ctx,
+                         bool InBaseClass);
+  void FoundName(StringRef Name);
+  void addKeywordResult(StringRef Keyword);
+  void addName(StringRef Name, NamedDecl *ND, unsigned Distance,
+               NestedNameSpecifier *NNS=NULL, bool isKeyword=false);
+  void addCorrection(TypoCorrection Correction);
+
+  typedef TypoResultsMap::iterator result_iterator;
+  typedef TypoEditDistanceMap::iterator distance_iterator;
+  distance_iterator begin() { return BestResults.begin(); }
+  distance_iterator end()  { return BestResults.end(); }
+  void erase(distance_iterator I) { BestResults.erase(I); }
+  unsigned size() const { return BestResults.size(); }
+  bool empty() const { return BestResults.empty(); }
+
+  TypoCorrection &operator[](StringRef Name) {
+    return BestResults.begin()->second[Name];
+  }
+
+  unsigned getBestEditDistance(bool Normalized) {
+    if (BestResults.empty())
+      return (std::numeric_limits<unsigned>::max)();
+
+    unsigned BestED = BestResults.begin()->first;
+    return Normalized ? TypoCorrection::NormalizeEditDistance(BestED) : BestED;
+  }
+};
+
+}
+
+void TypoCorrectionConsumer::FoundDecl(NamedDecl *ND, NamedDecl *Hiding,
+                                       DeclContext *Ctx, bool InBaseClass) {
+  // Don't consider hidden names for typo correction.
+  if (Hiding)
+    return;
+
+  // Only consider entities with identifiers for names, ignoring
+  // special names (constructors, overloaded operators, selectors,
+  // etc.).
+  IdentifierInfo *Name = ND->getIdentifier();
+  if (!Name)
+    return;
+
+  FoundName(Name->getName());
+}
+
+void TypoCorrectionConsumer::FoundName(StringRef Name) {
+  // Use a simple length-based heuristic to determine the minimum possible
+  // edit distance. If the minimum isn't good enough, bail out early.
+  unsigned MinED = abs((int)Name.size() - (int)Typo.size());
+  if (MinED && Typo.size() / MinED < 3)
+    return;
+
+  // Compute an upper bound on the allowable edit distance, so that the
+  // edit-distance algorithm can short-circuit.
+  unsigned UpperBound = (Typo.size() + 2) / 3;
+
+  // Compute the edit distance between the typo and the name of this
+  // entity, and add the identifier to the list of results.
+  addName(Name, NULL, Typo.edit_distance(Name, true, UpperBound));
+}
+
+void TypoCorrectionConsumer::addKeywordResult(StringRef Keyword) {
+  // Compute the edit distance between the typo and this keyword,
+  // and add the keyword to the list of results.
+  addName(Keyword, NULL, Typo.edit_distance(Keyword), NULL, true);
+}
+
+void TypoCorrectionConsumer::addName(StringRef Name,
+                                     NamedDecl *ND,
+                                     unsigned Distance,
+                                     NestedNameSpecifier *NNS,
+                                     bool isKeyword) {
+  TypoCorrection TC(&SemaRef.Context.Idents.get(Name), ND, NNS, Distance);
+  if (isKeyword) TC.makeKeyword();
+  addCorrection(TC);
+}
+
+void TypoCorrectionConsumer::addCorrection(TypoCorrection Correction) {
+  StringRef Name = Correction.getCorrectionAsIdentifierInfo()->getName();
+  TypoResultsMap &Map = BestResults[Correction.getEditDistance(false)];
+
+  TypoCorrection &CurrentCorrection = Map[Name];
+  if (!CurrentCorrection ||
+      // FIXME: The following should be rolled up into an operator< on
+      // TypoCorrection with a more principled definition.
+      CurrentCorrection.isKeyword() < Correction.isKeyword() ||
+      Correction.getAsString(SemaRef.getLangOpts()) <
+      CurrentCorrection.getAsString(SemaRef.getLangOpts()))
+    CurrentCorrection = Correction;
+
+  while (BestResults.size() > MaxTypoDistanceResultSets)
+    erase(llvm::prior(BestResults.end()));
+}
+
+// Fill the supplied vector with the IdentifierInfo pointers for each piece of
+// the given NestedNameSpecifier (i.e. given a NestedNameSpecifier "foo::bar::",
+// fill the vector with the IdentifierInfo pointers for "foo" and "bar").
+static void getNestedNameSpecifierIdentifiers(
+    NestedNameSpecifier *NNS,
+    SmallVectorImpl<const IdentifierInfo*> &Identifiers) {
+  if (NestedNameSpecifier *Prefix = NNS->getPrefix())
+    getNestedNameSpecifierIdentifiers(Prefix, Identifiers);
+  else
+    Identifiers.clear();
+
+  const IdentifierInfo *II = NULL;
+
+  switch (NNS->getKind()) {
+  case NestedNameSpecifier::Identifier:
+    II = NNS->getAsIdentifier();
+    break;
+
+  case NestedNameSpecifier::Namespace:
+    if (NNS->getAsNamespace()->isAnonymousNamespace())
+      return;
+    II = NNS->getAsNamespace()->getIdentifier();
+    break;
+
+  case NestedNameSpecifier::NamespaceAlias:
+    II = NNS->getAsNamespaceAlias()->getIdentifier();
+    break;
+
+  case NestedNameSpecifier::TypeSpecWithTemplate:
+  case NestedNameSpecifier::TypeSpec:
+    II = QualType(NNS->getAsType(), 0).getBaseTypeIdentifier();
+    break;
+
+  case NestedNameSpecifier::Global:
+    return;
+  }
+
+  if (II)
+    Identifiers.push_back(II);
+}
+
+namespace {
+
+class SpecifierInfo {
+ public:
+  DeclContext* DeclCtx;
+  NestedNameSpecifier* NameSpecifier;
+  unsigned EditDistance;
+
+  SpecifierInfo(DeclContext *Ctx, NestedNameSpecifier *NNS, unsigned ED)
+      : DeclCtx(Ctx), NameSpecifier(NNS), EditDistance(ED) {}
+};
+
+typedef SmallVector<DeclContext*, 4> DeclContextList;
+typedef SmallVector<SpecifierInfo, 16> SpecifierInfoList;
+
+class NamespaceSpecifierSet {
+  ASTContext &Context;
+  DeclContextList CurContextChain;
+  SmallVector<const IdentifierInfo*, 4> CurContextIdentifiers;
+  SmallVector<const IdentifierInfo*, 4> CurNameSpecifierIdentifiers;
+  bool isSorted;
+
+  SpecifierInfoList Specifiers;
+  llvm::SmallSetVector<unsigned, 4> Distances;
+  llvm::DenseMap<unsigned, SpecifierInfoList> DistanceMap;
+
+  /// \brief Helper for building the list of DeclContexts between the current
+  /// context and the top of the translation unit
+  static DeclContextList BuildContextChain(DeclContext *Start);
+
+  void SortNamespaces();
+
+ public:
+  NamespaceSpecifierSet(ASTContext &Context, DeclContext *CurContext,
+                        CXXScopeSpec *CurScopeSpec)
+      : Context(Context), CurContextChain(BuildContextChain(CurContext)),
+        isSorted(true) {
+    if (CurScopeSpec && CurScopeSpec->getScopeRep())
+      getNestedNameSpecifierIdentifiers(CurScopeSpec->getScopeRep(),
+                                        CurNameSpecifierIdentifiers);
+    // Build the list of identifiers that would be used for an absolute
+    // (from the global context) NestedNameSpecifier refering to the current
+    // context.
+    for (DeclContextList::reverse_iterator C = CurContextChain.rbegin(),
+                                        CEnd = CurContextChain.rend();
+         C != CEnd; ++C) {
+      if (NamespaceDecl *ND = dyn_cast_or_null<NamespaceDecl>(*C))
+        CurContextIdentifiers.push_back(ND->getIdentifier());
+    }
+  }
+
+  /// \brief Add the namespace to the set, computing the corresponding
+  /// NestedNameSpecifier and its distance in the process.
+  void AddNamespace(NamespaceDecl *ND);
+
+  typedef SpecifierInfoList::iterator iterator;
+  iterator begin() {
+    if (!isSorted) SortNamespaces();
+    return Specifiers.begin();
+  }
+  iterator end() { return Specifiers.end(); }
+};
+
+}
+
+DeclContextList NamespaceSpecifierSet::BuildContextChain(DeclContext *Start) {
+  assert(Start && "Bulding a context chain from a null context");
+  DeclContextList Chain;
+  for (DeclContext *DC = Start->getPrimaryContext(); DC != NULL;
+       DC = DC->getLookupParent()) {
+    NamespaceDecl *ND = dyn_cast_or_null<NamespaceDecl>(DC);
+    if (!DC->isInlineNamespace() && !DC->isTransparentContext() &&
+        !(ND && ND->isAnonymousNamespace()))
+      Chain.push_back(DC->getPrimaryContext());
+  }
+  return Chain;
+}
+
+void NamespaceSpecifierSet::SortNamespaces() {
+  SmallVector<unsigned, 4> sortedDistances;
+  sortedDistances.append(Distances.begin(), Distances.end());
+
+  if (sortedDistances.size() > 1)
+    std::sort(sortedDistances.begin(), sortedDistances.end());
+
+  Specifiers.clear();
+  for (SmallVector<unsigned, 4>::iterator DI = sortedDistances.begin(),
+                                       DIEnd = sortedDistances.end();
+       DI != DIEnd; ++DI) {
+    SpecifierInfoList &SpecList = DistanceMap[*DI];
+    Specifiers.append(SpecList.begin(), SpecList.end());
+  }
+
+  isSorted = true;
+}
+
+void NamespaceSpecifierSet::AddNamespace(NamespaceDecl *ND) {
+  DeclContext *Ctx = cast<DeclContext>(ND);
+  NestedNameSpecifier *NNS = NULL;
+  unsigned NumSpecifiers = 0;
+  DeclContextList NamespaceDeclChain(BuildContextChain(Ctx));
+  DeclContextList FullNamespaceDeclChain(NamespaceDeclChain);
+
+  // Eliminate common elements from the two DeclContext chains.
+  for (DeclContextList::reverse_iterator C = CurContextChain.rbegin(),
+                                      CEnd = CurContextChain.rend();
+       C != CEnd && !NamespaceDeclChain.empty() &&
+       NamespaceDeclChain.back() == *C; ++C) {
+    NamespaceDeclChain.pop_back();
+  }
+
+  // Add an explicit leading '::' specifier if needed.
+  if (NamespaceDecl *ND =
+        NamespaceDeclChain.empty() ? NULL :
+          dyn_cast_or_null<NamespaceDecl>(NamespaceDeclChain.back())) {
+    IdentifierInfo *Name = ND->getIdentifier();
+    if (std::find(CurContextIdentifiers.begin(), CurContextIdentifiers.end(),
+                  Name) != CurContextIdentifiers.end() ||
+        std::find(CurNameSpecifierIdentifiers.begin(),
+                  CurNameSpecifierIdentifiers.end(),
+                  Name) != CurNameSpecifierIdentifiers.end()) {
+      NamespaceDeclChain = FullNamespaceDeclChain;
+      NNS = NestedNameSpecifier::GlobalSpecifier(Context);
+    }
+  }
+
+  // Build the NestedNameSpecifier from what is left of the NamespaceDeclChain
+  for (DeclContextList::reverse_iterator C = NamespaceDeclChain.rbegin(),
+                                      CEnd = NamespaceDeclChain.rend();
+       C != CEnd; ++C) {
+    NamespaceDecl *ND = dyn_cast_or_null<NamespaceDecl>(*C);
+    if (ND) {
+      NNS = NestedNameSpecifier::Create(Context, NNS, ND);
+      ++NumSpecifiers;
+    }
+  }
+
+  // If the built NestedNameSpecifier would be replacing an existing
+  // NestedNameSpecifier, use the number of component identifiers that
+  // would need to be changed as the edit distance instead of the number
+  // of components in the built NestedNameSpecifier.
+  if (NNS && !CurNameSpecifierIdentifiers.empty()) {
+    SmallVector<const IdentifierInfo*, 4> NewNameSpecifierIdentifiers;
+    getNestedNameSpecifierIdentifiers(NNS, NewNameSpecifierIdentifiers);
+    NumSpecifiers = llvm::ComputeEditDistance(
+      llvm::ArrayRef<const IdentifierInfo*>(CurNameSpecifierIdentifiers),
+      llvm::ArrayRef<const IdentifierInfo*>(NewNameSpecifierIdentifiers));
+  }
+
+  isSorted = false;
+  Distances.insert(NumSpecifiers);
+  DistanceMap[NumSpecifiers].push_back(SpecifierInfo(Ctx, NNS, NumSpecifiers));
+}
+
+/// \brief Perform name lookup for a possible result for typo correction.
+static void LookupPotentialTypoResult(Sema &SemaRef,
+                                      LookupResult &Res,
+                                      IdentifierInfo *Name,
+                                      Scope *S, CXXScopeSpec *SS,
+                                      DeclContext *MemberContext,
+                                      bool EnteringContext,
+                                      bool isObjCIvarLookup) {
+  Res.suppressDiagnostics();
+  Res.clear();
+  Res.setLookupName(Name);
+  if (MemberContext) {
+    if (ObjCInterfaceDecl *Class = dyn_cast<ObjCInterfaceDecl>(MemberContext)) {
+      if (isObjCIvarLookup) {
+        if (ObjCIvarDecl *Ivar = Class->lookupInstanceVariable(Name)) {
+          Res.addDecl(Ivar);
+          Res.resolveKind();
+          return;
+        }
+      }
+
+      if (ObjCPropertyDecl *Prop = Class->FindPropertyDeclaration(Name)) {
+        Res.addDecl(Prop);
+        Res.resolveKind();
+        return;
+      }
+    }
+
+    SemaRef.LookupQualifiedName(Res, MemberContext);
+    return;
+  }
+
+  SemaRef.LookupParsedName(Res, S, SS, /*AllowBuiltinCreation=*/false,
+                           EnteringContext);
+
+  // Fake ivar lookup; this should really be part of
+  // LookupParsedName.
+  if (ObjCMethodDecl *Method = SemaRef.getCurMethodDecl()) {
+    if (Method->isInstanceMethod() && Method->getClassInterface() &&
+        (Res.empty() ||
+         (Res.isSingleResult() &&
+          Res.getFoundDecl()->isDefinedOutsideFunctionOrMethod()))) {
+       if (ObjCIvarDecl *IV
+             = Method->getClassInterface()->lookupInstanceVariable(Name)) {
+         Res.addDecl(IV);
+         Res.resolveKind();
+       }
+     }
+  }
+}
+
+/// \brief Add keywords to the consumer as possible typo corrections.
+static void AddKeywordsToConsumer(Sema &SemaRef,
+                                  TypoCorrectionConsumer &Consumer,
+                                  Scope *S, CorrectionCandidateCallback &CCC) {
+  if (CCC.WantObjCSuper)
+    Consumer.addKeywordResult("super");
+
+  if (CCC.WantTypeSpecifiers) {
+    // Add type-specifier keywords to the set of results.
+    const char *CTypeSpecs[] = {
+      "char", "const", "double", "enum", "float", "int", "long", "short",
+      "signed", "struct", "union", "unsigned", "void", "volatile", 
+      "_Complex", "_Imaginary",
+      // storage-specifiers as well
+      "extern", "inline", "static", "typedef"
+    };
+
+    const unsigned NumCTypeSpecs = sizeof(CTypeSpecs) / sizeof(CTypeSpecs[0]);
+    for (unsigned I = 0; I != NumCTypeSpecs; ++I)
+      Consumer.addKeywordResult(CTypeSpecs[I]);
+
+    if (SemaRef.getLangOpts().C99)
+      Consumer.addKeywordResult("restrict");
+    if (SemaRef.getLangOpts().Bool || SemaRef.getLangOpts().CPlusPlus)
+      Consumer.addKeywordResult("bool");
+    else if (SemaRef.getLangOpts().C99)
+      Consumer.addKeywordResult("_Bool");
+    
+    if (SemaRef.getLangOpts().CPlusPlus) {
+      Consumer.addKeywordResult("class");
+      Consumer.addKeywordResult("typename");
+      Consumer.addKeywordResult("wchar_t");
+
+      if (SemaRef.getLangOpts().CPlusPlus0x) {
+        Consumer.addKeywordResult("char16_t");
+        Consumer.addKeywordResult("char32_t");
+        Consumer.addKeywordResult("constexpr");
+        Consumer.addKeywordResult("decltype");
+        Consumer.addKeywordResult("thread_local");
+      }
+    }
+
+    if (SemaRef.getLangOpts().GNUMode)
+      Consumer.addKeywordResult("typeof");
+  }
+
+  if (CCC.WantCXXNamedCasts && SemaRef.getLangOpts().CPlusPlus) {
+    Consumer.addKeywordResult("const_cast");
+    Consumer.addKeywordResult("dynamic_cast");
+    Consumer.addKeywordResult("reinterpret_cast");
+    Consumer.addKeywordResult("static_cast");
+  }
+
+  if (CCC.WantExpressionKeywords) {
+    Consumer.addKeywordResult("sizeof");
+    if (SemaRef.getLangOpts().Bool || SemaRef.getLangOpts().CPlusPlus) {
+      Consumer.addKeywordResult("false");
+      Consumer.addKeywordResult("true");
+    }
+
+    if (SemaRef.getLangOpts().CPlusPlus) {
+      const char *CXXExprs[] = {
+        "delete", "new", "operator", "throw", "typeid"
+      };
+      const unsigned NumCXXExprs = sizeof(CXXExprs) / sizeof(CXXExprs[0]);
+      for (unsigned I = 0; I != NumCXXExprs; ++I)
+        Consumer.addKeywordResult(CXXExprs[I]);
+
+      if (isa<CXXMethodDecl>(SemaRef.CurContext) &&
+          cast<CXXMethodDecl>(SemaRef.CurContext)->isInstance())
+        Consumer.addKeywordResult("this");
+
+      if (SemaRef.getLangOpts().CPlusPlus0x) {
+        Consumer.addKeywordResult("alignof");
+        Consumer.addKeywordResult("nullptr");
+      }
+    }
+  }
+
+  if (CCC.WantRemainingKeywords) {
+    if (SemaRef.getCurFunctionOrMethodDecl() || SemaRef.getCurBlock()) {
+      // Statements.
+      const char *CStmts[] = {
+        "do", "else", "for", "goto", "if", "return", "switch", "while" };
+      const unsigned NumCStmts = sizeof(CStmts) / sizeof(CStmts[0]);
+      for (unsigned I = 0; I != NumCStmts; ++I)
+        Consumer.addKeywordResult(CStmts[I]);
+
+      if (SemaRef.getLangOpts().CPlusPlus) {
+        Consumer.addKeywordResult("catch");
+        Consumer.addKeywordResult("try");
+      }
+
+      if (S && S->getBreakParent())
+        Consumer.addKeywordResult("break");
+
+      if (S && S->getContinueParent())
+        Consumer.addKeywordResult("continue");
+
+      if (!SemaRef.getCurFunction()->SwitchStack.empty()) {
+        Consumer.addKeywordResult("case");
+        Consumer.addKeywordResult("default");
+      }
+    } else {
+      if (SemaRef.getLangOpts().CPlusPlus) {
+        Consumer.addKeywordResult("namespace");
+        Consumer.addKeywordResult("template");
+      }
+
+      if (S && S->isClassScope()) {
+        Consumer.addKeywordResult("explicit");
+        Consumer.addKeywordResult("friend");
+        Consumer.addKeywordResult("mutable");
+        Consumer.addKeywordResult("private");
+        Consumer.addKeywordResult("protected");
+        Consumer.addKeywordResult("public");
+        Consumer.addKeywordResult("virtual");
+      }
+    }
+
+    if (SemaRef.getLangOpts().CPlusPlus) {
+      Consumer.addKeywordResult("using");
+
+      if (SemaRef.getLangOpts().CPlusPlus0x)
+        Consumer.addKeywordResult("static_assert");
+    }
+  }
+}
+
+static bool isCandidateViable(CorrectionCandidateCallback &CCC,
+                              TypoCorrection &Candidate) {
+  Candidate.setCallbackDistance(CCC.RankCandidate(Candidate));
+  return Candidate.getEditDistance(false) != TypoCorrection::InvalidDistance;
+}
+
+/// \brief Try to "correct" a typo in the source code by finding
+/// visible declarations whose names are similar to the name that was
+/// present in the source code.
+///
+/// \param TypoName the \c DeclarationNameInfo structure that contains
+/// the name that was present in the source code along with its location.
+///
+/// \param LookupKind the name-lookup criteria used to search for the name.
+///
+/// \param S the scope in which name lookup occurs.
+///
+/// \param SS the nested-name-specifier that precedes the name we're
+/// looking for, if present.
+///
+/// \param CCC A CorrectionCandidateCallback object that provides further
+/// validation of typo correction candidates. It also provides flags for
+/// determining the set of keywords permitted.
+///
+/// \param MemberContext if non-NULL, the context in which to look for
+/// a member access expression.
+///
+/// \param EnteringContext whether we're entering the context described by
+/// the nested-name-specifier SS.
+///
+/// \param OPT when non-NULL, the search for visible declarations will
+/// also walk the protocols in the qualified interfaces of \p OPT.
+///
+/// \returns a \c TypoCorrection containing the corrected name if the typo
+/// along with information such as the \c NamedDecl where the corrected name
+/// was declared, and any additional \c NestedNameSpecifier needed to access
+/// it (C++ only). The \c TypoCorrection is empty if there is no correction.
+TypoCorrection Sema::CorrectTypo(const DeclarationNameInfo &TypoName,
+                                 Sema::LookupNameKind LookupKind,
+                                 Scope *S, CXXScopeSpec *SS,
+                                 CorrectionCandidateCallback &CCC,
+                                 DeclContext *MemberContext,
+                                 bool EnteringContext,
+                                 const ObjCObjectPointerType *OPT) {
+  if (Diags.hasFatalErrorOccurred() || !getLangOpts().SpellChecking)
+    return TypoCorrection();
+
+  // In Microsoft mode, don't perform typo correction in a template member
+  // function dependent context because it interferes with the "lookup into
+  // dependent bases of class templates" feature.
+  if (getLangOpts().MicrosoftMode && CurContext->isDependentContext() &&
+      isa<CXXMethodDecl>(CurContext))
+    return TypoCorrection();
+
+  // We only attempt to correct typos for identifiers.
+  IdentifierInfo *Typo = TypoName.getName().getAsIdentifierInfo();
+  if (!Typo)
+    return TypoCorrection();
+
+  // If the scope specifier itself was invalid, don't try to correct
+  // typos.
+  if (SS && SS->isInvalid())
+    return TypoCorrection();
+
+  // Never try to correct typos during template deduction or
+  // instantiation.
+  if (!ActiveTemplateInstantiations.empty())
+    return TypoCorrection();
+
+  NamespaceSpecifierSet Namespaces(Context, CurContext, SS);
+
+  TypoCorrectionConsumer Consumer(*this, Typo);
+
+  // If a callback object considers an empty typo correction candidate to be
+  // viable, assume it does not do any actual validation of the candidates.
+  TypoCorrection EmptyCorrection;
+  bool ValidatingCallback = !isCandidateViable(CCC, EmptyCorrection);
+
+  // Perform name lookup to find visible, similarly-named entities.
+  bool IsUnqualifiedLookup = false;
+  DeclContext *QualifiedDC = MemberContext;
+  if (MemberContext) {
+    LookupVisibleDecls(MemberContext, LookupKind, Consumer);
+
+    // Look in qualified interfaces.
+    if (OPT) {
+      for (ObjCObjectPointerType::qual_iterator
+             I = OPT->qual_begin(), E = OPT->qual_end();
+           I != E; ++I)
+        LookupVisibleDecls(*I, LookupKind, Consumer);
+    }
+  } else if (SS && SS->isSet()) {
+    QualifiedDC = computeDeclContext(*SS, EnteringContext);
+    if (!QualifiedDC)
+      return TypoCorrection();
+
+    // Provide a stop gap for files that are just seriously broken.  Trying
+    // to correct all typos can turn into a HUGE performance penalty, causing
+    // some files to take minutes to get rejected by the parser.
+    if (TyposCorrected + UnqualifiedTyposCorrected.size() >= 20)
+      return TypoCorrection();
+    ++TyposCorrected;
+
+    LookupVisibleDecls(QualifiedDC, LookupKind, Consumer);
+  } else {
+    IsUnqualifiedLookup = true;
+    UnqualifiedTyposCorrectedMap::iterator Cached
+      = UnqualifiedTyposCorrected.find(Typo);
+    if (Cached != UnqualifiedTyposCorrected.end()) {
+      // Add the cached value, unless it's a keyword or fails validation. In the
+      // keyword case, we'll end up adding the keyword below.
+      if (Cached->second) {
+        if (!Cached->second.isKeyword() &&
+            isCandidateViable(CCC, Cached->second))
+          Consumer.addCorrection(Cached->second);
+      } else {
+        // Only honor no-correction cache hits when a callback that will validate
+        // correction candidates is not being used.
+        if (!ValidatingCallback)
+          return TypoCorrection();
+      }
+    }
+    if (Cached == UnqualifiedTyposCorrected.end()) {
+      // Provide a stop gap for files that are just seriously broken.  Trying
+      // to correct all typos can turn into a HUGE performance penalty, causing
+      // some files to take minutes to get rejected by the parser.
+      if (TyposCorrected + UnqualifiedTyposCorrected.size() >= 20)
+        return TypoCorrection();
+    }
+  }
+
+  // Determine whether we are going to search in the various namespaces for
+  // corrections.
+  bool SearchNamespaces
+    = getLangOpts().CPlusPlus &&
+      (IsUnqualifiedLookup || (QualifiedDC && QualifiedDC->isNamespace()));
+  
+  if (IsUnqualifiedLookup || SearchNamespaces) {
+    // For unqualified lookup, look through all of the names that we have
+    // seen in this translation unit.
+    // FIXME: Re-add the ability to skip very unlikely potential corrections.
+    for (IdentifierTable::iterator I = Context.Idents.begin(),
+                                IEnd = Context.Idents.end();
+         I != IEnd; ++I)
+      Consumer.FoundName(I->getKey());
+
+    // Walk through identifiers in external identifier sources.
+    // FIXME: Re-add the ability to skip very unlikely potential corrections.
+    if (IdentifierInfoLookup *External
+                            = Context.Idents.getExternalIdentifierLookup()) {
+      OwningPtr<IdentifierIterator> Iter(External->getIdentifiers());
+      do {
+        StringRef Name = Iter->Next();
+        if (Name.empty())
+          break;
+
+        Consumer.FoundName(Name);
+      } while (true);
+    }
+  }
+
+  AddKeywordsToConsumer(*this, Consumer, S, CCC);
+
+  // If we haven't found anything, we're done.
+  if (Consumer.empty()) {
+    // If this was an unqualified lookup, note that no correction was found.
+    if (IsUnqualifiedLookup)
+      (void)UnqualifiedTyposCorrected[Typo];
+
+    return TypoCorrection();
+  }
+
+  // Make sure that the user typed at least 3 characters for each correction
+  // made. Otherwise, we don't even both looking at the results.
+  unsigned ED = Consumer.getBestEditDistance(true);
+  if (ED > 0 && Typo->getName().size() / ED < 3) {
+    // If this was an unqualified lookup, note that no correction was found.
+    if (IsUnqualifiedLookup)
+      (void)UnqualifiedTyposCorrected[Typo];
+
+    return TypoCorrection();
+  }
+
+  // Build the NestedNameSpecifiers for the KnownNamespaces, if we're going
+  // to search those namespaces.
+  if (SearchNamespaces) {
+    // Load any externally-known namespaces.
+    if (ExternalSource && !LoadedExternalKnownNamespaces) {
+      SmallVector<NamespaceDecl *, 4> ExternalKnownNamespaces;
+      LoadedExternalKnownNamespaces = true;
+      ExternalSource->ReadKnownNamespaces(ExternalKnownNamespaces);
+      for (unsigned I = 0, N = ExternalKnownNamespaces.size(); I != N; ++I)
+        KnownNamespaces[ExternalKnownNamespaces[I]] = true;
+    }
+    
+    for (llvm::DenseMap<NamespaceDecl*, bool>::iterator 
+           KNI = KnownNamespaces.begin(),
+           KNIEnd = KnownNamespaces.end();
+         KNI != KNIEnd; ++KNI)
+      Namespaces.AddNamespace(KNI->first);
+  }
+
+  // Weed out any names that could not be found by name lookup or, if a
+  // CorrectionCandidateCallback object was provided, failed validation.
+  llvm::SmallVector<TypoCorrection, 16> QualifiedResults;
+  LookupResult TmpRes(*this, TypoName, LookupKind);
+  TmpRes.suppressDiagnostics();
+  while (!Consumer.empty()) {
+    TypoCorrectionConsumer::distance_iterator DI = Consumer.begin();
+    unsigned ED = DI->first;
+    for (TypoCorrectionConsumer::result_iterator I = DI->second.begin(),
+                                              IEnd = DI->second.end();
+         I != IEnd; /* Increment in loop. */) {
+      // If the item already has been looked up or is a keyword, keep it.
+      // If a validator callback object was given, drop the correction
+      // unless it passes validation.
+      if (I->second.isResolved()) {
+        TypoCorrectionConsumer::result_iterator Prev = I;
+        ++I;
+        if (!isCandidateViable(CCC, Prev->second))
+          DI->second.erase(Prev);
+        continue;
+      }
+
+      // Perform name lookup on this name.
+      IdentifierInfo *Name = I->second.getCorrectionAsIdentifierInfo();
+      LookupPotentialTypoResult(*this, TmpRes, Name, S, SS, MemberContext,
+                                EnteringContext, CCC.IsObjCIvarLookup);
+
+      switch (TmpRes.getResultKind()) {
+      case LookupResult::NotFound:
+      case LookupResult::NotFoundInCurrentInstantiation:
+      case LookupResult::FoundUnresolvedValue:
+        QualifiedResults.push_back(I->second);
+        // We didn't find this name in our scope, or didn't like what we found;
+        // ignore it.
+        {
+          TypoCorrectionConsumer::result_iterator Next = I;
+          ++Next;
+          DI->second.erase(I);
+          I = Next;
+        }
+        break;
+
+      case LookupResult::Ambiguous:
+        // We don't deal with ambiguities.
+        return TypoCorrection();
+
+      case LookupResult::FoundOverloaded: {
+        TypoCorrectionConsumer::result_iterator Prev = I;
+        // Store all of the Decls for overloaded symbols
+        for (LookupResult::iterator TRD = TmpRes.begin(),
+                                 TRDEnd = TmpRes.end();
+             TRD != TRDEnd; ++TRD)
+          I->second.addCorrectionDecl(*TRD);
+        ++I;
+        if (!isCandidateViable(CCC, Prev->second))
+          DI->second.erase(Prev);
+        break;
+      }
+
+      case LookupResult::Found: {
+        TypoCorrectionConsumer::result_iterator Prev = I;
+        I->second.setCorrectionDecl(TmpRes.getAsSingle<NamedDecl>());
+        ++I;
+        if (!isCandidateViable(CCC, Prev->second))
+          DI->second.erase(Prev);
+        break;
+      }
+
+      }
+    }
+
+    if (DI->second.empty())
+      Consumer.erase(DI);
+    else if (!getLangOpts().CPlusPlus || QualifiedResults.empty() || !ED)
+      // If there are results in the closest possible bucket, stop
+      break;
+
+    // Only perform the qualified lookups for C++
+    if (SearchNamespaces) {
+      TmpRes.suppressDiagnostics();
+      for (llvm::SmallVector<TypoCorrection,
+                             16>::iterator QRI = QualifiedResults.begin(),
+                                        QRIEnd = QualifiedResults.end();
+           QRI != QRIEnd; ++QRI) {
+        for (NamespaceSpecifierSet::iterator NI = Namespaces.begin(),
+                                          NIEnd = Namespaces.end();
+             NI != NIEnd; ++NI) {
+          DeclContext *Ctx = NI->DeclCtx;
+
+          // FIXME: Stop searching once the namespaces are too far away to create
+          // acceptable corrections for this identifier (since the namespaces
+          // are sorted in ascending order by edit distance).
+
+          TmpRes.clear();
+          TmpRes.setLookupName(QRI->getCorrectionAsIdentifierInfo());
+          if (!LookupQualifiedName(TmpRes, Ctx)) continue;
+
+          // Any corrections added below will be validated in subsequent
+          // iterations of the main while() loop over the Consumer's contents.
+          switch (TmpRes.getResultKind()) {
+          case LookupResult::Found: {
+            TypoCorrection TC(*QRI);
+            TC.setCorrectionDecl(TmpRes.getAsSingle<NamedDecl>());
+            TC.setCorrectionSpecifier(NI->NameSpecifier);
+            TC.setQualifierDistance(NI->EditDistance);
+            Consumer.addCorrection(TC);
+            break;
+          }
+          case LookupResult::FoundOverloaded: {
+            TypoCorrection TC(*QRI);
+            TC.setCorrectionSpecifier(NI->NameSpecifier);
+            TC.setQualifierDistance(NI->EditDistance);
+            for (LookupResult::iterator TRD = TmpRes.begin(),
+                                     TRDEnd = TmpRes.end();
+                 TRD != TRDEnd; ++TRD)
+              TC.addCorrectionDecl(*TRD);
+            Consumer.addCorrection(TC);
+            break;
+          }
+          case LookupResult::NotFound:
+          case LookupResult::NotFoundInCurrentInstantiation:
+          case LookupResult::Ambiguous:
+          case LookupResult::FoundUnresolvedValue:
+            break;
+          }
+        }
+      }
+    }
+
+    QualifiedResults.clear();
+  }
+
+  // No corrections remain...
+  if (Consumer.empty()) return TypoCorrection();
+
+  TypoResultsMap &BestResults = Consumer.begin()->second;
+  ED = TypoCorrection::NormalizeEditDistance(Consumer.begin()->first);
+
+  if (ED > 0 && Typo->getName().size() / ED < 3) {
+    // If this was an unqualified lookup and we believe the callback
+    // object wouldn't have filtered out possible corrections, note
+    // that no correction was found.
+    if (IsUnqualifiedLookup && !ValidatingCallback)
+      (void)UnqualifiedTyposCorrected[Typo];
+
+    return TypoCorrection();
+  }
+
+  // If only a single name remains, return that result.
+  if (BestResults.size() == 1) {
+    const llvm::StringMapEntry<TypoCorrection> &Correction = *(BestResults.begin());
+    const TypoCorrection &Result = Correction.second;
+
+    // Don't correct to a keyword that's the same as the typo; the keyword
+    // wasn't actually in scope.
+    if (ED == 0 && Result.isKeyword()) return TypoCorrection();
+
+    // Record the correction for unqualified lookup.
+    if (IsUnqualifiedLookup)
+      UnqualifiedTyposCorrected[Typo] = Result;
+
+    return Result;
+  }
+  else if (BestResults.size() > 1
+           // Ugly hack equivalent to CTC == CTC_ObjCMessageReceiver;
+           // WantObjCSuper is only true for CTC_ObjCMessageReceiver and for
+           // some instances of CTC_Unknown, while WantRemainingKeywords is true
+           // for CTC_Unknown but not for CTC_ObjCMessageReceiver.
+           && CCC.WantObjCSuper && !CCC.WantRemainingKeywords
+           && BestResults["super"].isKeyword()) {
+    // Prefer 'super' when we're completing in a message-receiver
+    // context.
+
+    // Don't correct to a keyword that's the same as the typo; the keyword
+    // wasn't actually in scope.
+    if (ED == 0) return TypoCorrection();
+
+    // Record the correction for unqualified lookup.
+    if (IsUnqualifiedLookup)
+      UnqualifiedTyposCorrected[Typo] = BestResults["super"];
+
+    return BestResults["super"];
+  }
+
+  // If this was an unqualified lookup and we believe the callback object did
+  // not filter out possible corrections, note that no correction was found.
+  if (IsUnqualifiedLookup && !ValidatingCallback)
+    (void)UnqualifiedTyposCorrected[Typo];
+
+  return TypoCorrection();
+}
+
+void TypoCorrection::addCorrectionDecl(NamedDecl *CDecl) {
+  if (!CDecl) return;
+
+  if (isKeyword())
+    CorrectionDecls.clear();
+
+  CorrectionDecls.push_back(CDecl);
+
+  if (!CorrectionName)
+    CorrectionName = CDecl->getDeclName();
+}
+
+std::string TypoCorrection::getAsString(const LangOptions &LO) const {
+  if (CorrectionNameSpec) {
+    std::string tmpBuffer;
+    llvm::raw_string_ostream PrefixOStream(tmpBuffer);
+    CorrectionNameSpec->print(PrefixOStream, PrintingPolicy(LO));
+    CorrectionName.printName(PrefixOStream);
+    return PrefixOStream.str();
+  }
+
+  return CorrectionName.getAsString();
+}
diff --git a/clang/lib/Sema/SemaObjCProperty.cpp b/clang/lib/Sema/SemaObjCProperty.cpp
new file mode 100644
index 0000000..5ece8f1
--- /dev/null
+++ b/clang/lib/Sema/SemaObjCProperty.cpp
@@ -0,0 +1,1953 @@
+//===--- SemaObjCProperty.cpp - Semantic Analysis for ObjC @property ------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+//  This file implements semantic analysis for Objective C @property and
+//  @synthesize declarations.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Sema/SemaInternal.h"
+#include "clang/Sema/Initialization.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/AST/ExprObjC.h"
+#include "clang/AST/ExprCXX.h"
+#include "clang/AST/ASTMutationListener.h"
+#include "llvm/ADT/DenseSet.h"
+#include "llvm/ADT/SmallString.h"
+
+using namespace clang;
+
+//===----------------------------------------------------------------------===//
+// Grammar actions.
+//===----------------------------------------------------------------------===//
+
+/// getImpliedARCOwnership - Given a set of property attributes and a
+/// type, infer an expected lifetime.  The type's ownership qualification
+/// is not considered.
+///
+/// Returns OCL_None if the attributes as stated do not imply an ownership.
+/// Never returns OCL_Autoreleasing.
+static Qualifiers::ObjCLifetime getImpliedARCOwnership(
+                               ObjCPropertyDecl::PropertyAttributeKind attrs,
+                                                QualType type) {
+  // retain, strong, copy, weak, and unsafe_unretained are only legal
+  // on properties of retainable pointer type.
+  if (attrs & (ObjCPropertyDecl::OBJC_PR_retain |
+               ObjCPropertyDecl::OBJC_PR_strong |
+               ObjCPropertyDecl::OBJC_PR_copy)) {
+    return type->getObjCARCImplicitLifetime();
+  } else if (attrs & ObjCPropertyDecl::OBJC_PR_weak) {
+    return Qualifiers::OCL_Weak;
+  } else if (attrs & ObjCPropertyDecl::OBJC_PR_unsafe_unretained) {
+    return Qualifiers::OCL_ExplicitNone;
+  }
+
+  // assign can appear on other types, so we have to check the
+  // property type.
+  if (attrs & ObjCPropertyDecl::OBJC_PR_assign &&
+      type->isObjCRetainableType()) {
+    return Qualifiers::OCL_ExplicitNone;
+  }
+
+  return Qualifiers::OCL_None;
+}
+
+/// Check the internal consistency of a property declaration.
+static void checkARCPropertyDecl(Sema &S, ObjCPropertyDecl *property) {
+  if (property->isInvalidDecl()) return;
+
+  ObjCPropertyDecl::PropertyAttributeKind propertyKind
+    = property->getPropertyAttributes();
+  Qualifiers::ObjCLifetime propertyLifetime
+    = property->getType().getObjCLifetime();
+
+  // Nothing to do if we don't have a lifetime.
+  if (propertyLifetime == Qualifiers::OCL_None) return;
+
+  Qualifiers::ObjCLifetime expectedLifetime
+    = getImpliedARCOwnership(propertyKind, property->getType());
+  if (!expectedLifetime) {
+    // We have a lifetime qualifier but no dominating property
+    // attribute.  That's okay, but restore reasonable invariants by
+    // setting the property attribute according to the lifetime
+    // qualifier.
+    ObjCPropertyDecl::PropertyAttributeKind attr;
+    if (propertyLifetime == Qualifiers::OCL_Strong) {
+      attr = ObjCPropertyDecl::OBJC_PR_strong;
+    } else if (propertyLifetime == Qualifiers::OCL_Weak) {
+      attr = ObjCPropertyDecl::OBJC_PR_weak;
+    } else {
+      assert(propertyLifetime == Qualifiers::OCL_ExplicitNone);
+      attr = ObjCPropertyDecl::OBJC_PR_unsafe_unretained;
+    }
+    property->setPropertyAttributes(attr);
+    return;
+  }
+
+  if (propertyLifetime == expectedLifetime) return;
+
+  property->setInvalidDecl();
+  S.Diag(property->getLocation(),
+         diag::err_arc_inconsistent_property_ownership)
+    << property->getDeclName()
+    << expectedLifetime
+    << propertyLifetime;
+}
+
+Decl *Sema::ActOnProperty(Scope *S, SourceLocation AtLoc,
+                          SourceLocation LParenLoc,
+                          FieldDeclarator &FD,
+                          ObjCDeclSpec &ODS,
+                          Selector GetterSel,
+                          Selector SetterSel,
+                          bool *isOverridingProperty,
+                          tok::ObjCKeywordKind MethodImplKind,
+                          DeclContext *lexicalDC) {
+  unsigned Attributes = ODS.getPropertyAttributes();
+  TypeSourceInfo *TSI = GetTypeForDeclarator(FD.D, S);
+  QualType T = TSI->getType();
+  if ((getLangOpts().getGC() != LangOptions::NonGC && 
+       T.isObjCGCWeak()) ||
+      (getLangOpts().ObjCAutoRefCount &&
+       T.getObjCLifetime() == Qualifiers::OCL_Weak))
+    Attributes |= ObjCDeclSpec::DQ_PR_weak;
+
+  bool isReadWrite = ((Attributes & ObjCDeclSpec::DQ_PR_readwrite) ||
+                      // default is readwrite!
+                      !(Attributes & ObjCDeclSpec::DQ_PR_readonly));
+  // property is defaulted to 'assign' if it is readwrite and is
+  // not retain or copy
+  bool isAssign = ((Attributes & ObjCDeclSpec::DQ_PR_assign) ||
+                   (isReadWrite &&
+                    !(Attributes & ObjCDeclSpec::DQ_PR_retain) &&
+                    !(Attributes & ObjCDeclSpec::DQ_PR_strong) &&
+                    !(Attributes & ObjCDeclSpec::DQ_PR_copy) &&
+                    !(Attributes & ObjCDeclSpec::DQ_PR_unsafe_unretained) &&
+                    !(Attributes & ObjCDeclSpec::DQ_PR_weak)));
+
+  // Proceed with constructing the ObjCPropertDecls.
+  ObjCContainerDecl *ClassDecl = cast<ObjCContainerDecl>(CurContext);
+
+  if (ObjCCategoryDecl *CDecl = dyn_cast<ObjCCategoryDecl>(ClassDecl))
+    if (CDecl->IsClassExtension()) {
+      Decl *Res = HandlePropertyInClassExtension(S, AtLoc, LParenLoc,
+                                           FD, GetterSel, SetterSel,
+                                           isAssign, isReadWrite,
+                                           Attributes,
+                                           ODS.getPropertyAttributes(),
+                                           isOverridingProperty, TSI,
+                                           MethodImplKind);
+      if (Res) {
+        CheckObjCPropertyAttributes(Res, AtLoc, Attributes);
+        if (getLangOpts().ObjCAutoRefCount)
+          checkARCPropertyDecl(*this, cast<ObjCPropertyDecl>(Res));
+      }
+      return Res;
+    }
+  
+  ObjCPropertyDecl *Res = CreatePropertyDecl(S, ClassDecl, AtLoc, LParenLoc, FD,
+                                             GetterSel, SetterSel,
+                                             isAssign, isReadWrite,
+                                             Attributes,
+                                             ODS.getPropertyAttributes(),
+                                             TSI, MethodImplKind);
+  if (lexicalDC)
+    Res->setLexicalDeclContext(lexicalDC);
+
+  // Validate the attributes on the @property.
+  CheckObjCPropertyAttributes(Res, AtLoc, Attributes);
+
+  if (getLangOpts().ObjCAutoRefCount)
+    checkARCPropertyDecl(*this, Res);
+
+  return Res;
+}
+
+static ObjCPropertyDecl::PropertyAttributeKind
+makePropertyAttributesAsWritten(unsigned Attributes) {
+  unsigned attributesAsWritten = 0;
+  if (Attributes & ObjCDeclSpec::DQ_PR_readonly)
+    attributesAsWritten |= ObjCPropertyDecl::OBJC_PR_readonly;
+  if (Attributes & ObjCDeclSpec::DQ_PR_readwrite)
+    attributesAsWritten |= ObjCPropertyDecl::OBJC_PR_readwrite;
+  if (Attributes & ObjCDeclSpec::DQ_PR_getter)
+    attributesAsWritten |= ObjCPropertyDecl::OBJC_PR_getter;
+  if (Attributes & ObjCDeclSpec::DQ_PR_setter)
+    attributesAsWritten |= ObjCPropertyDecl::OBJC_PR_setter;
+  if (Attributes & ObjCDeclSpec::DQ_PR_assign)
+    attributesAsWritten |= ObjCPropertyDecl::OBJC_PR_assign;
+  if (Attributes & ObjCDeclSpec::DQ_PR_retain)
+    attributesAsWritten |= ObjCPropertyDecl::OBJC_PR_retain;
+  if (Attributes & ObjCDeclSpec::DQ_PR_strong)
+    attributesAsWritten |= ObjCPropertyDecl::OBJC_PR_strong;
+  if (Attributes & ObjCDeclSpec::DQ_PR_weak)
+    attributesAsWritten |= ObjCPropertyDecl::OBJC_PR_weak;
+  if (Attributes & ObjCDeclSpec::DQ_PR_copy)
+    attributesAsWritten |= ObjCPropertyDecl::OBJC_PR_copy;
+  if (Attributes & ObjCDeclSpec::DQ_PR_unsafe_unretained)
+    attributesAsWritten |= ObjCPropertyDecl::OBJC_PR_unsafe_unretained;
+  if (Attributes & ObjCDeclSpec::DQ_PR_nonatomic)
+    attributesAsWritten |= ObjCPropertyDecl::OBJC_PR_nonatomic;
+  if (Attributes & ObjCDeclSpec::DQ_PR_atomic)
+    attributesAsWritten |= ObjCPropertyDecl::OBJC_PR_atomic;
+  
+  return (ObjCPropertyDecl::PropertyAttributeKind)attributesAsWritten;
+}
+
+Decl *
+Sema::HandlePropertyInClassExtension(Scope *S,
+                                     SourceLocation AtLoc,
+                                     SourceLocation LParenLoc,
+                                     FieldDeclarator &FD,
+                                     Selector GetterSel, Selector SetterSel,
+                                     const bool isAssign,
+                                     const bool isReadWrite,
+                                     const unsigned Attributes,
+                                     const unsigned AttributesAsWritten,
+                                     bool *isOverridingProperty,
+                                     TypeSourceInfo *T,
+                                     tok::ObjCKeywordKind MethodImplKind) {
+  ObjCCategoryDecl *CDecl = cast<ObjCCategoryDecl>(CurContext);
+  // Diagnose if this property is already in continuation class.
+  DeclContext *DC = CurContext;
+  IdentifierInfo *PropertyId = FD.D.getIdentifier();
+  ObjCInterfaceDecl *CCPrimary = CDecl->getClassInterface();
+  
+  if (CCPrimary)
+    // Check for duplicate declaration of this property in current and
+    // other class extensions.
+    for (const ObjCCategoryDecl *ClsExtDecl = 
+         CCPrimary->getFirstClassExtension();
+         ClsExtDecl; ClsExtDecl = ClsExtDecl->getNextClassExtension()) {
+      if (ObjCPropertyDecl *prevDecl =
+          ObjCPropertyDecl::findPropertyDecl(ClsExtDecl, PropertyId)) {
+        Diag(AtLoc, diag::err_duplicate_property);
+        Diag(prevDecl->getLocation(), diag::note_property_declare);
+        return 0;
+      }
+    }
+  
+  // Create a new ObjCPropertyDecl with the DeclContext being
+  // the class extension.
+  // FIXME. We should really be using CreatePropertyDecl for this.
+  ObjCPropertyDecl *PDecl =
+    ObjCPropertyDecl::Create(Context, DC, FD.D.getIdentifierLoc(),
+                             PropertyId, AtLoc, LParenLoc, T);
+  PDecl->setPropertyAttributesAsWritten(
+                          makePropertyAttributesAsWritten(AttributesAsWritten));
+  if (Attributes & ObjCDeclSpec::DQ_PR_readonly)
+    PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_readonly);
+  if (Attributes & ObjCDeclSpec::DQ_PR_readwrite)
+    PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_readwrite);
+  // Set setter/getter selector name. Needed later.
+  PDecl->setGetterName(GetterSel);
+  PDecl->setSetterName(SetterSel);
+  ProcessDeclAttributes(S, PDecl, FD.D);
+  DC->addDecl(PDecl);
+
+  // We need to look in the @interface to see if the @property was
+  // already declared.
+  if (!CCPrimary) {
+    Diag(CDecl->getLocation(), diag::err_continuation_class);
+    *isOverridingProperty = true;
+    return 0;
+  }
+
+  // Find the property in continuation class's primary class only.
+  ObjCPropertyDecl *PIDecl =
+    CCPrimary->FindPropertyVisibleInPrimaryClass(PropertyId);
+
+  if (!PIDecl) {
+    // No matching property found in the primary class. Just fall thru
+    // and add property to continuation class's primary class.
+    ObjCPropertyDecl *PrimaryPDecl =
+      CreatePropertyDecl(S, CCPrimary, AtLoc, LParenLoc,
+                         FD, GetterSel, SetterSel, isAssign, isReadWrite,
+                         Attributes,AttributesAsWritten, T, MethodImplKind, DC);
+
+    // A case of continuation class adding a new property in the class. This
+    // is not what it was meant for. However, gcc supports it and so should we.
+    // Make sure setter/getters are declared here.
+    ProcessPropertyDecl(PrimaryPDecl, CCPrimary, /* redeclaredProperty = */ 0,
+                        /* lexicalDC = */ CDecl);
+    PDecl->setGetterMethodDecl(PrimaryPDecl->getGetterMethodDecl());
+    PDecl->setSetterMethodDecl(PrimaryPDecl->getSetterMethodDecl());
+    if (ASTMutationListener *L = Context.getASTMutationListener())
+      L->AddedObjCPropertyInClassExtension(PrimaryPDecl, /*OrigProp=*/0, CDecl);
+    return PrimaryPDecl;
+  }
+  if (!Context.hasSameType(PIDecl->getType(), PDecl->getType())) {
+    bool IncompatibleObjC = false;
+    QualType ConvertedType;
+    // Relax the strict type matching for property type in continuation class.
+    // Allow property object type of continuation class to be different as long
+    // as it narrows the object type in its primary class property. Note that
+    // this conversion is safe only because the wider type is for a 'readonly'
+    // property in primary class and 'narrowed' type for a 'readwrite' property
+    // in continuation class.
+    if (!isa<ObjCObjectPointerType>(PIDecl->getType()) ||
+        !isa<ObjCObjectPointerType>(PDecl->getType()) ||
+        (!isObjCPointerConversion(PDecl->getType(), PIDecl->getType(), 
+                                  ConvertedType, IncompatibleObjC))
+        || IncompatibleObjC) {
+      Diag(AtLoc, 
+          diag::err_type_mismatch_continuation_class) << PDecl->getType();
+      Diag(PIDecl->getLocation(), diag::note_property_declare);
+    }
+  }
+    
+  // The property 'PIDecl's readonly attribute will be over-ridden
+  // with continuation class's readwrite property attribute!
+  unsigned PIkind = PIDecl->getPropertyAttributesAsWritten();
+  if (isReadWrite && (PIkind & ObjCPropertyDecl::OBJC_PR_readonly)) {
+    unsigned retainCopyNonatomic =
+    (ObjCPropertyDecl::OBJC_PR_retain |
+     ObjCPropertyDecl::OBJC_PR_strong |
+     ObjCPropertyDecl::OBJC_PR_copy |
+     ObjCPropertyDecl::OBJC_PR_nonatomic);
+    if ((Attributes & retainCopyNonatomic) !=
+        (PIkind & retainCopyNonatomic)) {
+      Diag(AtLoc, diag::warn_property_attr_mismatch);
+      Diag(PIDecl->getLocation(), diag::note_property_declare);
+    }
+    DeclContext *DC = cast<DeclContext>(CCPrimary);
+    if (!ObjCPropertyDecl::findPropertyDecl(DC,
+                                 PIDecl->getDeclName().getAsIdentifierInfo())) {
+      // Protocol is not in the primary class. Must build one for it.
+      ObjCDeclSpec ProtocolPropertyODS;
+      // FIXME. Assuming that ObjCDeclSpec::ObjCPropertyAttributeKind
+      // and ObjCPropertyDecl::PropertyAttributeKind have identical
+      // values.  Should consolidate both into one enum type.
+      ProtocolPropertyODS.
+      setPropertyAttributes((ObjCDeclSpec::ObjCPropertyAttributeKind)
+                            PIkind);
+      // Must re-establish the context from class extension to primary
+      // class context.
+      ContextRAII SavedContext(*this, CCPrimary);
+      
+      Decl *ProtocolPtrTy =
+        ActOnProperty(S, AtLoc, LParenLoc, FD, ProtocolPropertyODS,
+                      PIDecl->getGetterName(),
+                      PIDecl->getSetterName(),
+                      isOverridingProperty,
+                      MethodImplKind,
+                      /* lexicalDC = */ CDecl);
+      PIDecl = cast<ObjCPropertyDecl>(ProtocolPtrTy);
+    }
+    PIDecl->makeitReadWriteAttribute();
+    if (Attributes & ObjCDeclSpec::DQ_PR_retain)
+      PIDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_retain);
+    if (Attributes & ObjCDeclSpec::DQ_PR_strong)
+      PIDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_strong);
+    if (Attributes & ObjCDeclSpec::DQ_PR_copy)
+      PIDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_copy);
+    PIDecl->setSetterName(SetterSel);
+  } else {
+    // Tailor the diagnostics for the common case where a readwrite
+    // property is declared both in the @interface and the continuation.
+    // This is a common error where the user often intended the original
+    // declaration to be readonly.
+    unsigned diag =
+      (Attributes & ObjCDeclSpec::DQ_PR_readwrite) &&
+      (PIkind & ObjCPropertyDecl::OBJC_PR_readwrite)
+      ? diag::err_use_continuation_class_redeclaration_readwrite
+      : diag::err_use_continuation_class;
+    Diag(AtLoc, diag)
+      << CCPrimary->getDeclName();
+    Diag(PIDecl->getLocation(), diag::note_property_declare);
+  }
+  *isOverridingProperty = true;
+  // Make sure setter decl is synthesized, and added to primary class's list.
+  ProcessPropertyDecl(PIDecl, CCPrimary, PDecl, CDecl);
+  PDecl->setGetterMethodDecl(PIDecl->getGetterMethodDecl());
+  PDecl->setSetterMethodDecl(PIDecl->getSetterMethodDecl());
+  if (ASTMutationListener *L = Context.getASTMutationListener())
+    L->AddedObjCPropertyInClassExtension(PDecl, PIDecl, CDecl);
+  return 0;
+}
+
+ObjCPropertyDecl *Sema::CreatePropertyDecl(Scope *S,
+                                           ObjCContainerDecl *CDecl,
+                                           SourceLocation AtLoc,
+                                           SourceLocation LParenLoc,
+                                           FieldDeclarator &FD,
+                                           Selector GetterSel,
+                                           Selector SetterSel,
+                                           const bool isAssign,
+                                           const bool isReadWrite,
+                                           const unsigned Attributes,
+                                           const unsigned AttributesAsWritten,
+                                           TypeSourceInfo *TInfo,
+                                           tok::ObjCKeywordKind MethodImplKind,
+                                           DeclContext *lexicalDC){
+  IdentifierInfo *PropertyId = FD.D.getIdentifier();
+  QualType T = TInfo->getType();
+
+  // Issue a warning if property is 'assign' as default and its object, which is
+  // gc'able conforms to NSCopying protocol
+  if (getLangOpts().getGC() != LangOptions::NonGC &&
+      isAssign && !(Attributes & ObjCDeclSpec::DQ_PR_assign))
+    if (const ObjCObjectPointerType *ObjPtrTy =
+          T->getAs<ObjCObjectPointerType>()) {
+      ObjCInterfaceDecl *IDecl = ObjPtrTy->getObjectType()->getInterface();
+      if (IDecl)
+        if (ObjCProtocolDecl* PNSCopying =
+            LookupProtocol(&Context.Idents.get("NSCopying"), AtLoc))
+          if (IDecl->ClassImplementsProtocol(PNSCopying, true))
+            Diag(AtLoc, diag::warn_implements_nscopying) << PropertyId;
+    }
+  if (T->isObjCObjectType())
+    Diag(FD.D.getIdentifierLoc(), diag::err_statically_allocated_object);
+
+  DeclContext *DC = cast<DeclContext>(CDecl);
+  ObjCPropertyDecl *PDecl = ObjCPropertyDecl::Create(Context, DC,
+                                                     FD.D.getIdentifierLoc(),
+                                                     PropertyId, AtLoc, LParenLoc, TInfo);
+
+  if (ObjCPropertyDecl *prevDecl =
+        ObjCPropertyDecl::findPropertyDecl(DC, PropertyId)) {
+    Diag(PDecl->getLocation(), diag::err_duplicate_property);
+    Diag(prevDecl->getLocation(), diag::note_property_declare);
+    PDecl->setInvalidDecl();
+  }
+  else {
+    DC->addDecl(PDecl);
+    if (lexicalDC)
+      PDecl->setLexicalDeclContext(lexicalDC);
+  }
+
+  if (T->isArrayType() || T->isFunctionType()) {
+    Diag(AtLoc, diag::err_property_type) << T;
+    PDecl->setInvalidDecl();
+  }
+
+  ProcessDeclAttributes(S, PDecl, FD.D);
+
+  // Regardless of setter/getter attribute, we save the default getter/setter
+  // selector names in anticipation of declaration of setter/getter methods.
+  PDecl->setGetterName(GetterSel);
+  PDecl->setSetterName(SetterSel);
+  PDecl->setPropertyAttributesAsWritten(
+                          makePropertyAttributesAsWritten(AttributesAsWritten));
+
+  if (Attributes & ObjCDeclSpec::DQ_PR_readonly)
+    PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_readonly);
+
+  if (Attributes & ObjCDeclSpec::DQ_PR_getter)
+    PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_getter);
+
+  if (Attributes & ObjCDeclSpec::DQ_PR_setter)
+    PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_setter);
+
+  if (isReadWrite)
+    PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_readwrite);
+
+  if (Attributes & ObjCDeclSpec::DQ_PR_retain)
+    PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_retain);
+
+  if (Attributes & ObjCDeclSpec::DQ_PR_strong)
+    PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_strong);
+
+  if (Attributes & ObjCDeclSpec::DQ_PR_weak)
+    PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_weak);
+
+  if (Attributes & ObjCDeclSpec::DQ_PR_copy)
+    PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_copy);
+
+  if (Attributes & ObjCDeclSpec::DQ_PR_unsafe_unretained)
+    PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_unsafe_unretained);
+
+  if (isAssign)
+    PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_assign);
+
+  // In the semantic attributes, one of nonatomic or atomic is always set.
+  if (Attributes & ObjCDeclSpec::DQ_PR_nonatomic)
+    PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_nonatomic);
+  else
+    PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_atomic);
+
+  // 'unsafe_unretained' is alias for 'assign'.
+  if (Attributes & ObjCDeclSpec::DQ_PR_unsafe_unretained)
+    PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_assign);
+  if (isAssign)
+    PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_unsafe_unretained);
+
+  if (MethodImplKind == tok::objc_required)
+    PDecl->setPropertyImplementation(ObjCPropertyDecl::Required);
+  else if (MethodImplKind == tok::objc_optional)
+    PDecl->setPropertyImplementation(ObjCPropertyDecl::Optional);
+
+  return PDecl;
+}
+
+static void checkARCPropertyImpl(Sema &S, SourceLocation propertyImplLoc,
+                                 ObjCPropertyDecl *property,
+                                 ObjCIvarDecl *ivar) {
+  if (property->isInvalidDecl() || ivar->isInvalidDecl()) return;
+
+  QualType ivarType = ivar->getType();
+  Qualifiers::ObjCLifetime ivarLifetime = ivarType.getObjCLifetime();
+
+  // The lifetime implied by the property's attributes.
+  Qualifiers::ObjCLifetime propertyLifetime =
+    getImpliedARCOwnership(property->getPropertyAttributes(),
+                           property->getType());
+
+  // We're fine if they match.
+  if (propertyLifetime == ivarLifetime) return;
+
+  // These aren't valid lifetimes for object ivars;  don't diagnose twice.
+  if (ivarLifetime == Qualifiers::OCL_None ||
+      ivarLifetime == Qualifiers::OCL_Autoreleasing)
+    return;
+
+  switch (propertyLifetime) {
+  case Qualifiers::OCL_Strong:
+    S.Diag(propertyImplLoc, diag::err_arc_strong_property_ownership)
+      << property->getDeclName()
+      << ivar->getDeclName()
+      << ivarLifetime;
+    break;
+
+  case Qualifiers::OCL_Weak:
+    S.Diag(propertyImplLoc, diag::error_weak_property)
+      << property->getDeclName()
+      << ivar->getDeclName();
+    break;
+
+  case Qualifiers::OCL_ExplicitNone:
+    S.Diag(propertyImplLoc, diag::err_arc_assign_property_ownership)
+      << property->getDeclName()
+      << ivar->getDeclName()
+      << ((property->getPropertyAttributesAsWritten() 
+           & ObjCPropertyDecl::OBJC_PR_assign) != 0);
+    break;
+
+  case Qualifiers::OCL_Autoreleasing:
+    llvm_unreachable("properties cannot be autoreleasing");
+
+  case Qualifiers::OCL_None:
+    // Any other property should be ignored.
+    return;
+  }
+
+  S.Diag(property->getLocation(), diag::note_property_declare);
+}
+
+/// setImpliedPropertyAttributeForReadOnlyProperty -
+/// This routine evaludates life-time attributes for a 'readonly'
+/// property with no known lifetime of its own, using backing
+/// 'ivar's attribute, if any. If no backing 'ivar', property's
+/// life-time is assumed 'strong'.
+static void setImpliedPropertyAttributeForReadOnlyProperty(
+              ObjCPropertyDecl *property, ObjCIvarDecl *ivar) {
+  Qualifiers::ObjCLifetime propertyLifetime = 
+    getImpliedARCOwnership(property->getPropertyAttributes(),
+                           property->getType());
+  if (propertyLifetime != Qualifiers::OCL_None)
+    return;
+  
+  if (!ivar) {
+    // if no backing ivar, make property 'strong'.
+    property->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_strong);
+    return;
+  }
+  // property assumes owenership of backing ivar.
+  QualType ivarType = ivar->getType();
+  Qualifiers::ObjCLifetime ivarLifetime = ivarType.getObjCLifetime();
+  if (ivarLifetime == Qualifiers::OCL_Strong)
+    property->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_strong);
+  else if (ivarLifetime == Qualifiers::OCL_Weak)
+    property->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_weak);
+  return;
+}
+
+/// ActOnPropertyImplDecl - This routine performs semantic checks and
+/// builds the AST node for a property implementation declaration; declared
+/// as @synthesize or @dynamic.
+///
+Decl *Sema::ActOnPropertyImplDecl(Scope *S,
+                                  SourceLocation AtLoc,
+                                  SourceLocation PropertyLoc,
+                                  bool Synthesize,
+                                  IdentifierInfo *PropertyId,
+                                  IdentifierInfo *PropertyIvar,
+                                  SourceLocation PropertyIvarLoc) {
+  ObjCContainerDecl *ClassImpDecl =
+    dyn_cast<ObjCContainerDecl>(CurContext);
+  // Make sure we have a context for the property implementation declaration.
+  if (!ClassImpDecl) {
+    Diag(AtLoc, diag::error_missing_property_context);
+    return 0;
+  }
+  if (PropertyIvarLoc.isInvalid())
+    PropertyIvarLoc = PropertyLoc;
+  ObjCPropertyDecl *property = 0;
+  ObjCInterfaceDecl* IDecl = 0;
+  // Find the class or category class where this property must have
+  // a declaration.
+  ObjCImplementationDecl *IC = 0;
+  ObjCCategoryImplDecl* CatImplClass = 0;
+  if ((IC = dyn_cast<ObjCImplementationDecl>(ClassImpDecl))) {
+    IDecl = IC->getClassInterface();
+    // We always synthesize an interface for an implementation
+    // without an interface decl. So, IDecl is always non-zero.
+    assert(IDecl &&
+           "ActOnPropertyImplDecl - @implementation without @interface");
+
+    // Look for this property declaration in the @implementation's @interface
+    property = IDecl->FindPropertyDeclaration(PropertyId);
+    if (!property) {
+      Diag(PropertyLoc, diag::error_bad_property_decl) << IDecl->getDeclName();
+      return 0;
+    }
+    unsigned PIkind = property->getPropertyAttributesAsWritten();
+    if ((PIkind & (ObjCPropertyDecl::OBJC_PR_atomic |
+                   ObjCPropertyDecl::OBJC_PR_nonatomic) ) == 0) {
+      if (AtLoc.isValid())
+        Diag(AtLoc, diag::warn_implicit_atomic_property);
+      else
+        Diag(IC->getLocation(), diag::warn_auto_implicit_atomic_property);
+      Diag(property->getLocation(), diag::note_property_declare);
+    }
+    
+    if (const ObjCCategoryDecl *CD =
+        dyn_cast<ObjCCategoryDecl>(property->getDeclContext())) {
+      if (!CD->IsClassExtension()) {
+        Diag(PropertyLoc, diag::error_category_property) << CD->getDeclName();
+        Diag(property->getLocation(), diag::note_property_declare);
+        return 0;
+      }
+    }
+  } else if ((CatImplClass = dyn_cast<ObjCCategoryImplDecl>(ClassImpDecl))) {
+    if (Synthesize) {
+      Diag(AtLoc, diag::error_synthesize_category_decl);
+      return 0;
+    }
+    IDecl = CatImplClass->getClassInterface();
+    if (!IDecl) {
+      Diag(AtLoc, diag::error_missing_property_interface);
+      return 0;
+    }
+    ObjCCategoryDecl *Category =
+    IDecl->FindCategoryDeclaration(CatImplClass->getIdentifier());
+
+    // If category for this implementation not found, it is an error which
+    // has already been reported eralier.
+    if (!Category)
+      return 0;
+    // Look for this property declaration in @implementation's category
+    property = Category->FindPropertyDeclaration(PropertyId);
+    if (!property) {
+      Diag(PropertyLoc, diag::error_bad_category_property_decl)
+      << Category->getDeclName();
+      return 0;
+    }
+  } else {
+    Diag(AtLoc, diag::error_bad_property_context);
+    return 0;
+  }
+  ObjCIvarDecl *Ivar = 0;
+  // Check that we have a valid, previously declared ivar for @synthesize
+  if (Synthesize) {
+    // @synthesize
+    if (!PropertyIvar)
+      PropertyIvar = PropertyId;
+    // Check that this is a previously declared 'ivar' in 'IDecl' interface
+    ObjCInterfaceDecl *ClassDeclared;
+    Ivar = IDecl->lookupInstanceVariable(PropertyIvar, ClassDeclared);
+    QualType PropType = property->getType();
+    QualType PropertyIvarType = PropType.getNonReferenceType();
+    
+    if (getLangOpts().ObjCAutoRefCount &&
+        (property->getPropertyAttributesAsWritten() &
+         ObjCPropertyDecl::OBJC_PR_readonly) &&
+        PropertyIvarType->isObjCRetainableType()) {
+      setImpliedPropertyAttributeForReadOnlyProperty(property, Ivar);    
+    }
+    
+    ObjCPropertyDecl::PropertyAttributeKind kind 
+      = property->getPropertyAttributes();
+
+    // Add GC __weak to the ivar type if the property is weak.
+    if ((kind & ObjCPropertyDecl::OBJC_PR_weak) && 
+        getLangOpts().getGC() != LangOptions::NonGC) {
+      assert(!getLangOpts().ObjCAutoRefCount);
+      if (PropertyIvarType.isObjCGCStrong()) {
+        Diag(PropertyLoc, diag::err_gc_weak_property_strong_type);
+        Diag(property->getLocation(), diag::note_property_declare);
+      } else {
+        PropertyIvarType =
+          Context.getObjCGCQualType(PropertyIvarType, Qualifiers::Weak);
+      }
+    }
+
+    if (!Ivar) {
+      // In ARC, give the ivar a lifetime qualifier based on the
+      // property attributes.
+      if (getLangOpts().ObjCAutoRefCount &&
+          !PropertyIvarType.getObjCLifetime() &&
+          PropertyIvarType->isObjCRetainableType()) {
+
+        // It's an error if we have to do this and the user didn't
+        // explicitly write an ownership attribute on the property.
+        if (!property->hasWrittenStorageAttribute() &&
+            !(kind & ObjCPropertyDecl::OBJC_PR_strong)) {
+          Diag(PropertyLoc,
+               diag::err_arc_objc_property_default_assign_on_object);
+          Diag(property->getLocation(), diag::note_property_declare);
+        } else {
+          Qualifiers::ObjCLifetime lifetime =
+            getImpliedARCOwnership(kind, PropertyIvarType);
+          assert(lifetime && "no lifetime for property?");
+          if (lifetime == Qualifiers::OCL_Weak) {
+            bool err = false;
+            if (const ObjCObjectPointerType *ObjT =
+                PropertyIvarType->getAs<ObjCObjectPointerType>())
+              if (ObjT->getInterfaceDecl()->isArcWeakrefUnavailable()) {
+                Diag(PropertyLoc, diag::err_arc_weak_unavailable_property);
+                Diag(property->getLocation(), diag::note_property_declare);
+                err = true;
+              }
+            if (!err && !getLangOpts().ObjCRuntimeHasWeak) {
+              Diag(PropertyLoc, diag::err_arc_weak_no_runtime);
+              Diag(property->getLocation(), diag::note_property_declare);
+            }
+          }
+          
+          Qualifiers qs;
+          qs.addObjCLifetime(lifetime);
+          PropertyIvarType = Context.getQualifiedType(PropertyIvarType, qs);   
+        }
+      }
+
+      if (kind & ObjCPropertyDecl::OBJC_PR_weak &&
+          !getLangOpts().ObjCAutoRefCount &&
+          getLangOpts().getGC() == LangOptions::NonGC) {
+        Diag(PropertyLoc, diag::error_synthesize_weak_non_arc_or_gc);
+        Diag(property->getLocation(), diag::note_property_declare);
+      }
+
+      Ivar = ObjCIvarDecl::Create(Context, ClassImpDecl,
+                                  PropertyIvarLoc,PropertyIvarLoc, PropertyIvar,
+                                  PropertyIvarType, /*Dinfo=*/0,
+                                  ObjCIvarDecl::Private,
+                                  (Expr *)0, true);
+      ClassImpDecl->addDecl(Ivar);
+      IDecl->makeDeclVisibleInContext(Ivar);
+      property->setPropertyIvarDecl(Ivar);
+
+      if (!getLangOpts().ObjCNonFragileABI)
+        Diag(PropertyLoc, diag::error_missing_property_ivar_decl) << PropertyId;
+      // Note! I deliberately want it to fall thru so, we have a
+      // a property implementation and to avoid future warnings.
+    } else if (getLangOpts().ObjCNonFragileABI &&
+               !declaresSameEntity(ClassDeclared, IDecl)) {
+      Diag(PropertyLoc, diag::error_ivar_in_superclass_use)
+      << property->getDeclName() << Ivar->getDeclName()
+      << ClassDeclared->getDeclName();
+      Diag(Ivar->getLocation(), diag::note_previous_access_declaration)
+      << Ivar << Ivar->getName();
+      // Note! I deliberately want it to fall thru so more errors are caught.
+    }
+    QualType IvarType = Context.getCanonicalType(Ivar->getType());
+
+    // Check that type of property and its ivar are type compatible.
+    if (Context.getCanonicalType(PropertyIvarType) != IvarType) {
+      bool compat = false;
+      if (isa<ObjCObjectPointerType>(PropertyIvarType) 
+          && isa<ObjCObjectPointerType>(IvarType))
+        compat = 
+          Context.canAssignObjCInterfaces(
+                                  PropertyIvarType->getAs<ObjCObjectPointerType>(),
+                                  IvarType->getAs<ObjCObjectPointerType>());
+      else {
+        compat = (CheckAssignmentConstraints(PropertyIvarLoc, PropertyIvarType,
+                                             IvarType)
+                    == Compatible);
+      }
+      if (!compat) {
+        Diag(PropertyLoc, diag::error_property_ivar_type)
+          << property->getDeclName() << PropType
+          << Ivar->getDeclName() << IvarType;
+        Diag(Ivar->getLocation(), diag::note_ivar_decl);
+        // Note! I deliberately want it to fall thru so, we have a
+        // a property implementation and to avoid future warnings.
+      }
+
+      // FIXME! Rules for properties are somewhat different that those
+      // for assignments. Use a new routine to consolidate all cases;
+      // specifically for property redeclarations as well as for ivars.
+      QualType lhsType =Context.getCanonicalType(PropertyIvarType).getUnqualifiedType();
+      QualType rhsType =Context.getCanonicalType(IvarType).getUnqualifiedType();
+      if (lhsType != rhsType &&
+          lhsType->isArithmeticType()) {
+        Diag(PropertyLoc, diag::error_property_ivar_type)
+          << property->getDeclName() << PropType
+          << Ivar->getDeclName() << IvarType;
+        Diag(Ivar->getLocation(), diag::note_ivar_decl);
+        // Fall thru - see previous comment
+      }
+      // __weak is explicit. So it works on Canonical type.
+      if ((PropType.isObjCGCWeak() && !IvarType.isObjCGCWeak() &&
+           getLangOpts().getGC() != LangOptions::NonGC)) {
+        Diag(PropertyLoc, diag::error_weak_property)
+        << property->getDeclName() << Ivar->getDeclName();
+        Diag(Ivar->getLocation(), diag::note_ivar_decl);
+        // Fall thru - see previous comment
+      }
+      // Fall thru - see previous comment
+      if ((property->getType()->isObjCObjectPointerType() ||
+           PropType.isObjCGCStrong()) && IvarType.isObjCGCWeak() &&
+          getLangOpts().getGC() != LangOptions::NonGC) {
+        Diag(PropertyLoc, diag::error_strong_property)
+        << property->getDeclName() << Ivar->getDeclName();
+        // Fall thru - see previous comment
+      }
+    }
+    if (getLangOpts().ObjCAutoRefCount)
+      checkARCPropertyImpl(*this, PropertyLoc, property, Ivar);
+  } else if (PropertyIvar)
+    // @dynamic
+    Diag(PropertyLoc, diag::error_dynamic_property_ivar_decl);
+    
+  assert (property && "ActOnPropertyImplDecl - property declaration missing");
+  ObjCPropertyImplDecl *PIDecl =
+  ObjCPropertyImplDecl::Create(Context, CurContext, AtLoc, PropertyLoc,
+                               property,
+                               (Synthesize ?
+                                ObjCPropertyImplDecl::Synthesize
+                                : ObjCPropertyImplDecl::Dynamic),
+                               Ivar, PropertyIvarLoc);
+  if (ObjCMethodDecl *getterMethod = property->getGetterMethodDecl()) {
+    getterMethod->createImplicitParams(Context, IDecl);
+    if (getLangOpts().CPlusPlus && Synthesize &&
+        Ivar->getType()->isRecordType()) {
+      // For Objective-C++, need to synthesize the AST for the IVAR object to be
+      // returned by the getter as it must conform to C++'s copy-return rules.
+      // FIXME. Eventually we want to do this for Objective-C as well.
+      ImplicitParamDecl *SelfDecl = getterMethod->getSelfDecl();
+      DeclRefExpr *SelfExpr = 
+        new (Context) DeclRefExpr(SelfDecl, false, SelfDecl->getType(),
+                                  VK_RValue, SourceLocation());
+      Expr *IvarRefExpr =
+        new (Context) ObjCIvarRefExpr(Ivar, Ivar->getType(), AtLoc,
+                                      SelfExpr, true, true);
+      ExprResult Res = 
+        PerformCopyInitialization(InitializedEntity::InitializeResult(
+                                    SourceLocation(),
+                                    getterMethod->getResultType(),
+                                    /*NRVO=*/false),
+                                  SourceLocation(),
+                                  Owned(IvarRefExpr));
+      if (!Res.isInvalid()) {
+        Expr *ResExpr = Res.takeAs<Expr>();
+        if (ResExpr)
+          ResExpr = MaybeCreateExprWithCleanups(ResExpr);
+        PIDecl->setGetterCXXConstructor(ResExpr);
+      }
+    }
+    if (property->hasAttr<NSReturnsNotRetainedAttr>() &&
+        !getterMethod->hasAttr<NSReturnsNotRetainedAttr>()) {
+      Diag(getterMethod->getLocation(), 
+           diag::warn_property_getter_owning_mismatch);
+      Diag(property->getLocation(), diag::note_property_declare);
+    }
+  }
+  if (ObjCMethodDecl *setterMethod = property->getSetterMethodDecl()) {
+    setterMethod->createImplicitParams(Context, IDecl);
+    if (getLangOpts().CPlusPlus && Synthesize
+        && Ivar->getType()->isRecordType()) {
+      // FIXME. Eventually we want to do this for Objective-C as well.
+      ImplicitParamDecl *SelfDecl = setterMethod->getSelfDecl();
+      DeclRefExpr *SelfExpr = 
+        new (Context) DeclRefExpr(SelfDecl, false, SelfDecl->getType(),
+                                  VK_RValue, SourceLocation());
+      Expr *lhs =
+        new (Context) ObjCIvarRefExpr(Ivar, Ivar->getType(), AtLoc,
+                                      SelfExpr, true, true);
+      ObjCMethodDecl::param_iterator P = setterMethod->param_begin();
+      ParmVarDecl *Param = (*P);
+      QualType T = Param->getType().getNonReferenceType();
+      Expr *rhs = new (Context) DeclRefExpr(Param, false, T,
+                                            VK_LValue, SourceLocation());
+      ExprResult Res = BuildBinOp(S, lhs->getLocEnd(), 
+                                  BO_Assign, lhs, rhs);
+      if (property->getPropertyAttributes() & 
+          ObjCPropertyDecl::OBJC_PR_atomic) {
+        Expr *callExpr = Res.takeAs<Expr>();
+        if (const CXXOperatorCallExpr *CXXCE = 
+              dyn_cast_or_null<CXXOperatorCallExpr>(callExpr))
+          if (const FunctionDecl *FuncDecl = CXXCE->getDirectCallee())
+            if (!FuncDecl->isTrivial())
+              if (property->getType()->isReferenceType()) {
+                Diag(PropertyLoc, 
+                     diag::err_atomic_property_nontrivial_assign_op)
+                    << property->getType();
+                Diag(FuncDecl->getLocStart(), 
+                     diag::note_callee_decl) << FuncDecl;
+              }
+      }
+      PIDecl->setSetterCXXAssignment(Res.takeAs<Expr>());
+    }
+  }
+  
+  if (IC) {
+    if (Synthesize)
+      if (ObjCPropertyImplDecl *PPIDecl =
+          IC->FindPropertyImplIvarDecl(PropertyIvar)) {
+        Diag(PropertyLoc, diag::error_duplicate_ivar_use)
+        << PropertyId << PPIDecl->getPropertyDecl()->getIdentifier()
+        << PropertyIvar;
+        Diag(PPIDecl->getLocation(), diag::note_previous_use);
+      }
+
+    if (ObjCPropertyImplDecl *PPIDecl
+        = IC->FindPropertyImplDecl(PropertyId)) {
+      Diag(PropertyLoc, diag::error_property_implemented) << PropertyId;
+      Diag(PPIDecl->getLocation(), diag::note_previous_declaration);
+      return 0;
+    }
+    IC->addPropertyImplementation(PIDecl);
+    if (getLangOpts().ObjCDefaultSynthProperties &&
+        getLangOpts().ObjCNonFragileABI2 &&
+        !IDecl->isObjCRequiresPropertyDefs()) {
+      // Diagnose if an ivar was lazily synthesdized due to a previous
+      // use and if 1) property is @dynamic or 2) property is synthesized
+      // but it requires an ivar of different name.
+      ObjCInterfaceDecl *ClassDeclared=0;
+      ObjCIvarDecl *Ivar = 0;
+      if (!Synthesize)
+        Ivar = IDecl->lookupInstanceVariable(PropertyId, ClassDeclared);
+      else {
+        if (PropertyIvar && PropertyIvar != PropertyId)
+          Ivar = IDecl->lookupInstanceVariable(PropertyId, ClassDeclared);
+      }
+      // Issue diagnostics only if Ivar belongs to current class.
+      if (Ivar && Ivar->getSynthesize() && 
+          declaresSameEntity(IC->getClassInterface(), ClassDeclared)) {
+        Diag(Ivar->getLocation(), diag::err_undeclared_var_use) 
+        << PropertyId;
+        Ivar->setInvalidDecl();
+      }
+    }
+  } else {
+    if (Synthesize)
+      if (ObjCPropertyImplDecl *PPIDecl =
+          CatImplClass->FindPropertyImplIvarDecl(PropertyIvar)) {
+        Diag(PropertyLoc, diag::error_duplicate_ivar_use)
+        << PropertyId << PPIDecl->getPropertyDecl()->getIdentifier()
+        << PropertyIvar;
+        Diag(PPIDecl->getLocation(), diag::note_previous_use);
+      }
+
+    if (ObjCPropertyImplDecl *PPIDecl =
+        CatImplClass->FindPropertyImplDecl(PropertyId)) {
+      Diag(PropertyLoc, diag::error_property_implemented) << PropertyId;
+      Diag(PPIDecl->getLocation(), diag::note_previous_declaration);
+      return 0;
+    }
+    CatImplClass->addPropertyImplementation(PIDecl);
+  }
+
+  return PIDecl;
+}
+
+//===----------------------------------------------------------------------===//
+// Helper methods.
+//===----------------------------------------------------------------------===//
+
+/// DiagnosePropertyMismatch - Compares two properties for their
+/// attributes and types and warns on a variety of inconsistencies.
+///
+void
+Sema::DiagnosePropertyMismatch(ObjCPropertyDecl *Property,
+                               ObjCPropertyDecl *SuperProperty,
+                               const IdentifierInfo *inheritedName) {
+  ObjCPropertyDecl::PropertyAttributeKind CAttr =
+  Property->getPropertyAttributes();
+  ObjCPropertyDecl::PropertyAttributeKind SAttr =
+  SuperProperty->getPropertyAttributes();
+  if ((CAttr & ObjCPropertyDecl::OBJC_PR_readonly)
+      && (SAttr & ObjCPropertyDecl::OBJC_PR_readwrite))
+    Diag(Property->getLocation(), diag::warn_readonly_property)
+      << Property->getDeclName() << inheritedName;
+  if ((CAttr & ObjCPropertyDecl::OBJC_PR_copy)
+      != (SAttr & ObjCPropertyDecl::OBJC_PR_copy))
+    Diag(Property->getLocation(), diag::warn_property_attribute)
+      << Property->getDeclName() << "copy" << inheritedName;
+  else if (!(SAttr & ObjCPropertyDecl::OBJC_PR_readonly)){
+    unsigned CAttrRetain = 
+      (CAttr & 
+       (ObjCPropertyDecl::OBJC_PR_retain | ObjCPropertyDecl::OBJC_PR_strong));
+    unsigned SAttrRetain = 
+      (SAttr & 
+       (ObjCPropertyDecl::OBJC_PR_retain | ObjCPropertyDecl::OBJC_PR_strong));
+    bool CStrong = (CAttrRetain != 0);
+    bool SStrong = (SAttrRetain != 0);
+    if (CStrong != SStrong)
+      Diag(Property->getLocation(), diag::warn_property_attribute)
+        << Property->getDeclName() << "retain (or strong)" << inheritedName;
+  }
+
+  if ((CAttr & ObjCPropertyDecl::OBJC_PR_nonatomic)
+      != (SAttr & ObjCPropertyDecl::OBJC_PR_nonatomic))
+    Diag(Property->getLocation(), diag::warn_property_attribute)
+      << Property->getDeclName() << "atomic" << inheritedName;
+  if (Property->getSetterName() != SuperProperty->getSetterName())
+    Diag(Property->getLocation(), diag::warn_property_attribute)
+      << Property->getDeclName() << "setter" << inheritedName;
+  if (Property->getGetterName() != SuperProperty->getGetterName())
+    Diag(Property->getLocation(), diag::warn_property_attribute)
+      << Property->getDeclName() << "getter" << inheritedName;
+
+  QualType LHSType =
+    Context.getCanonicalType(SuperProperty->getType());
+  QualType RHSType =
+    Context.getCanonicalType(Property->getType());
+
+  if (!Context.propertyTypesAreCompatible(LHSType, RHSType)) {
+    // Do cases not handled in above.
+    // FIXME. For future support of covariant property types, revisit this.
+    bool IncompatibleObjC = false;
+    QualType ConvertedType;
+    if (!isObjCPointerConversion(RHSType, LHSType, 
+                                 ConvertedType, IncompatibleObjC) ||
+        IncompatibleObjC) {
+        Diag(Property->getLocation(), diag::warn_property_types_are_incompatible)
+        << Property->getType() << SuperProperty->getType() << inheritedName;
+      Diag(SuperProperty->getLocation(), diag::note_property_declare);
+    }
+  }
+}
+
+bool Sema::DiagnosePropertyAccessorMismatch(ObjCPropertyDecl *property,
+                                            ObjCMethodDecl *GetterMethod,
+                                            SourceLocation Loc) {
+  if (GetterMethod &&
+      !Context.hasSameType(GetterMethod->getResultType().getNonReferenceType(),
+                           property->getType().getNonReferenceType())) {
+    AssignConvertType result = Incompatible;
+    if (property->getType()->isObjCObjectPointerType())
+      result = CheckAssignmentConstraints(Loc, GetterMethod->getResultType(),
+                                          property->getType());
+    if (result != Compatible) {
+      Diag(Loc, diag::warn_accessor_property_type_mismatch)
+      << property->getDeclName()
+      << GetterMethod->getSelector();
+      Diag(GetterMethod->getLocation(), diag::note_declared_at);
+      return true;
+    }
+  }
+  return false;
+}
+
+/// ComparePropertiesInBaseAndSuper - This routine compares property
+/// declarations in base and its super class, if any, and issues
+/// diagnostics in a variety of inconsistent situations.
+///
+void Sema::ComparePropertiesInBaseAndSuper(ObjCInterfaceDecl *IDecl) {
+  ObjCInterfaceDecl *SDecl = IDecl->getSuperClass();
+  if (!SDecl)
+    return;
+  // FIXME: O(N^2)
+  for (ObjCInterfaceDecl::prop_iterator S = SDecl->prop_begin(),
+       E = SDecl->prop_end(); S != E; ++S) {
+    ObjCPropertyDecl *SuperPDecl = (*S);
+    // Does property in super class has declaration in current class?
+    for (ObjCInterfaceDecl::prop_iterator I = IDecl->prop_begin(),
+         E = IDecl->prop_end(); I != E; ++I) {
+      ObjCPropertyDecl *PDecl = (*I);
+      if (SuperPDecl->getIdentifier() == PDecl->getIdentifier())
+          DiagnosePropertyMismatch(PDecl, SuperPDecl,
+                                   SDecl->getIdentifier());
+    }
+  }
+}
+
+/// MatchOneProtocolPropertiesInClass - This routine goes thru the list
+/// of properties declared in a protocol and compares their attribute against
+/// the same property declared in the class or category.
+void
+Sema::MatchOneProtocolPropertiesInClass(Decl *CDecl,
+                                          ObjCProtocolDecl *PDecl) {
+  ObjCInterfaceDecl *IDecl = dyn_cast_or_null<ObjCInterfaceDecl>(CDecl);
+  if (!IDecl) {
+    // Category
+    ObjCCategoryDecl *CatDecl = static_cast<ObjCCategoryDecl*>(CDecl);
+    assert (CatDecl && "MatchOneProtocolPropertiesInClass");
+    if (!CatDecl->IsClassExtension())
+      for (ObjCProtocolDecl::prop_iterator P = PDecl->prop_begin(),
+           E = PDecl->prop_end(); P != E; ++P) {
+        ObjCPropertyDecl *Pr = (*P);
+        ObjCCategoryDecl::prop_iterator CP, CE;
+        // Is this property already in  category's list of properties?
+        for (CP = CatDecl->prop_begin(), CE = CatDecl->prop_end(); CP!=CE; ++CP)
+          if ((*CP)->getIdentifier() == Pr->getIdentifier())
+            break;
+        if (CP != CE)
+          // Property protocol already exist in class. Diagnose any mismatch.
+          DiagnosePropertyMismatch((*CP), Pr, PDecl->getIdentifier());
+      }
+    return;
+  }
+  for (ObjCProtocolDecl::prop_iterator P = PDecl->prop_begin(),
+       E = PDecl->prop_end(); P != E; ++P) {
+    ObjCPropertyDecl *Pr = (*P);
+    ObjCInterfaceDecl::prop_iterator CP, CE;
+    // Is this property already in  class's list of properties?
+    for (CP = IDecl->prop_begin(), CE = IDecl->prop_end(); CP != CE; ++CP)
+      if ((*CP)->getIdentifier() == Pr->getIdentifier())
+        break;
+    if (CP != CE)
+      // Property protocol already exist in class. Diagnose any mismatch.
+      DiagnosePropertyMismatch((*CP), Pr, PDecl->getIdentifier());
+    }
+}
+
+/// CompareProperties - This routine compares properties
+/// declared in 'ClassOrProtocol' objects (which can be a class or an
+/// inherited protocol with the list of properties for class/category 'CDecl'
+///
+void Sema::CompareProperties(Decl *CDecl, Decl *ClassOrProtocol) {
+  Decl *ClassDecl = ClassOrProtocol;
+  ObjCInterfaceDecl *IDecl = dyn_cast_or_null<ObjCInterfaceDecl>(CDecl);
+
+  if (!IDecl) {
+    // Category
+    ObjCCategoryDecl *CatDecl = static_cast<ObjCCategoryDecl*>(CDecl);
+    assert (CatDecl && "CompareProperties");
+    if (ObjCCategoryDecl *MDecl = dyn_cast<ObjCCategoryDecl>(ClassDecl)) {
+      for (ObjCCategoryDecl::protocol_iterator P = MDecl->protocol_begin(),
+           E = MDecl->protocol_end(); P != E; ++P)
+      // Match properties of category with those of protocol (*P)
+      MatchOneProtocolPropertiesInClass(CatDecl, *P);
+
+      // Go thru the list of protocols for this category and recursively match
+      // their properties with those in the category.
+      for (ObjCCategoryDecl::protocol_iterator P = CatDecl->protocol_begin(),
+           E = CatDecl->protocol_end(); P != E; ++P)
+        CompareProperties(CatDecl, *P);
+    } else {
+      ObjCProtocolDecl *MD = cast<ObjCProtocolDecl>(ClassDecl);
+      for (ObjCProtocolDecl::protocol_iterator P = MD->protocol_begin(),
+           E = MD->protocol_end(); P != E; ++P)
+        MatchOneProtocolPropertiesInClass(CatDecl, *P);
+    }
+    return;
+  }
+
+  if (ObjCInterfaceDecl *MDecl = dyn_cast<ObjCInterfaceDecl>(ClassDecl)) {
+    for (ObjCInterfaceDecl::all_protocol_iterator
+          P = MDecl->all_referenced_protocol_begin(),
+          E = MDecl->all_referenced_protocol_end(); P != E; ++P)
+      // Match properties of class IDecl with those of protocol (*P).
+      MatchOneProtocolPropertiesInClass(IDecl, *P);
+
+    // Go thru the list of protocols for this class and recursively match
+    // their properties with those declared in the class.
+    for (ObjCInterfaceDecl::all_protocol_iterator
+          P = IDecl->all_referenced_protocol_begin(),
+          E = IDecl->all_referenced_protocol_end(); P != E; ++P)
+      CompareProperties(IDecl, *P);
+  } else {
+    ObjCProtocolDecl *MD = cast<ObjCProtocolDecl>(ClassDecl);
+    for (ObjCProtocolDecl::protocol_iterator P = MD->protocol_begin(),
+         E = MD->protocol_end(); P != E; ++P)
+      MatchOneProtocolPropertiesInClass(IDecl, *P);
+  }
+}
+
+/// isPropertyReadonly - Return true if property is readonly, by searching
+/// for the property in the class and in its categories and implementations
+///
+bool Sema::isPropertyReadonly(ObjCPropertyDecl *PDecl,
+                              ObjCInterfaceDecl *IDecl) {
+  // by far the most common case.
+  if (!PDecl->isReadOnly())
+    return false;
+  // Even if property is ready only, if interface has a user defined setter,
+  // it is not considered read only.
+  if (IDecl->getInstanceMethod(PDecl->getSetterName()))
+    return false;
+
+  // Main class has the property as 'readonly'. Must search
+  // through the category list to see if the property's
+  // attribute has been over-ridden to 'readwrite'.
+  for (ObjCCategoryDecl *Category = IDecl->getCategoryList();
+       Category; Category = Category->getNextClassCategory()) {
+    // Even if property is ready only, if a category has a user defined setter,
+    // it is not considered read only.
+    if (Category->getInstanceMethod(PDecl->getSetterName()))
+      return false;
+    ObjCPropertyDecl *P =
+      Category->FindPropertyDeclaration(PDecl->getIdentifier());
+    if (P && !P->isReadOnly())
+      return false;
+  }
+
+  // Also, check for definition of a setter method in the implementation if
+  // all else failed.
+  if (ObjCMethodDecl *OMD = dyn_cast<ObjCMethodDecl>(CurContext)) {
+    if (ObjCImplementationDecl *IMD =
+        dyn_cast<ObjCImplementationDecl>(OMD->getDeclContext())) {
+      if (IMD->getInstanceMethod(PDecl->getSetterName()))
+        return false;
+    } else if (ObjCCategoryImplDecl *CIMD =
+               dyn_cast<ObjCCategoryImplDecl>(OMD->getDeclContext())) {
+      if (CIMD->getInstanceMethod(PDecl->getSetterName()))
+        return false;
+    }
+  }
+  // Lastly, look through the implementation (if one is in scope).
+  if (ObjCImplementationDecl *ImpDecl = IDecl->getImplementation())
+    if (ImpDecl->getInstanceMethod(PDecl->getSetterName()))
+      return false;
+  // If all fails, look at the super class.
+  if (ObjCInterfaceDecl *SIDecl = IDecl->getSuperClass())
+    return isPropertyReadonly(PDecl, SIDecl);
+  return true;
+}
+
+/// CollectImmediateProperties - This routine collects all properties in
+/// the class and its conforming protocols; but not those it its super class.
+void Sema::CollectImmediateProperties(ObjCContainerDecl *CDecl,
+            llvm::DenseMap<IdentifierInfo *, ObjCPropertyDecl*>& PropMap,
+            llvm::DenseMap<IdentifierInfo *, ObjCPropertyDecl*>& SuperPropMap) {
+  if (ObjCInterfaceDecl *IDecl = dyn_cast<ObjCInterfaceDecl>(CDecl)) {
+    for (ObjCContainerDecl::prop_iterator P = IDecl->prop_begin(),
+         E = IDecl->prop_end(); P != E; ++P) {
+      ObjCPropertyDecl *Prop = (*P);
+      PropMap[Prop->getIdentifier()] = Prop;
+    }
+    // scan through class's protocols.
+    for (ObjCInterfaceDecl::all_protocol_iterator
+         PI = IDecl->all_referenced_protocol_begin(),
+         E = IDecl->all_referenced_protocol_end(); PI != E; ++PI)
+        CollectImmediateProperties((*PI), PropMap, SuperPropMap);
+  }
+  if (ObjCCategoryDecl *CATDecl = dyn_cast<ObjCCategoryDecl>(CDecl)) {
+    if (!CATDecl->IsClassExtension())
+      for (ObjCContainerDecl::prop_iterator P = CATDecl->prop_begin(),
+           E = CATDecl->prop_end(); P != E; ++P) {
+        ObjCPropertyDecl *Prop = (*P);
+        PropMap[Prop->getIdentifier()] = Prop;
+      }
+    // scan through class's protocols.
+    for (ObjCCategoryDecl::protocol_iterator PI = CATDecl->protocol_begin(),
+         E = CATDecl->protocol_end(); PI != E; ++PI)
+      CollectImmediateProperties((*PI), PropMap, SuperPropMap);
+  }
+  else if (ObjCProtocolDecl *PDecl = dyn_cast<ObjCProtocolDecl>(CDecl)) {
+    for (ObjCProtocolDecl::prop_iterator P = PDecl->prop_begin(),
+         E = PDecl->prop_end(); P != E; ++P) {
+      ObjCPropertyDecl *Prop = (*P);
+      ObjCPropertyDecl *PropertyFromSuper = SuperPropMap[Prop->getIdentifier()];
+      // Exclude property for protocols which conform to class's super-class, 
+      // as super-class has to implement the property.
+      if (!PropertyFromSuper || 
+          PropertyFromSuper->getIdentifier() != Prop->getIdentifier()) {
+        ObjCPropertyDecl *&PropEntry = PropMap[Prop->getIdentifier()];
+        if (!PropEntry)
+          PropEntry = Prop;
+      }
+    }
+    // scan through protocol's protocols.
+    for (ObjCProtocolDecl::protocol_iterator PI = PDecl->protocol_begin(),
+         E = PDecl->protocol_end(); PI != E; ++PI)
+      CollectImmediateProperties((*PI), PropMap, SuperPropMap);
+  }
+}
+
+/// CollectClassPropertyImplementations - This routine collects list of
+/// properties to be implemented in the class. This includes, class's
+/// and its conforming protocols' properties.
+static void CollectClassPropertyImplementations(ObjCContainerDecl *CDecl,
+                llvm::DenseMap<IdentifierInfo *, ObjCPropertyDecl*>& PropMap) {
+  if (ObjCInterfaceDecl *IDecl = dyn_cast<ObjCInterfaceDecl>(CDecl)) {
+    for (ObjCContainerDecl::prop_iterator P = IDecl->prop_begin(),
+         E = IDecl->prop_end(); P != E; ++P) {
+      ObjCPropertyDecl *Prop = (*P);
+      PropMap[Prop->getIdentifier()] = Prop;
+    }
+    for (ObjCInterfaceDecl::all_protocol_iterator
+         PI = IDecl->all_referenced_protocol_begin(),
+         E = IDecl->all_referenced_protocol_end(); PI != E; ++PI)
+      CollectClassPropertyImplementations((*PI), PropMap);
+  }
+  else if (ObjCProtocolDecl *PDecl = dyn_cast<ObjCProtocolDecl>(CDecl)) {
+    for (ObjCProtocolDecl::prop_iterator P = PDecl->prop_begin(),
+         E = PDecl->prop_end(); P != E; ++P) {
+      ObjCPropertyDecl *Prop = (*P);
+      if (!PropMap.count(Prop->getIdentifier()))
+        PropMap[Prop->getIdentifier()] = Prop;
+    }
+    // scan through protocol's protocols.
+    for (ObjCProtocolDecl::protocol_iterator PI = PDecl->protocol_begin(),
+         E = PDecl->protocol_end(); PI != E; ++PI)
+      CollectClassPropertyImplementations((*PI), PropMap);
+  }
+}
+
+/// CollectSuperClassPropertyImplementations - This routine collects list of
+/// properties to be implemented in super class(s) and also coming from their
+/// conforming protocols.
+static void CollectSuperClassPropertyImplementations(ObjCInterfaceDecl *CDecl,
+                llvm::DenseMap<IdentifierInfo *, ObjCPropertyDecl*>& PropMap) {
+  if (ObjCInterfaceDecl *SDecl = CDecl->getSuperClass()) {
+    while (SDecl) {
+      CollectClassPropertyImplementations(SDecl, PropMap);
+      SDecl = SDecl->getSuperClass();
+    }
+  }
+}
+
+/// LookupPropertyDecl - Looks up a property in the current class and all
+/// its protocols.
+ObjCPropertyDecl *Sema::LookupPropertyDecl(const ObjCContainerDecl *CDecl,
+                                     IdentifierInfo *II) {
+  if (const ObjCInterfaceDecl *IDecl =
+        dyn_cast<ObjCInterfaceDecl>(CDecl)) {
+    for (ObjCContainerDecl::prop_iterator P = IDecl->prop_begin(),
+         E = IDecl->prop_end(); P != E; ++P) {
+      ObjCPropertyDecl *Prop = (*P);
+      if (Prop->getIdentifier() == II)
+        return Prop;
+    }
+    // scan through class's protocols.
+    for (ObjCInterfaceDecl::all_protocol_iterator
+         PI = IDecl->all_referenced_protocol_begin(),
+         E = IDecl->all_referenced_protocol_end(); PI != E; ++PI) {
+      ObjCPropertyDecl *Prop = LookupPropertyDecl((*PI), II);
+      if (Prop)
+        return Prop;
+    }
+  }
+  else if (const ObjCProtocolDecl *PDecl =
+            dyn_cast<ObjCProtocolDecl>(CDecl)) {
+    for (ObjCProtocolDecl::prop_iterator P = PDecl->prop_begin(),
+         E = PDecl->prop_end(); P != E; ++P) {
+      ObjCPropertyDecl *Prop = (*P);
+      if (Prop->getIdentifier() == II)
+        return Prop;
+    }
+    // scan through protocol's protocols.
+    for (ObjCProtocolDecl::protocol_iterator PI = PDecl->protocol_begin(),
+         E = PDecl->protocol_end(); PI != E; ++PI) {
+      ObjCPropertyDecl *Prop = LookupPropertyDecl((*PI), II);
+      if (Prop)
+        return Prop;
+    }
+  }
+  return 0;
+}
+
+static IdentifierInfo * getDefaultSynthIvarName(ObjCPropertyDecl *Prop,
+                                                ASTContext &Ctx) {
+  SmallString<128> ivarName;
+  {
+    llvm::raw_svector_ostream os(ivarName);
+    os << '_' << Prop->getIdentifier()->getName();
+  }
+  return &Ctx.Idents.get(ivarName.str());
+}
+
+/// DefaultSynthesizeProperties - This routine default synthesizes all
+/// properties which must be synthesized in class's @implementation.
+void Sema::DefaultSynthesizeProperties(Scope *S, ObjCImplDecl* IMPDecl,
+                                       ObjCInterfaceDecl *IDecl) {
+  
+  llvm::DenseMap<IdentifierInfo *, ObjCPropertyDecl*> PropMap;
+  CollectClassPropertyImplementations(IDecl, PropMap);
+  if (PropMap.empty())
+    return;
+  llvm::DenseMap<IdentifierInfo *, ObjCPropertyDecl*> SuperPropMap;
+  CollectSuperClassPropertyImplementations(IDecl, SuperPropMap);
+  
+  for (llvm::DenseMap<IdentifierInfo *, ObjCPropertyDecl*>::iterator
+       P = PropMap.begin(), E = PropMap.end(); P != E; ++P) {
+    ObjCPropertyDecl *Prop = P->second;
+    // If property to be implemented in the super class, ignore.
+    if (SuperPropMap[Prop->getIdentifier()])
+      continue;
+    // Is there a matching propery synthesize/dynamic?
+    if (Prop->isInvalidDecl() ||
+        Prop->getPropertyImplementation() == ObjCPropertyDecl::Optional ||
+        IMPDecl->FindPropertyImplIvarDecl(Prop->getIdentifier()))
+      continue;
+    // Property may have been synthesized by user.
+    if (IMPDecl->FindPropertyImplDecl(Prop->getIdentifier()))
+      continue;
+    if (IMPDecl->getInstanceMethod(Prop->getGetterName())) {
+      if (Prop->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_readonly)
+        continue;
+      if (IMPDecl->getInstanceMethod(Prop->getSetterName()))
+        continue;
+    }
+    if (isa<ObjCProtocolDecl>(Prop->getDeclContext())) {
+      // We won't auto-synthesize properties declared in protocols.
+      Diag(IMPDecl->getLocation(), 
+           diag::warn_auto_synthesizing_protocol_property);
+      Diag(Prop->getLocation(), diag::note_property_declare);
+      continue;
+    }
+
+    // We use invalid SourceLocations for the synthesized ivars since they
+    // aren't really synthesized at a particular location; they just exist.
+    // Saying that they are located at the @implementation isn't really going
+    // to help users.
+    ActOnPropertyImplDecl(S, SourceLocation(), SourceLocation(),
+                          true,
+                          /* property = */ Prop->getIdentifier(),
+                          /* ivar = */ getDefaultSynthIvarName(Prop, Context),
+                          SourceLocation());
+  }
+}
+
+void Sema::DefaultSynthesizeProperties(Scope *S, Decl *D) {
+  if (!LangOpts.ObjCDefaultSynthProperties || !LangOpts.ObjCNonFragileABI2)
+    return;
+  ObjCImplementationDecl *IC=dyn_cast_or_null<ObjCImplementationDecl>(D);
+  if (!IC)
+    return;
+  if (ObjCInterfaceDecl* IDecl = IC->getClassInterface())
+    if (!IDecl->isObjCRequiresPropertyDefs())
+      DefaultSynthesizeProperties(S, IC, IDecl);
+}
+
+void Sema::DiagnoseUnimplementedProperties(Scope *S, ObjCImplDecl* IMPDecl,
+                                      ObjCContainerDecl *CDecl,
+                                      const llvm::DenseSet<Selector>& InsMap) {
+  llvm::DenseMap<IdentifierInfo *, ObjCPropertyDecl*> SuperPropMap;
+  if (ObjCInterfaceDecl *IDecl = dyn_cast<ObjCInterfaceDecl>(CDecl))
+    CollectSuperClassPropertyImplementations(IDecl, SuperPropMap);
+  
+  llvm::DenseMap<IdentifierInfo *, ObjCPropertyDecl*> PropMap;
+  CollectImmediateProperties(CDecl, PropMap, SuperPropMap);
+  if (PropMap.empty())
+    return;
+
+  llvm::DenseSet<ObjCPropertyDecl *> PropImplMap;
+  for (ObjCImplDecl::propimpl_iterator
+       I = IMPDecl->propimpl_begin(),
+       EI = IMPDecl->propimpl_end(); I != EI; ++I)
+    PropImplMap.insert((*I)->getPropertyDecl());
+
+  for (llvm::DenseMap<IdentifierInfo *, ObjCPropertyDecl*>::iterator
+       P = PropMap.begin(), E = PropMap.end(); P != E; ++P) {
+    ObjCPropertyDecl *Prop = P->second;
+    // Is there a matching propery synthesize/dynamic?
+    if (Prop->isInvalidDecl() ||
+        Prop->getPropertyImplementation() == ObjCPropertyDecl::Optional ||
+        PropImplMap.count(Prop) || Prop->hasAttr<UnavailableAttr>())
+      continue;
+    if (!InsMap.count(Prop->getGetterName())) {
+      Diag(IMPDecl->getLocation(),
+           isa<ObjCCategoryDecl>(CDecl) ?
+            diag::warn_setter_getter_impl_required_in_category :
+            diag::warn_setter_getter_impl_required)
+      << Prop->getDeclName() << Prop->getGetterName();
+      Diag(Prop->getLocation(),
+           diag::note_property_declare);
+      if (LangOpts.ObjCDefaultSynthProperties && LangOpts.ObjCNonFragileABI2)
+        if (ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(CDecl))
+          if (const ObjCInterfaceDecl *RID = ID->isObjCRequiresPropertyDefs())
+            Diag(RID->getLocation(), diag::note_suppressed_class_declare);
+            
+    }
+
+    if (!Prop->isReadOnly() && !InsMap.count(Prop->getSetterName())) {
+      Diag(IMPDecl->getLocation(),
+           isa<ObjCCategoryDecl>(CDecl) ?
+           diag::warn_setter_getter_impl_required_in_category :
+           diag::warn_setter_getter_impl_required)
+      << Prop->getDeclName() << Prop->getSetterName();
+      Diag(Prop->getLocation(),
+           diag::note_property_declare);
+      if (LangOpts.ObjCDefaultSynthProperties && LangOpts.ObjCNonFragileABI2)
+        if (ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(CDecl))
+          if (const ObjCInterfaceDecl *RID = ID->isObjCRequiresPropertyDefs())
+            Diag(RID->getLocation(), diag::note_suppressed_class_declare);
+    }
+  }
+}
+
+void
+Sema::AtomicPropertySetterGetterRules (ObjCImplDecl* IMPDecl,
+                                       ObjCContainerDecl* IDecl) {
+  // Rules apply in non-GC mode only
+  if (getLangOpts().getGC() != LangOptions::NonGC)
+    return;
+  for (ObjCContainerDecl::prop_iterator I = IDecl->prop_begin(),
+       E = IDecl->prop_end();
+       I != E; ++I) {
+    ObjCPropertyDecl *Property = (*I);
+    ObjCMethodDecl *GetterMethod = 0;
+    ObjCMethodDecl *SetterMethod = 0;
+    bool LookedUpGetterSetter = false;
+
+    unsigned Attributes = Property->getPropertyAttributes();
+    unsigned AttributesAsWritten = Property->getPropertyAttributesAsWritten();
+
+    if (!(AttributesAsWritten & ObjCPropertyDecl::OBJC_PR_atomic) &&
+        !(AttributesAsWritten & ObjCPropertyDecl::OBJC_PR_nonatomic)) {
+      GetterMethod = IMPDecl->getInstanceMethod(Property->getGetterName());
+      SetterMethod = IMPDecl->getInstanceMethod(Property->getSetterName());
+      LookedUpGetterSetter = true;
+      if (GetterMethod) {
+        Diag(GetterMethod->getLocation(),
+             diag::warn_default_atomic_custom_getter_setter)
+          << Property->getIdentifier() << 0;
+        Diag(Property->getLocation(), diag::note_property_declare);
+      }
+      if (SetterMethod) {
+        Diag(SetterMethod->getLocation(),
+             diag::warn_default_atomic_custom_getter_setter)
+          << Property->getIdentifier() << 1;
+        Diag(Property->getLocation(), diag::note_property_declare);
+      }
+    }
+
+    // We only care about readwrite atomic property.
+    if ((Attributes & ObjCPropertyDecl::OBJC_PR_nonatomic) ||
+        !(Attributes & ObjCPropertyDecl::OBJC_PR_readwrite))
+      continue;
+    if (const ObjCPropertyImplDecl *PIDecl
+         = IMPDecl->FindPropertyImplDecl(Property->getIdentifier())) {
+      if (PIDecl->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic)
+        continue;
+      if (!LookedUpGetterSetter) {
+        GetterMethod = IMPDecl->getInstanceMethod(Property->getGetterName());
+        SetterMethod = IMPDecl->getInstanceMethod(Property->getSetterName());
+        LookedUpGetterSetter = true;
+      }
+      if ((GetterMethod && !SetterMethod) || (!GetterMethod && SetterMethod)) {
+        SourceLocation MethodLoc =
+          (GetterMethod ? GetterMethod->getLocation()
+                        : SetterMethod->getLocation());
+        Diag(MethodLoc, diag::warn_atomic_property_rule)
+          << Property->getIdentifier() << (GetterMethod != 0)
+          << (SetterMethod != 0);
+        // fixit stuff.
+        if (!AttributesAsWritten) {
+          if (Property->getLParenLoc().isValid()) {
+            // @property () ... case.
+            SourceRange PropSourceRange(Property->getAtLoc(), 
+                                        Property->getLParenLoc());
+            Diag(Property->getLocation(), diag::note_atomic_property_fixup_suggest) <<
+              FixItHint::CreateReplacement(PropSourceRange, "@property (nonatomic");
+          }
+          else {
+            //@property id etc.
+            SourceLocation endLoc = 
+              Property->getTypeSourceInfo()->getTypeLoc().getBeginLoc();
+            endLoc = endLoc.getLocWithOffset(-1);
+            SourceRange PropSourceRange(Property->getAtLoc(), endLoc);
+            Diag(Property->getLocation(), diag::note_atomic_property_fixup_suggest) <<
+              FixItHint::CreateReplacement(PropSourceRange, "@property (nonatomic) ");
+          }
+        }
+        else if (!(AttributesAsWritten & ObjCPropertyDecl::OBJC_PR_atomic)) {
+          // @property () ... case.
+          SourceLocation endLoc = Property->getLParenLoc();
+          SourceRange PropSourceRange(Property->getAtLoc(), endLoc);
+          Diag(Property->getLocation(), diag::note_atomic_property_fixup_suggest) <<
+           FixItHint::CreateReplacement(PropSourceRange, "@property (nonatomic, ");
+        }
+        else
+          Diag(MethodLoc, diag::note_atomic_property_fixup_suggest);
+        Diag(Property->getLocation(), diag::note_property_declare);
+      }
+    }
+  }
+}
+
+void Sema::DiagnoseOwningPropertyGetterSynthesis(const ObjCImplementationDecl *D) {
+  if (getLangOpts().getGC() == LangOptions::GCOnly)
+    return;
+
+  for (ObjCImplementationDecl::propimpl_iterator
+         i = D->propimpl_begin(), e = D->propimpl_end(); i != e; ++i) {
+    ObjCPropertyImplDecl *PID = *i;
+    if (PID->getPropertyImplementation() != ObjCPropertyImplDecl::Synthesize)
+      continue;
+    
+    const ObjCPropertyDecl *PD = PID->getPropertyDecl();
+    if (PD && !PD->hasAttr<NSReturnsNotRetainedAttr>() &&
+        !D->getInstanceMethod(PD->getGetterName())) {
+      ObjCMethodDecl *method = PD->getGetterMethodDecl();
+      if (!method)
+        continue;
+      ObjCMethodFamily family = method->getMethodFamily();
+      if (family == OMF_alloc || family == OMF_copy ||
+          family == OMF_mutableCopy || family == OMF_new) {
+        if (getLangOpts().ObjCAutoRefCount)
+          Diag(PID->getLocation(), diag::err_ownin_getter_rule);
+        else
+          Diag(PID->getLocation(), diag::warn_owning_getter_rule);
+        Diag(PD->getLocation(), diag::note_property_declare);
+      }
+    }
+  }
+}
+
+/// AddPropertyAttrs - Propagates attributes from a property to the
+/// implicitly-declared getter or setter for that property.
+static void AddPropertyAttrs(Sema &S, ObjCMethodDecl *PropertyMethod,
+                             ObjCPropertyDecl *Property) {
+  // Should we just clone all attributes over?
+  for (Decl::attr_iterator A = Property->attr_begin(), 
+                        AEnd = Property->attr_end(); 
+       A != AEnd; ++A) {
+    if (isa<DeprecatedAttr>(*A) || 
+        isa<UnavailableAttr>(*A) || 
+        isa<AvailabilityAttr>(*A))
+      PropertyMethod->addAttr((*A)->clone(S.Context));
+  }
+}
+
+/// ProcessPropertyDecl - Make sure that any user-defined setter/getter methods
+/// have the property type and issue diagnostics if they don't.
+/// Also synthesize a getter/setter method if none exist (and update the
+/// appropriate lookup tables. FIXME: Should reconsider if adding synthesized
+/// methods is the "right" thing to do.
+void Sema::ProcessPropertyDecl(ObjCPropertyDecl *property,
+                               ObjCContainerDecl *CD,
+                               ObjCPropertyDecl *redeclaredProperty,
+                               ObjCContainerDecl *lexicalDC) {
+
+  ObjCMethodDecl *GetterMethod, *SetterMethod;
+
+  GetterMethod = CD->getInstanceMethod(property->getGetterName());
+  SetterMethod = CD->getInstanceMethod(property->getSetterName());
+  DiagnosePropertyAccessorMismatch(property, GetterMethod,
+                                   property->getLocation());
+
+  if (SetterMethod) {
+    ObjCPropertyDecl::PropertyAttributeKind CAttr =
+      property->getPropertyAttributes();
+    if ((!(CAttr & ObjCPropertyDecl::OBJC_PR_readonly)) &&
+        Context.getCanonicalType(SetterMethod->getResultType()) !=
+          Context.VoidTy)
+      Diag(SetterMethod->getLocation(), diag::err_setter_type_void);
+    if (SetterMethod->param_size() != 1 ||
+        !Context.hasSameUnqualifiedType(
+          (*SetterMethod->param_begin())->getType().getNonReferenceType(), 
+          property->getType().getNonReferenceType())) {
+      Diag(property->getLocation(),
+           diag::warn_accessor_property_type_mismatch)
+        << property->getDeclName()
+        << SetterMethod->getSelector();
+      Diag(SetterMethod->getLocation(), diag::note_declared_at);
+    }
+  }
+
+  // Synthesize getter/setter methods if none exist.
+  // Find the default getter and if one not found, add one.
+  // FIXME: The synthesized property we set here is misleading. We almost always
+  // synthesize these methods unless the user explicitly provided prototypes
+  // (which is odd, but allowed). Sema should be typechecking that the
+  // declarations jive in that situation (which it is not currently).
+  if (!GetterMethod) {
+    // No instance method of same name as property getter name was found.
+    // Declare a getter method and add it to the list of methods
+    // for this class.
+    SourceLocation Loc = redeclaredProperty ? 
+      redeclaredProperty->getLocation() :
+      property->getLocation();
+
+    GetterMethod = ObjCMethodDecl::Create(Context, Loc, Loc,
+                             property->getGetterName(),
+                             property->getType(), 0, CD, /*isInstance=*/true,
+                             /*isVariadic=*/false, /*isSynthesized=*/true,
+                             /*isImplicitlyDeclared=*/true, /*isDefined=*/false,
+                             (property->getPropertyImplementation() ==
+                              ObjCPropertyDecl::Optional) ?
+                             ObjCMethodDecl::Optional :
+                             ObjCMethodDecl::Required);
+    CD->addDecl(GetterMethod);
+
+    AddPropertyAttrs(*this, GetterMethod, property);
+
+    // FIXME: Eventually this shouldn't be needed, as the lexical context
+    // and the real context should be the same.
+    if (lexicalDC)
+      GetterMethod->setLexicalDeclContext(lexicalDC);
+    if (property->hasAttr<NSReturnsNotRetainedAttr>())
+      GetterMethod->addAttr(
+        ::new (Context) NSReturnsNotRetainedAttr(Loc, Context));
+  } else
+    // A user declared getter will be synthesize when @synthesize of
+    // the property with the same name is seen in the @implementation
+    GetterMethod->setSynthesized(true);
+  property->setGetterMethodDecl(GetterMethod);
+
+  // Skip setter if property is read-only.
+  if (!property->isReadOnly()) {
+    // Find the default setter and if one not found, add one.
+    if (!SetterMethod) {
+      // No instance method of same name as property setter name was found.
+      // Declare a setter method and add it to the list of methods
+      // for this class.
+      SourceLocation Loc = redeclaredProperty ? 
+        redeclaredProperty->getLocation() :
+        property->getLocation();
+
+      SetterMethod =
+        ObjCMethodDecl::Create(Context, Loc, Loc,
+                               property->getSetterName(), Context.VoidTy, 0,
+                               CD, /*isInstance=*/true, /*isVariadic=*/false,
+                               /*isSynthesized=*/true,
+                               /*isImplicitlyDeclared=*/true,
+                               /*isDefined=*/false,
+                               (property->getPropertyImplementation() ==
+                                ObjCPropertyDecl::Optional) ?
+                                ObjCMethodDecl::Optional :
+                                ObjCMethodDecl::Required);
+
+      // Invent the arguments for the setter. We don't bother making a
+      // nice name for the argument.
+      ParmVarDecl *Argument = ParmVarDecl::Create(Context, SetterMethod,
+                                                  Loc, Loc,
+                                                  property->getIdentifier(),
+                                    property->getType().getUnqualifiedType(),
+                                                  /*TInfo=*/0,
+                                                  SC_None,
+                                                  SC_None,
+                                                  0);
+      SetterMethod->setMethodParams(Context, Argument,
+                                    ArrayRef<SourceLocation>());
+
+      AddPropertyAttrs(*this, SetterMethod, property);
+
+      CD->addDecl(SetterMethod);
+      // FIXME: Eventually this shouldn't be needed, as the lexical context
+      // and the real context should be the same.
+      if (lexicalDC)
+        SetterMethod->setLexicalDeclContext(lexicalDC);
+    } else
+      // A user declared setter will be synthesize when @synthesize of
+      // the property with the same name is seen in the @implementation
+      SetterMethod->setSynthesized(true);
+    property->setSetterMethodDecl(SetterMethod);
+  }
+  // Add any synthesized methods to the global pool. This allows us to
+  // handle the following, which is supported by GCC (and part of the design).
+  //
+  // @interface Foo
+  // @property double bar;
+  // @end
+  //
+  // void thisIsUnfortunate() {
+  //   id foo;
+  //   double bar = [foo bar];
+  // }
+  //
+  if (GetterMethod)
+    AddInstanceMethodToGlobalPool(GetterMethod);
+  if (SetterMethod)
+    AddInstanceMethodToGlobalPool(SetterMethod);
+}
+
+void Sema::CheckObjCPropertyAttributes(Decl *PDecl,
+                                       SourceLocation Loc,
+                                       unsigned &Attributes) {
+  // FIXME: Improve the reported location.
+  if (!PDecl || PDecl->isInvalidDecl())
+    return;
+
+  ObjCPropertyDecl *PropertyDecl = cast<ObjCPropertyDecl>(PDecl);
+  QualType PropertyTy = PropertyDecl->getType(); 
+
+  if (getLangOpts().ObjCAutoRefCount &&
+      (Attributes & ObjCDeclSpec::DQ_PR_readonly) &&
+      PropertyTy->isObjCRetainableType()) {
+    // 'readonly' property with no obvious lifetime.
+    // its life time will be determined by its backing ivar.
+    unsigned rel = (ObjCDeclSpec::DQ_PR_unsafe_unretained |
+                    ObjCDeclSpec::DQ_PR_copy |
+                    ObjCDeclSpec::DQ_PR_retain |
+                    ObjCDeclSpec::DQ_PR_strong |
+                    ObjCDeclSpec::DQ_PR_weak |
+                    ObjCDeclSpec::DQ_PR_assign);
+    if ((Attributes & rel) == 0)
+      return;
+  }
+  
+  // readonly and readwrite/assign/retain/copy conflict.
+  if ((Attributes & ObjCDeclSpec::DQ_PR_readonly) &&
+      (Attributes & (ObjCDeclSpec::DQ_PR_readwrite |
+                     ObjCDeclSpec::DQ_PR_assign |
+                     ObjCDeclSpec::DQ_PR_unsafe_unretained |
+                     ObjCDeclSpec::DQ_PR_copy |
+                     ObjCDeclSpec::DQ_PR_retain |
+                     ObjCDeclSpec::DQ_PR_strong))) {
+    const char * which = (Attributes & ObjCDeclSpec::DQ_PR_readwrite) ?
+                          "readwrite" :
+                         (Attributes & ObjCDeclSpec::DQ_PR_assign) ?
+                          "assign" :
+                         (Attributes & ObjCDeclSpec::DQ_PR_unsafe_unretained) ?
+                          "unsafe_unretained" :
+                         (Attributes & ObjCDeclSpec::DQ_PR_copy) ?
+                          "copy" : "retain";
+
+    Diag(Loc, (Attributes & (ObjCDeclSpec::DQ_PR_readwrite)) ?
+                 diag::err_objc_property_attr_mutually_exclusive :
+                 diag::warn_objc_property_attr_mutually_exclusive)
+      << "readonly" << which;
+  }
+
+  // Check for copy or retain on non-object types.
+  if ((Attributes & (ObjCDeclSpec::DQ_PR_weak | ObjCDeclSpec::DQ_PR_copy |
+                    ObjCDeclSpec::DQ_PR_retain | ObjCDeclSpec::DQ_PR_strong)) &&
+      !PropertyTy->isObjCRetainableType() &&
+      !PropertyDecl->getAttr<ObjCNSObjectAttr>()) {
+    Diag(Loc, diag::err_objc_property_requires_object)
+      << (Attributes & ObjCDeclSpec::DQ_PR_weak ? "weak" :
+          Attributes & ObjCDeclSpec::DQ_PR_copy ? "copy" : "retain (or strong)");
+    Attributes &= ~(ObjCDeclSpec::DQ_PR_weak   | ObjCDeclSpec::DQ_PR_copy |
+                    ObjCDeclSpec::DQ_PR_retain | ObjCDeclSpec::DQ_PR_strong);
+    PropertyDecl->setInvalidDecl();
+  }
+
+  // Check for more than one of { assign, copy, retain }.
+  if (Attributes & ObjCDeclSpec::DQ_PR_assign) {
+    if (Attributes & ObjCDeclSpec::DQ_PR_copy) {
+      Diag(Loc, diag::err_objc_property_attr_mutually_exclusive)
+        << "assign" << "copy";
+      Attributes &= ~ObjCDeclSpec::DQ_PR_copy;
+    }
+    if (Attributes & ObjCDeclSpec::DQ_PR_retain) {
+      Diag(Loc, diag::err_objc_property_attr_mutually_exclusive)
+        << "assign" << "retain";
+      Attributes &= ~ObjCDeclSpec::DQ_PR_retain;
+    }
+    if (Attributes & ObjCDeclSpec::DQ_PR_strong) {
+      Diag(Loc, diag::err_objc_property_attr_mutually_exclusive)
+        << "assign" << "strong";
+      Attributes &= ~ObjCDeclSpec::DQ_PR_strong;
+    }
+    if (getLangOpts().ObjCAutoRefCount  &&
+        (Attributes & ObjCDeclSpec::DQ_PR_weak)) {
+      Diag(Loc, diag::err_objc_property_attr_mutually_exclusive)
+        << "assign" << "weak";
+      Attributes &= ~ObjCDeclSpec::DQ_PR_weak;
+    }
+  } else if (Attributes & ObjCDeclSpec::DQ_PR_unsafe_unretained) {
+    if (Attributes & ObjCDeclSpec::DQ_PR_copy) {
+      Diag(Loc, diag::err_objc_property_attr_mutually_exclusive)
+        << "unsafe_unretained" << "copy";
+      Attributes &= ~ObjCDeclSpec::DQ_PR_copy;
+    }
+    if (Attributes & ObjCDeclSpec::DQ_PR_retain) {
+      Diag(Loc, diag::err_objc_property_attr_mutually_exclusive)
+        << "unsafe_unretained" << "retain";
+      Attributes &= ~ObjCDeclSpec::DQ_PR_retain;
+    }
+    if (Attributes & ObjCDeclSpec::DQ_PR_strong) {
+      Diag(Loc, diag::err_objc_property_attr_mutually_exclusive)
+        << "unsafe_unretained" << "strong";
+      Attributes &= ~ObjCDeclSpec::DQ_PR_strong;
+    }
+    if (getLangOpts().ObjCAutoRefCount  &&
+        (Attributes & ObjCDeclSpec::DQ_PR_weak)) {
+      Diag(Loc, diag::err_objc_property_attr_mutually_exclusive)
+        << "unsafe_unretained" << "weak";
+      Attributes &= ~ObjCDeclSpec::DQ_PR_weak;
+    }
+  } else if (Attributes & ObjCDeclSpec::DQ_PR_copy) {
+    if (Attributes & ObjCDeclSpec::DQ_PR_retain) {
+      Diag(Loc, diag::err_objc_property_attr_mutually_exclusive)
+        << "copy" << "retain";
+      Attributes &= ~ObjCDeclSpec::DQ_PR_retain;
+    }
+    if (Attributes & ObjCDeclSpec::DQ_PR_strong) {
+      Diag(Loc, diag::err_objc_property_attr_mutually_exclusive)
+        << "copy" << "strong";
+      Attributes &= ~ObjCDeclSpec::DQ_PR_strong;
+    }
+    if (Attributes & ObjCDeclSpec::DQ_PR_weak) {
+      Diag(Loc, diag::err_objc_property_attr_mutually_exclusive)
+        << "copy" << "weak";
+      Attributes &= ~ObjCDeclSpec::DQ_PR_weak;
+    }
+  }
+  else if ((Attributes & ObjCDeclSpec::DQ_PR_retain) &&
+           (Attributes & ObjCDeclSpec::DQ_PR_weak)) {
+      Diag(Loc, diag::err_objc_property_attr_mutually_exclusive)
+        << "retain" << "weak";
+      Attributes &= ~ObjCDeclSpec::DQ_PR_retain;
+  }
+  else if ((Attributes & ObjCDeclSpec::DQ_PR_strong) &&
+           (Attributes & ObjCDeclSpec::DQ_PR_weak)) {
+      Diag(Loc, diag::err_objc_property_attr_mutually_exclusive)
+        << "strong" << "weak";
+      Attributes &= ~ObjCDeclSpec::DQ_PR_weak;
+  }
+
+  if ((Attributes & ObjCDeclSpec::DQ_PR_atomic) &&
+      (Attributes & ObjCDeclSpec::DQ_PR_nonatomic)) {
+      Diag(Loc, diag::err_objc_property_attr_mutually_exclusive)
+        << "atomic" << "nonatomic";
+      Attributes &= ~ObjCDeclSpec::DQ_PR_atomic;
+  }
+
+  // Warn if user supplied no assignment attribute, property is
+  // readwrite, and this is an object type.
+  if (!(Attributes & (ObjCDeclSpec::DQ_PR_assign | ObjCDeclSpec::DQ_PR_copy |
+                      ObjCDeclSpec::DQ_PR_unsafe_unretained |
+                      ObjCDeclSpec::DQ_PR_retain | ObjCDeclSpec::DQ_PR_strong |
+                      ObjCDeclSpec::DQ_PR_weak)) &&
+      PropertyTy->isObjCObjectPointerType()) {
+      if (getLangOpts().ObjCAutoRefCount)
+        // With arc,  @property definitions should default to (strong) when 
+        // not specified; including when property is 'readonly'.
+        PropertyDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_strong);
+      else if (!(Attributes & ObjCDeclSpec::DQ_PR_readonly)) {
+        bool isAnyClassTy = 
+          (PropertyTy->isObjCClassType() || 
+           PropertyTy->isObjCQualifiedClassType());
+        // In non-gc, non-arc mode, 'Class' is treated as a 'void *' no need to
+        // issue any warning.
+        if (isAnyClassTy && getLangOpts().getGC() == LangOptions::NonGC)
+          ;
+        else {
+          // Skip this warning in gc-only mode.
+          if (getLangOpts().getGC() != LangOptions::GCOnly)
+            Diag(Loc, diag::warn_objc_property_no_assignment_attribute);
+
+          // If non-gc code warn that this is likely inappropriate.
+          if (getLangOpts().getGC() == LangOptions::NonGC)
+            Diag(Loc, diag::warn_objc_property_default_assign_on_object);
+        }
+      }
+
+    // FIXME: Implement warning dependent on NSCopying being
+    // implemented. See also:
+    // <rdar://5168496&4855821&5607453&5096644&4947311&5698469&4947014&5168496>
+    // (please trim this list while you are at it).
+  }
+
+  if (!(Attributes & ObjCDeclSpec::DQ_PR_copy)
+      &&!(Attributes & ObjCDeclSpec::DQ_PR_readonly)
+      && getLangOpts().getGC() == LangOptions::GCOnly
+      && PropertyTy->isBlockPointerType())
+    Diag(Loc, diag::warn_objc_property_copy_missing_on_block);
+  else if (getLangOpts().ObjCAutoRefCount &&
+           (Attributes & ObjCDeclSpec::DQ_PR_retain) &&
+           !(Attributes & ObjCDeclSpec::DQ_PR_readonly) &&
+           !(Attributes & ObjCDeclSpec::DQ_PR_strong) &&
+           PropertyTy->isBlockPointerType())
+      Diag(Loc, diag::warn_objc_property_retain_of_block);
+  
+  if ((Attributes & ObjCDeclSpec::DQ_PR_readonly) &&
+      (Attributes & ObjCDeclSpec::DQ_PR_setter))
+    Diag(Loc, diag::warn_objc_readonly_property_has_setter);
+      
+}
diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
new file mode 100644
index 0000000..50230f0
--- /dev/null
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -0,0 +1,11229 @@
+//===--- SemaOverload.cpp - C++ Overloading ---------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file provides Sema routines for C++ overloading.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Sema/SemaInternal.h"
+#include "clang/Sema/Lookup.h"
+#include "clang/Sema/Initialization.h"
+#include "clang/Sema/Template.h"
+#include "clang/Sema/TemplateDeduction.h"
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Lex/Preprocessor.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/CXXInheritance.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/ExprCXX.h"
+#include "clang/AST/ExprObjC.h"
+#include "clang/AST/TypeOrdering.h"
+#include "clang/Basic/PartialDiagnostic.h"
+#include "llvm/ADT/DenseSet.h"
+#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/STLExtras.h"
+#include <algorithm>
+
+namespace clang {
+using namespace sema;
+
+/// A convenience routine for creating a decayed reference to a
+/// function.
+static ExprResult
+CreateFunctionRefExpr(Sema &S, FunctionDecl *Fn, bool HadMultipleCandidates,
+                      SourceLocation Loc = SourceLocation(), 
+                      const DeclarationNameLoc &LocInfo = DeclarationNameLoc()){
+  DeclRefExpr *DRE = new (S.Context) DeclRefExpr(Fn, false, Fn->getType(),
+                                                 VK_LValue, Loc, LocInfo);
+  if (HadMultipleCandidates)
+    DRE->setHadMultipleCandidates(true);
+  ExprResult E = S.Owned(DRE);
+  E = S.DefaultFunctionArrayConversion(E.take());
+  if (E.isInvalid())
+    return ExprError();
+  return move(E);
+}
+
+static bool IsStandardConversion(Sema &S, Expr* From, QualType ToType,
+                                 bool InOverloadResolution,
+                                 StandardConversionSequence &SCS,
+                                 bool CStyle,
+                                 bool AllowObjCWritebackConversion);
+  
+static bool IsTransparentUnionStandardConversion(Sema &S, Expr* From, 
+                                                 QualType &ToType,
+                                                 bool InOverloadResolution,
+                                                 StandardConversionSequence &SCS,
+                                                 bool CStyle);
+static OverloadingResult
+IsUserDefinedConversion(Sema &S, Expr *From, QualType ToType,
+                        UserDefinedConversionSequence& User,
+                        OverloadCandidateSet& Conversions,
+                        bool AllowExplicit);
+
+
+static ImplicitConversionSequence::CompareKind
+CompareStandardConversionSequences(Sema &S,
+                                   const StandardConversionSequence& SCS1,
+                                   const StandardConversionSequence& SCS2);
+
+static ImplicitConversionSequence::CompareKind
+CompareQualificationConversions(Sema &S,
+                                const StandardConversionSequence& SCS1,
+                                const StandardConversionSequence& SCS2);
+
+static ImplicitConversionSequence::CompareKind
+CompareDerivedToBaseConversions(Sema &S,
+                                const StandardConversionSequence& SCS1,
+                                const StandardConversionSequence& SCS2);
+
+
+
+/// GetConversionCategory - Retrieve the implicit conversion
+/// category corresponding to the given implicit conversion kind.
+ImplicitConversionCategory
+GetConversionCategory(ImplicitConversionKind Kind) {
+  static const ImplicitConversionCategory
+    Category[(int)ICK_Num_Conversion_Kinds] = {
+    ICC_Identity,
+    ICC_Lvalue_Transformation,
+    ICC_Lvalue_Transformation,
+    ICC_Lvalue_Transformation,
+    ICC_Identity,
+    ICC_Qualification_Adjustment,
+    ICC_Promotion,
+    ICC_Promotion,
+    ICC_Promotion,
+    ICC_Conversion,
+    ICC_Conversion,
+    ICC_Conversion,
+    ICC_Conversion,
+    ICC_Conversion,
+    ICC_Conversion,
+    ICC_Conversion,
+    ICC_Conversion,
+    ICC_Conversion,
+    ICC_Conversion,
+    ICC_Conversion,
+    ICC_Conversion,
+    ICC_Conversion
+  };
+  return Category[(int)Kind];
+}
+
+/// GetConversionRank - Retrieve the implicit conversion rank
+/// corresponding to the given implicit conversion kind.
+ImplicitConversionRank GetConversionRank(ImplicitConversionKind Kind) {
+  static const ImplicitConversionRank
+    Rank[(int)ICK_Num_Conversion_Kinds] = {
+    ICR_Exact_Match,
+    ICR_Exact_Match,
+    ICR_Exact_Match,
+    ICR_Exact_Match,
+    ICR_Exact_Match,
+    ICR_Exact_Match,
+    ICR_Promotion,
+    ICR_Promotion,
+    ICR_Promotion,
+    ICR_Conversion,
+    ICR_Conversion,
+    ICR_Conversion,
+    ICR_Conversion,
+    ICR_Conversion,
+    ICR_Conversion,
+    ICR_Conversion,
+    ICR_Conversion,
+    ICR_Conversion,
+    ICR_Conversion,
+    ICR_Conversion,
+    ICR_Complex_Real_Conversion,
+    ICR_Conversion,
+    ICR_Conversion,
+    ICR_Writeback_Conversion
+  };
+  return Rank[(int)Kind];
+}
+
+/// GetImplicitConversionName - Return the name of this kind of
+/// implicit conversion.
+const char* GetImplicitConversionName(ImplicitConversionKind Kind) {
+  static const char* const Name[(int)ICK_Num_Conversion_Kinds] = {
+    "No conversion",
+    "Lvalue-to-rvalue",
+    "Array-to-pointer",
+    "Function-to-pointer",
+    "Noreturn adjustment",
+    "Qualification",
+    "Integral promotion",
+    "Floating point promotion",
+    "Complex promotion",
+    "Integral conversion",
+    "Floating conversion",
+    "Complex conversion",
+    "Floating-integral conversion",
+    "Pointer conversion",
+    "Pointer-to-member conversion",
+    "Boolean conversion",
+    "Compatible-types conversion",
+    "Derived-to-base conversion",
+    "Vector conversion",
+    "Vector splat",
+    "Complex-real conversion",
+    "Block Pointer conversion",
+    "Transparent Union Conversion"
+    "Writeback conversion"
+  };
+  return Name[Kind];
+}
+
+/// StandardConversionSequence - Set the standard conversion
+/// sequence to the identity conversion.
+void StandardConversionSequence::setAsIdentityConversion() {
+  First = ICK_Identity;
+  Second = ICK_Identity;
+  Third = ICK_Identity;
+  DeprecatedStringLiteralToCharPtr = false;
+  QualificationIncludesObjCLifetime = false;
+  ReferenceBinding = false;
+  DirectBinding = false;
+  IsLvalueReference = true;
+  BindsToFunctionLvalue = false;
+  BindsToRvalue = false;
+  BindsImplicitObjectArgumentWithoutRefQualifier = false;
+  ObjCLifetimeConversionBinding = false;
+  CopyConstructor = 0;
+}
+
+/// getRank - Retrieve the rank of this standard conversion sequence
+/// (C++ 13.3.3.1.1p3). The rank is the largest rank of each of the
+/// implicit conversions.
+ImplicitConversionRank StandardConversionSequence::getRank() const {
+  ImplicitConversionRank Rank = ICR_Exact_Match;
+  if  (GetConversionRank(First) > Rank)
+    Rank = GetConversionRank(First);
+  if  (GetConversionRank(Second) > Rank)
+    Rank = GetConversionRank(Second);
+  if  (GetConversionRank(Third) > Rank)
+    Rank = GetConversionRank(Third);
+  return Rank;
+}
+
+/// isPointerConversionToBool - Determines whether this conversion is
+/// a conversion of a pointer or pointer-to-member to bool. This is
+/// used as part of the ranking of standard conversion sequences
+/// (C++ 13.3.3.2p4).
+bool StandardConversionSequence::isPointerConversionToBool() const {
+  // Note that FromType has not necessarily been transformed by the
+  // array-to-pointer or function-to-pointer implicit conversions, so
+  // check for their presence as well as checking whether FromType is
+  // a pointer.
+  if (getToType(1)->isBooleanType() &&
+      (getFromType()->isPointerType() ||
+       getFromType()->isObjCObjectPointerType() ||
+       getFromType()->isBlockPointerType() ||
+       getFromType()->isNullPtrType() ||
+       First == ICK_Array_To_Pointer || First == ICK_Function_To_Pointer))
+    return true;
+
+  return false;
+}
+
+/// isPointerConversionToVoidPointer - Determines whether this
+/// conversion is a conversion of a pointer to a void pointer. This is
+/// used as part of the ranking of standard conversion sequences (C++
+/// 13.3.3.2p4).
+bool
+StandardConversionSequence::
+isPointerConversionToVoidPointer(ASTContext& Context) const {
+  QualType FromType = getFromType();
+  QualType ToType = getToType(1);
+
+  // Note that FromType has not necessarily been transformed by the
+  // array-to-pointer implicit conversion, so check for its presence
+  // and redo the conversion to get a pointer.
+  if (First == ICK_Array_To_Pointer)
+    FromType = Context.getArrayDecayedType(FromType);
+
+  if (Second == ICK_Pointer_Conversion && FromType->isAnyPointerType())
+    if (const PointerType* ToPtrType = ToType->getAs<PointerType>())
+      return ToPtrType->getPointeeType()->isVoidType();
+
+  return false;
+}
+
+/// Skip any implicit casts which could be either part of a narrowing conversion
+/// or after one in an implicit conversion.
+static const Expr *IgnoreNarrowingConversion(const Expr *Converted) {
+  while (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(Converted)) {
+    switch (ICE->getCastKind()) {
+    case CK_NoOp:
+    case CK_IntegralCast:
+    case CK_IntegralToBoolean:
+    case CK_IntegralToFloating:
+    case CK_FloatingToIntegral:
+    case CK_FloatingToBoolean:
+    case CK_FloatingCast:
+      Converted = ICE->getSubExpr();
+      continue;
+
+    default:
+      return Converted;
+    }
+  }
+
+  return Converted;
+}
+
+/// Check if this standard conversion sequence represents a narrowing
+/// conversion, according to C++11 [dcl.init.list]p7.
+///
+/// \param Ctx  The AST context.
+/// \param Converted  The result of applying this standard conversion sequence.
+/// \param ConstantValue  If this is an NK_Constant_Narrowing conversion, the
+///        value of the expression prior to the narrowing conversion.
+/// \param ConstantType  If this is an NK_Constant_Narrowing conversion, the
+///        type of the expression prior to the narrowing conversion.
+NarrowingKind
+StandardConversionSequence::getNarrowingKind(ASTContext &Ctx,
+                                             const Expr *Converted,
+                                             APValue &ConstantValue,
+                                             QualType &ConstantType) const {
+  assert(Ctx.getLangOpts().CPlusPlus && "narrowing check outside C++");
+
+  // C++11 [dcl.init.list]p7:
+  //   A narrowing conversion is an implicit conversion ...
+  QualType FromType = getToType(0);
+  QualType ToType = getToType(1);
+  switch (Second) {
+  // -- from a floating-point type to an integer type, or
+  //
+  // -- from an integer type or unscoped enumeration type to a floating-point
+  //    type, except where the source is a constant expression and the actual
+  //    value after conversion will fit into the target type and will produce
+  //    the original value when converted back to the original type, or
+  case ICK_Floating_Integral:
+    if (FromType->isRealFloatingType() && ToType->isIntegralType(Ctx)) {
+      return NK_Type_Narrowing;
+    } else if (FromType->isIntegralType(Ctx) && ToType->isRealFloatingType()) {
+      llvm::APSInt IntConstantValue;
+      const Expr *Initializer = IgnoreNarrowingConversion(Converted);
+      if (Initializer &&
+          Initializer->isIntegerConstantExpr(IntConstantValue, Ctx)) {
+        // Convert the integer to the floating type.
+        llvm::APFloat Result(Ctx.getFloatTypeSemantics(ToType));
+        Result.convertFromAPInt(IntConstantValue, IntConstantValue.isSigned(),
+                                llvm::APFloat::rmNearestTiesToEven);
+        // And back.
+        llvm::APSInt ConvertedValue = IntConstantValue;
+        bool ignored;
+        Result.convertToInteger(ConvertedValue,
+                                llvm::APFloat::rmTowardZero, &ignored);
+        // If the resulting value is different, this was a narrowing conversion.
+        if (IntConstantValue != ConvertedValue) {
+          ConstantValue = APValue(IntConstantValue);
+          ConstantType = Initializer->getType();
+          return NK_Constant_Narrowing;
+        }
+      } else {
+        // Variables are always narrowings.
+        return NK_Variable_Narrowing;
+      }
+    }
+    return NK_Not_Narrowing;
+
+  // -- from long double to double or float, or from double to float, except
+  //    where the source is a constant expression and the actual value after
+  //    conversion is within the range of values that can be represented (even
+  //    if it cannot be represented exactly), or
+  case ICK_Floating_Conversion:
+    if (FromType->isRealFloatingType() && ToType->isRealFloatingType() &&
+        Ctx.getFloatingTypeOrder(FromType, ToType) == 1) {
+      // FromType is larger than ToType.
+      const Expr *Initializer = IgnoreNarrowingConversion(Converted);
+      if (Initializer->isCXX11ConstantExpr(Ctx, &ConstantValue)) {
+        // Constant!
+        assert(ConstantValue.isFloat());
+        llvm::APFloat FloatVal = ConstantValue.getFloat();
+        // Convert the source value into the target type.
+        bool ignored;
+        llvm::APFloat::opStatus ConvertStatus = FloatVal.convert(
+          Ctx.getFloatTypeSemantics(ToType),
+          llvm::APFloat::rmNearestTiesToEven, &ignored);
+        // If there was no overflow, the source value is within the range of
+        // values that can be represented.
+        if (ConvertStatus & llvm::APFloat::opOverflow) {
+          ConstantType = Initializer->getType();
+          return NK_Constant_Narrowing;
+        }
+      } else {
+        return NK_Variable_Narrowing;
+      }
+    }
+    return NK_Not_Narrowing;
+
+  // -- from an integer type or unscoped enumeration type to an integer type
+  //    that cannot represent all the values of the original type, except where
+  //    the source is a constant expression and the actual value after
+  //    conversion will fit into the target type and will produce the original
+  //    value when converted back to the original type.
+  case ICK_Boolean_Conversion:  // Bools are integers too.
+    if (!FromType->isIntegralOrUnscopedEnumerationType()) {
+      // Boolean conversions can be from pointers and pointers to members
+      // [conv.bool], and those aren't considered narrowing conversions.
+      return NK_Not_Narrowing;
+    }  // Otherwise, fall through to the integral case.
+  case ICK_Integral_Conversion: {
+    assert(FromType->isIntegralOrUnscopedEnumerationType());
+    assert(ToType->isIntegralOrUnscopedEnumerationType());
+    const bool FromSigned = FromType->isSignedIntegerOrEnumerationType();
+    const unsigned FromWidth = Ctx.getIntWidth(FromType);
+    const bool ToSigned = ToType->isSignedIntegerOrEnumerationType();
+    const unsigned ToWidth = Ctx.getIntWidth(ToType);
+
+    if (FromWidth > ToWidth ||
+        (FromWidth == ToWidth && FromSigned != ToSigned)) {
+      // Not all values of FromType can be represented in ToType.
+      llvm::APSInt InitializerValue;
+      const Expr *Initializer = IgnoreNarrowingConversion(Converted);
+      if (Initializer->isIntegerConstantExpr(InitializerValue, Ctx)) {
+        ConstantValue = APValue(InitializerValue);
+
+        // Add a bit to the InitializerValue so we don't have to worry about
+        // signed vs. unsigned comparisons.
+        InitializerValue = InitializerValue.extend(
+          InitializerValue.getBitWidth() + 1);
+        // Convert the initializer to and from the target width and signed-ness.
+        llvm::APSInt ConvertedValue = InitializerValue;
+        ConvertedValue = ConvertedValue.trunc(ToWidth);
+        ConvertedValue.setIsSigned(ToSigned);
+        ConvertedValue = ConvertedValue.extend(InitializerValue.getBitWidth());
+        ConvertedValue.setIsSigned(InitializerValue.isSigned());
+        // If the result is different, this was a narrowing conversion.
+        if (ConvertedValue != InitializerValue) {
+          ConstantType = Initializer->getType();
+          return NK_Constant_Narrowing;
+        }
+      } else {
+        // Variables are always narrowings.
+        return NK_Variable_Narrowing;
+      }
+    }
+    return NK_Not_Narrowing;
+  }
+
+  default:
+    // Other kinds of conversions are not narrowings.
+    return NK_Not_Narrowing;
+  }
+}
+
+/// DebugPrint - Print this standard conversion sequence to standard
+/// error. Useful for debugging overloading issues.
+void StandardConversionSequence::DebugPrint() const {
+  raw_ostream &OS = llvm::errs();
+  bool PrintedSomething = false;
+  if (First != ICK_Identity) {
+    OS << GetImplicitConversionName(First);
+    PrintedSomething = true;
+  }
+
+  if (Second != ICK_Identity) {
+    if (PrintedSomething) {
+      OS << " -> ";
+    }
+    OS << GetImplicitConversionName(Second);
+
+    if (CopyConstructor) {
+      OS << " (by copy constructor)";
+    } else if (DirectBinding) {
+      OS << " (direct reference binding)";
+    } else if (ReferenceBinding) {
+      OS << " (reference binding)";
+    }
+    PrintedSomething = true;
+  }
+
+  if (Third != ICK_Identity) {
+    if (PrintedSomething) {
+      OS << " -> ";
+    }
+    OS << GetImplicitConversionName(Third);
+    PrintedSomething = true;
+  }
+
+  if (!PrintedSomething) {
+    OS << "No conversions required";
+  }
+}
+
+/// DebugPrint - Print this user-defined conversion sequence to standard
+/// error. Useful for debugging overloading issues.
+void UserDefinedConversionSequence::DebugPrint() const {
+  raw_ostream &OS = llvm::errs();
+  if (Before.First || Before.Second || Before.Third) {
+    Before.DebugPrint();
+    OS << " -> ";
+  }
+  if (ConversionFunction)
+    OS << '\'' << *ConversionFunction << '\'';
+  else
+    OS << "aggregate initialization";
+  if (After.First || After.Second || After.Third) {
+    OS << " -> ";
+    After.DebugPrint();
+  }
+}
+
+/// DebugPrint - Print this implicit conversion sequence to standard
+/// error. Useful for debugging overloading issues.
+void ImplicitConversionSequence::DebugPrint() const {
+  raw_ostream &OS = llvm::errs();
+  switch (ConversionKind) {
+  case StandardConversion:
+    OS << "Standard conversion: ";
+    Standard.DebugPrint();
+    break;
+  case UserDefinedConversion:
+    OS << "User-defined conversion: ";
+    UserDefined.DebugPrint();
+    break;
+  case EllipsisConversion:
+    OS << "Ellipsis conversion";
+    break;
+  case AmbiguousConversion:
+    OS << "Ambiguous conversion";
+    break;
+  case BadConversion:
+    OS << "Bad conversion";
+    break;
+  }
+
+  OS << "\n";
+}
+
+void AmbiguousConversionSequence::construct() {
+  new (&conversions()) ConversionSet();
+}
+
+void AmbiguousConversionSequence::destruct() {
+  conversions().~ConversionSet();
+}
+
+void
+AmbiguousConversionSequence::copyFrom(const AmbiguousConversionSequence &O) {
+  FromTypePtr = O.FromTypePtr;
+  ToTypePtr = O.ToTypePtr;
+  new (&conversions()) ConversionSet(O.conversions());
+}
+
+namespace {
+  // Structure used by OverloadCandidate::DeductionFailureInfo to store
+  // template parameter and template argument information.
+  struct DFIParamWithArguments {
+    TemplateParameter Param;
+    TemplateArgument FirstArg;
+    TemplateArgument SecondArg;
+  };
+}
+
+/// \brief Convert from Sema's representation of template deduction information
+/// to the form used in overload-candidate information.
+OverloadCandidate::DeductionFailureInfo
+static MakeDeductionFailureInfo(ASTContext &Context,
+                                Sema::TemplateDeductionResult TDK,
+                                TemplateDeductionInfo &Info) {
+  OverloadCandidate::DeductionFailureInfo Result;
+  Result.Result = static_cast<unsigned>(TDK);
+  Result.Data = 0;
+  switch (TDK) {
+  case Sema::TDK_Success:
+  case Sema::TDK_InstantiationDepth:
+  case Sema::TDK_TooManyArguments:
+  case Sema::TDK_TooFewArguments:
+    break;
+
+  case Sema::TDK_Incomplete:
+  case Sema::TDK_InvalidExplicitArguments:
+    Result.Data = Info.Param.getOpaqueValue();
+    break;
+
+  case Sema::TDK_Inconsistent:
+  case Sema::TDK_Underqualified: {
+    // FIXME: Should allocate from normal heap so that we can free this later.
+    DFIParamWithArguments *Saved = new (Context) DFIParamWithArguments;
+    Saved->Param = Info.Param;
+    Saved->FirstArg = Info.FirstArg;
+    Saved->SecondArg = Info.SecondArg;
+    Result.Data = Saved;
+    break;
+  }
+
+  case Sema::TDK_SubstitutionFailure:
+    Result.Data = Info.take();
+    break;
+
+  case Sema::TDK_NonDeducedMismatch:
+  case Sema::TDK_FailedOverloadResolution:
+    break;
+  }
+
+  return Result;
+}
+
+void OverloadCandidate::DeductionFailureInfo::Destroy() {
+  switch (static_cast<Sema::TemplateDeductionResult>(Result)) {
+  case Sema::TDK_Success:
+  case Sema::TDK_InstantiationDepth:
+  case Sema::TDK_Incomplete:
+  case Sema::TDK_TooManyArguments:
+  case Sema::TDK_TooFewArguments:
+  case Sema::TDK_InvalidExplicitArguments:
+    break;
+
+  case Sema::TDK_Inconsistent:
+  case Sema::TDK_Underqualified:
+    // FIXME: Destroy the data?
+    Data = 0;
+    break;
+
+  case Sema::TDK_SubstitutionFailure:
+    // FIXME: Destroy the template arugment list?
+    Data = 0;
+    break;
+
+  // Unhandled
+  case Sema::TDK_NonDeducedMismatch:
+  case Sema::TDK_FailedOverloadResolution:
+    break;
+  }
+}
+
+TemplateParameter
+OverloadCandidate::DeductionFailureInfo::getTemplateParameter() {
+  switch (static_cast<Sema::TemplateDeductionResult>(Result)) {
+  case Sema::TDK_Success:
+  case Sema::TDK_InstantiationDepth:
+  case Sema::TDK_TooManyArguments:
+  case Sema::TDK_TooFewArguments:
+  case Sema::TDK_SubstitutionFailure:
+    return TemplateParameter();
+
+  case Sema::TDK_Incomplete:
+  case Sema::TDK_InvalidExplicitArguments:
+    return TemplateParameter::getFromOpaqueValue(Data);
+
+  case Sema::TDK_Inconsistent:
+  case Sema::TDK_Underqualified:
+    return static_cast<DFIParamWithArguments*>(Data)->Param;
+
+  // Unhandled
+  case Sema::TDK_NonDeducedMismatch:
+  case Sema::TDK_FailedOverloadResolution:
+    break;
+  }
+
+  return TemplateParameter();
+}
+
+TemplateArgumentList *
+OverloadCandidate::DeductionFailureInfo::getTemplateArgumentList() {
+  switch (static_cast<Sema::TemplateDeductionResult>(Result)) {
+    case Sema::TDK_Success:
+    case Sema::TDK_InstantiationDepth:
+    case Sema::TDK_TooManyArguments:
+    case Sema::TDK_TooFewArguments:
+    case Sema::TDK_Incomplete:
+    case Sema::TDK_InvalidExplicitArguments:
+    case Sema::TDK_Inconsistent:
+    case Sema::TDK_Underqualified:
+      return 0;
+
+    case Sema::TDK_SubstitutionFailure:
+      return static_cast<TemplateArgumentList*>(Data);
+
+    // Unhandled
+    case Sema::TDK_NonDeducedMismatch:
+    case Sema::TDK_FailedOverloadResolution:
+      break;
+  }
+
+  return 0;
+}
+
+const TemplateArgument *OverloadCandidate::DeductionFailureInfo::getFirstArg() {
+  switch (static_cast<Sema::TemplateDeductionResult>(Result)) {
+  case Sema::TDK_Success:
+  case Sema::TDK_InstantiationDepth:
+  case Sema::TDK_Incomplete:
+  case Sema::TDK_TooManyArguments:
+  case Sema::TDK_TooFewArguments:
+  case Sema::TDK_InvalidExplicitArguments:
+  case Sema::TDK_SubstitutionFailure:
+    return 0;
+
+  case Sema::TDK_Inconsistent:
+  case Sema::TDK_Underqualified:
+    return &static_cast<DFIParamWithArguments*>(Data)->FirstArg;
+
+  // Unhandled
+  case Sema::TDK_NonDeducedMismatch:
+  case Sema::TDK_FailedOverloadResolution:
+    break;
+  }
+
+  return 0;
+}
+
+const TemplateArgument *
+OverloadCandidate::DeductionFailureInfo::getSecondArg() {
+  switch (static_cast<Sema::TemplateDeductionResult>(Result)) {
+  case Sema::TDK_Success:
+  case Sema::TDK_InstantiationDepth:
+  case Sema::TDK_Incomplete:
+  case Sema::TDK_TooManyArguments:
+  case Sema::TDK_TooFewArguments:
+  case Sema::TDK_InvalidExplicitArguments:
+  case Sema::TDK_SubstitutionFailure:
+    return 0;
+
+  case Sema::TDK_Inconsistent:
+  case Sema::TDK_Underqualified:
+    return &static_cast<DFIParamWithArguments*>(Data)->SecondArg;
+
+  // Unhandled
+  case Sema::TDK_NonDeducedMismatch:
+  case Sema::TDK_FailedOverloadResolution:
+    break;
+  }
+
+  return 0;
+}
+
+void OverloadCandidateSet::clear() {
+  for (iterator i = begin(), e = end(); i != e; ++i)
+    for (unsigned ii = 0, ie = i->NumConversions; ii != ie; ++ii)
+      i->Conversions[ii].~ImplicitConversionSequence();
+  NumInlineSequences = 0;
+  Candidates.clear();
+  Functions.clear();
+}
+
+namespace {
+  class UnbridgedCastsSet {
+    struct Entry {
+      Expr **Addr;
+      Expr *Saved;
+    };
+    SmallVector<Entry, 2> Entries;
+    
+  public:
+    void save(Sema &S, Expr *&E) {
+      assert(E->hasPlaceholderType(BuiltinType::ARCUnbridgedCast));
+      Entry entry = { &E, E };
+      Entries.push_back(entry);
+      E = S.stripARCUnbridgedCast(E);
+    }
+
+    void restore() {
+      for (SmallVectorImpl<Entry>::iterator
+             i = Entries.begin(), e = Entries.end(); i != e; ++i) 
+        *i->Addr = i->Saved;
+    }
+  };
+}
+
+/// checkPlaceholderForOverload - Do any interesting placeholder-like
+/// preprocessing on the given expression.
+///
+/// \param unbridgedCasts a collection to which to add unbridged casts;
+///   without this, they will be immediately diagnosed as errors
+///
+/// Return true on unrecoverable error.
+static bool checkPlaceholderForOverload(Sema &S, Expr *&E,
+                                        UnbridgedCastsSet *unbridgedCasts = 0) {
+  if (const BuiltinType *placeholder =  E->getType()->getAsPlaceholderType()) {
+    // We can't handle overloaded expressions here because overload
+    // resolution might reasonably tweak them.
+    if (placeholder->getKind() == BuiltinType::Overload) return false;
+
+    // If the context potentially accepts unbridged ARC casts, strip
+    // the unbridged cast and add it to the collection for later restoration.
+    if (placeholder->getKind() == BuiltinType::ARCUnbridgedCast &&
+        unbridgedCasts) {
+      unbridgedCasts->save(S, E);
+      return false;
+    }
+
+    // Go ahead and check everything else.
+    ExprResult result = S.CheckPlaceholderExpr(E);
+    if (result.isInvalid())
+      return true;
+
+    E = result.take();
+    return false;
+  }
+
+  // Nothing to do.
+  return false;
+}
+
+/// checkArgPlaceholdersForOverload - Check a set of call operands for
+/// placeholders.
+static bool checkArgPlaceholdersForOverload(Sema &S, Expr **args,
+                                            unsigned numArgs,
+                                            UnbridgedCastsSet &unbridged) {
+  for (unsigned i = 0; i != numArgs; ++i)
+    if (checkPlaceholderForOverload(S, args[i], &unbridged))
+      return true;
+
+  return false;
+}
+
+// IsOverload - Determine whether the given New declaration is an
+// overload of the declarations in Old. This routine returns false if
+// New and Old cannot be overloaded, e.g., if New has the same
+// signature as some function in Old (C++ 1.3.10) or if the Old
+// declarations aren't functions (or function templates) at all. When
+// it does return false, MatchedDecl will point to the decl that New
+// cannot be overloaded with.  This decl may be a UsingShadowDecl on
+// top of the underlying declaration.
+//
+// Example: Given the following input:
+//
+//   void f(int, float); // #1
+//   void f(int, int); // #2
+//   int f(int, int); // #3
+//
+// When we process #1, there is no previous declaration of "f",
+// so IsOverload will not be used.
+//
+// When we process #2, Old contains only the FunctionDecl for #1.  By
+// comparing the parameter types, we see that #1 and #2 are overloaded
+// (since they have different signatures), so this routine returns
+// false; MatchedDecl is unchanged.
+//
+// When we process #3, Old is an overload set containing #1 and #2. We
+// compare the signatures of #3 to #1 (they're overloaded, so we do
+// nothing) and then #3 to #2. Since the signatures of #3 and #2 are
+// identical (return types of functions are not part of the
+// signature), IsOverload returns false and MatchedDecl will be set to
+// point to the FunctionDecl for #2.
+//
+// 'NewIsUsingShadowDecl' indicates that 'New' is being introduced
+// into a class by a using declaration.  The rules for whether to hide
+// shadow declarations ignore some properties which otherwise figure
+// into a function template's signature.
+Sema::OverloadKind
+Sema::CheckOverload(Scope *S, FunctionDecl *New, const LookupResult &Old,
+                    NamedDecl *&Match, bool NewIsUsingDecl) {
+  for (LookupResult::iterator I = Old.begin(), E = Old.end();
+         I != E; ++I) {
+    NamedDecl *OldD = *I;
+
+    bool OldIsUsingDecl = false;
+    if (isa<UsingShadowDecl>(OldD)) {
+      OldIsUsingDecl = true;
+
+      // We can always introduce two using declarations into the same
+      // context, even if they have identical signatures.
+      if (NewIsUsingDecl) continue;
+
+      OldD = cast<UsingShadowDecl>(OldD)->getTargetDecl();
+    }
+
+    // If either declaration was introduced by a using declaration,
+    // we'll need to use slightly different rules for matching.
+    // Essentially, these rules are the normal rules, except that
+    // function templates hide function templates with different
+    // return types or template parameter lists.
+    bool UseMemberUsingDeclRules =
+      (OldIsUsingDecl || NewIsUsingDecl) && CurContext->isRecord();
+
+    if (FunctionTemplateDecl *OldT = dyn_cast<FunctionTemplateDecl>(OldD)) {
+      if (!IsOverload(New, OldT->getTemplatedDecl(), UseMemberUsingDeclRules)) {
+        if (UseMemberUsingDeclRules && OldIsUsingDecl) {
+          HideUsingShadowDecl(S, cast<UsingShadowDecl>(*I));
+          continue;
+        }
+
+        Match = *I;
+        return Ovl_Match;
+      }
+    } else if (FunctionDecl *OldF = dyn_cast<FunctionDecl>(OldD)) {
+      if (!IsOverload(New, OldF, UseMemberUsingDeclRules)) {
+        if (UseMemberUsingDeclRules && OldIsUsingDecl) {
+          HideUsingShadowDecl(S, cast<UsingShadowDecl>(*I));
+          continue;
+        }
+
+        Match = *I;
+        return Ovl_Match;
+      }
+    } else if (isa<UsingDecl>(OldD)) {
+      // We can overload with these, which can show up when doing
+      // redeclaration checks for UsingDecls.
+      assert(Old.getLookupKind() == LookupUsingDeclName);
+    } else if (isa<TagDecl>(OldD)) {
+      // We can always overload with tags by hiding them.
+    } else if (isa<UnresolvedUsingValueDecl>(OldD)) {
+      // Optimistically assume that an unresolved using decl will
+      // overload; if it doesn't, we'll have to diagnose during
+      // template instantiation.
+    } else {
+      // (C++ 13p1):
+      //   Only function declarations can be overloaded; object and type
+      //   declarations cannot be overloaded.
+      Match = *I;
+      return Ovl_NonFunction;
+    }
+  }
+
+  return Ovl_Overload;
+}
+
+bool Sema::IsOverload(FunctionDecl *New, FunctionDecl *Old,
+                      bool UseUsingDeclRules) {
+  // If both of the functions are extern "C", then they are not
+  // overloads.
+  if (Old->isExternC() && New->isExternC())
+    return false;
+
+  FunctionTemplateDecl *OldTemplate = Old->getDescribedFunctionTemplate();
+  FunctionTemplateDecl *NewTemplate = New->getDescribedFunctionTemplate();
+
+  // C++ [temp.fct]p2:
+  //   A function template can be overloaded with other function templates
+  //   and with normal (non-template) functions.
+  if ((OldTemplate == 0) != (NewTemplate == 0))
+    return true;
+
+  // Is the function New an overload of the function Old?
+  QualType OldQType = Context.getCanonicalType(Old->getType());
+  QualType NewQType = Context.getCanonicalType(New->getType());
+
+  // Compare the signatures (C++ 1.3.10) of the two functions to
+  // determine whether they are overloads. If we find any mismatch
+  // in the signature, they are overloads.
+
+  // If either of these functions is a K&R-style function (no
+  // prototype), then we consider them to have matching signatures.
+  if (isa<FunctionNoProtoType>(OldQType.getTypePtr()) ||
+      isa<FunctionNoProtoType>(NewQType.getTypePtr()))
+    return false;
+
+  const FunctionProtoType* OldType = cast<FunctionProtoType>(OldQType);
+  const FunctionProtoType* NewType = cast<FunctionProtoType>(NewQType);
+
+  // The signature of a function includes the types of its
+  // parameters (C++ 1.3.10), which includes the presence or absence
+  // of the ellipsis; see C++ DR 357).
+  if (OldQType != NewQType &&
+      (OldType->getNumArgs() != NewType->getNumArgs() ||
+       OldType->isVariadic() != NewType->isVariadic() ||
+       !FunctionArgTypesAreEqual(OldType, NewType)))
+    return true;
+
+  // C++ [temp.over.link]p4:
+  //   The signature of a function template consists of its function
+  //   signature, its return type and its template parameter list. The names
+  //   of the template parameters are significant only for establishing the
+  //   relationship between the template parameters and the rest of the
+  //   signature.
+  //
+  // We check the return type and template parameter lists for function
+  // templates first; the remaining checks follow.
+  //
+  // However, we don't consider either of these when deciding whether
+  // a member introduced by a shadow declaration is hidden.
+  if (!UseUsingDeclRules && NewTemplate &&
+      (!TemplateParameterListsAreEqual(NewTemplate->getTemplateParameters(),
+                                       OldTemplate->getTemplateParameters(),
+                                       false, TPL_TemplateMatch) ||
+       OldType->getResultType() != NewType->getResultType()))
+    return true;
+
+  // If the function is a class member, its signature includes the
+  // cv-qualifiers (if any) and ref-qualifier (if any) on the function itself.
+  //
+  // As part of this, also check whether one of the member functions
+  // is static, in which case they are not overloads (C++
+  // 13.1p2). While not part of the definition of the signature,
+  // this check is important to determine whether these functions
+  // can be overloaded.
+  CXXMethodDecl* OldMethod = dyn_cast<CXXMethodDecl>(Old);
+  CXXMethodDecl* NewMethod = dyn_cast<CXXMethodDecl>(New);
+  if (OldMethod && NewMethod &&
+      !OldMethod->isStatic() && !NewMethod->isStatic() &&
+      (OldMethod->getTypeQualifiers() != NewMethod->getTypeQualifiers() ||
+       OldMethod->getRefQualifier() != NewMethod->getRefQualifier())) {
+    if (!UseUsingDeclRules &&
+        OldMethod->getRefQualifier() != NewMethod->getRefQualifier() &&
+        (OldMethod->getRefQualifier() == RQ_None ||
+         NewMethod->getRefQualifier() == RQ_None)) {
+      // C++0x [over.load]p2:
+      //   - Member function declarations with the same name and the same
+      //     parameter-type-list as well as member function template
+      //     declarations with the same name, the same parameter-type-list, and
+      //     the same template parameter lists cannot be overloaded if any of
+      //     them, but not all, have a ref-qualifier (8.3.5).
+      Diag(NewMethod->getLocation(), diag::err_ref_qualifier_overload)
+        << NewMethod->getRefQualifier() << OldMethod->getRefQualifier();
+      Diag(OldMethod->getLocation(), diag::note_previous_declaration);
+    }
+
+    return true;
+  }
+
+  // The signatures match; this is not an overload.
+  return false;
+}
+
+/// \brief Checks availability of the function depending on the current
+/// function context. Inside an unavailable function, unavailability is ignored.
+///
+/// \returns true if \arg FD is unavailable and current context is inside
+/// an available function, false otherwise.
+bool Sema::isFunctionConsideredUnavailable(FunctionDecl *FD) {
+  return FD->isUnavailable() && !cast<Decl>(CurContext)->isUnavailable();
+}
+
+/// \brief Tries a user-defined conversion from From to ToType.
+///
+/// Produces an implicit conversion sequence for when a standard conversion
+/// is not an option. See TryImplicitConversion for more information.
+static ImplicitConversionSequence
+TryUserDefinedConversion(Sema &S, Expr *From, QualType ToType,
+                         bool SuppressUserConversions,
+                         bool AllowExplicit,
+                         bool InOverloadResolution,
+                         bool CStyle,
+                         bool AllowObjCWritebackConversion) {
+  ImplicitConversionSequence ICS;
+
+  if (SuppressUserConversions) {
+    // We're not in the case above, so there is no conversion that
+    // we can perform.
+    ICS.setBad(BadConversionSequence::no_conversion, From, ToType);
+    return ICS;
+  }
+
+  // Attempt user-defined conversion.
+  OverloadCandidateSet Conversions(From->getExprLoc());
+  OverloadingResult UserDefResult
+    = IsUserDefinedConversion(S, From, ToType, ICS.UserDefined, Conversions,
+                              AllowExplicit);
+
+  if (UserDefResult == OR_Success) {
+    ICS.setUserDefined();
+    // C++ [over.ics.user]p4:
+    //   A conversion of an expression of class type to the same class
+    //   type is given Exact Match rank, and a conversion of an
+    //   expression of class type to a base class of that type is
+    //   given Conversion rank, in spite of the fact that a copy
+    //   constructor (i.e., a user-defined conversion function) is
+    //   called for those cases.
+    if (CXXConstructorDecl *Constructor
+          = dyn_cast<CXXConstructorDecl>(ICS.UserDefined.ConversionFunction)) {
+      QualType FromCanon
+        = S.Context.getCanonicalType(From->getType().getUnqualifiedType());
+      QualType ToCanon
+        = S.Context.getCanonicalType(ToType).getUnqualifiedType();
+      if (Constructor->isCopyConstructor() &&
+          (FromCanon == ToCanon || S.IsDerivedFrom(FromCanon, ToCanon))) {
+        // Turn this into a "standard" conversion sequence, so that it
+        // gets ranked with standard conversion sequences.
+        ICS.setStandard();
+        ICS.Standard.setAsIdentityConversion();
+        ICS.Standard.setFromType(From->getType());
+        ICS.Standard.setAllToTypes(ToType);
+        ICS.Standard.CopyConstructor = Constructor;
+        if (ToCanon != FromCanon)
+          ICS.Standard.Second = ICK_Derived_To_Base;
+      }
+    }
+
+    // C++ [over.best.ics]p4:
+    //   However, when considering the argument of a user-defined
+    //   conversion function that is a candidate by 13.3.1.3 when
+    //   invoked for the copying of the temporary in the second step
+    //   of a class copy-initialization, or by 13.3.1.4, 13.3.1.5, or
+    //   13.3.1.6 in all cases, only standard conversion sequences and
+    //   ellipsis conversion sequences are allowed.
+    if (SuppressUserConversions && ICS.isUserDefined()) {
+      ICS.setBad(BadConversionSequence::suppressed_user, From, ToType);
+    }
+  } else if (UserDefResult == OR_Ambiguous && !SuppressUserConversions) {
+    ICS.setAmbiguous();
+    ICS.Ambiguous.setFromType(From->getType());
+    ICS.Ambiguous.setToType(ToType);
+    for (OverloadCandidateSet::iterator Cand = Conversions.begin();
+         Cand != Conversions.end(); ++Cand)
+      if (Cand->Viable)
+        ICS.Ambiguous.addConversion(Cand->Function);
+  } else {
+    ICS.setBad(BadConversionSequence::no_conversion, From, ToType);
+  }
+
+  return ICS;
+}
+
+/// TryImplicitConversion - Attempt to perform an implicit conversion
+/// from the given expression (Expr) to the given type (ToType). This
+/// function returns an implicit conversion sequence that can be used
+/// to perform the initialization. Given
+///
+///   void f(float f);
+///   void g(int i) { f(i); }
+///
+/// this routine would produce an implicit conversion sequence to
+/// describe the initialization of f from i, which will be a standard
+/// conversion sequence containing an lvalue-to-rvalue conversion (C++
+/// 4.1) followed by a floating-integral conversion (C++ 4.9).
+//
+/// Note that this routine only determines how the conversion can be
+/// performed; it does not actually perform the conversion. As such,
+/// it will not produce any diagnostics if no conversion is available,
+/// but will instead return an implicit conversion sequence of kind
+/// "BadConversion".
+///
+/// If @p SuppressUserConversions, then user-defined conversions are
+/// not permitted.
+/// If @p AllowExplicit, then explicit user-defined conversions are
+/// permitted.
+///
+/// \param AllowObjCWritebackConversion Whether we allow the Objective-C
+/// writeback conversion, which allows __autoreleasing id* parameters to
+/// be initialized with __strong id* or __weak id* arguments.
+static ImplicitConversionSequence
+TryImplicitConversion(Sema &S, Expr *From, QualType ToType,
+                      bool SuppressUserConversions,
+                      bool AllowExplicit,
+                      bool InOverloadResolution,
+                      bool CStyle,
+                      bool AllowObjCWritebackConversion) {
+  ImplicitConversionSequence ICS;
+  if (IsStandardConversion(S, From, ToType, InOverloadResolution,
+                           ICS.Standard, CStyle, AllowObjCWritebackConversion)){
+    ICS.setStandard();
+    return ICS;
+  }
+
+  if (!S.getLangOpts().CPlusPlus) {
+    ICS.setBad(BadConversionSequence::no_conversion, From, ToType);
+    return ICS;
+  }
+
+  // C++ [over.ics.user]p4:
+  //   A conversion of an expression of class type to the same class
+  //   type is given Exact Match rank, and a conversion of an
+  //   expression of class type to a base class of that type is
+  //   given Conversion rank, in spite of the fact that a copy/move
+  //   constructor (i.e., a user-defined conversion function) is
+  //   called for those cases.
+  QualType FromType = From->getType();
+  if (ToType->getAs<RecordType>() && FromType->getAs<RecordType>() &&
+      (S.Context.hasSameUnqualifiedType(FromType, ToType) ||
+       S.IsDerivedFrom(FromType, ToType))) {
+    ICS.setStandard();
+    ICS.Standard.setAsIdentityConversion();
+    ICS.Standard.setFromType(FromType);
+    ICS.Standard.setAllToTypes(ToType);
+
+    // We don't actually check at this point whether there is a valid
+    // copy/move constructor, since overloading just assumes that it
+    // exists. When we actually perform initialization, we'll find the
+    // appropriate constructor to copy the returned object, if needed.
+    ICS.Standard.CopyConstructor = 0;
+
+    // Determine whether this is considered a derived-to-base conversion.
+    if (!S.Context.hasSameUnqualifiedType(FromType, ToType))
+      ICS.Standard.Second = ICK_Derived_To_Base;
+
+    return ICS;
+  }
+
+  return TryUserDefinedConversion(S, From, ToType, SuppressUserConversions,
+                                  AllowExplicit, InOverloadResolution, CStyle,
+                                  AllowObjCWritebackConversion);
+}
+
+ImplicitConversionSequence
+Sema::TryImplicitConversion(Expr *From, QualType ToType,
+                            bool SuppressUserConversions,
+                            bool AllowExplicit,
+                            bool InOverloadResolution,
+                            bool CStyle,
+                            bool AllowObjCWritebackConversion) {
+  return clang::TryImplicitConversion(*this, From, ToType, 
+                                      SuppressUserConversions, AllowExplicit,
+                                      InOverloadResolution, CStyle, 
+                                      AllowObjCWritebackConversion);
+}
+
+/// PerformImplicitConversion - Perform an implicit conversion of the
+/// expression From to the type ToType. Returns the
+/// converted expression. Flavor is the kind of conversion we're
+/// performing, used in the error message. If @p AllowExplicit,
+/// explicit user-defined conversions are permitted.
+ExprResult
+Sema::PerformImplicitConversion(Expr *From, QualType ToType,
+                                AssignmentAction Action, bool AllowExplicit) {
+  ImplicitConversionSequence ICS;
+  return PerformImplicitConversion(From, ToType, Action, AllowExplicit, ICS);
+}
+
+ExprResult
+Sema::PerformImplicitConversion(Expr *From, QualType ToType,
+                                AssignmentAction Action, bool AllowExplicit,
+                                ImplicitConversionSequence& ICS) {
+  if (checkPlaceholderForOverload(*this, From))
+    return ExprError();
+
+  // Objective-C ARC: Determine whether we will allow the writeback conversion.
+  bool AllowObjCWritebackConversion
+    = getLangOpts().ObjCAutoRefCount && 
+      (Action == AA_Passing || Action == AA_Sending);
+
+  ICS = clang::TryImplicitConversion(*this, From, ToType,
+                                     /*SuppressUserConversions=*/false,
+                                     AllowExplicit,
+                                     /*InOverloadResolution=*/false,
+                                     /*CStyle=*/false,
+                                     AllowObjCWritebackConversion);
+  return PerformImplicitConversion(From, ToType, ICS, Action);
+}
+
+/// \brief Determine whether the conversion from FromType to ToType is a valid
+/// conversion that strips "noreturn" off the nested function type.
+bool Sema::IsNoReturnConversion(QualType FromType, QualType ToType,
+                                QualType &ResultTy) {
+  if (Context.hasSameUnqualifiedType(FromType, ToType))
+    return false;
+
+  // Permit the conversion F(t __attribute__((noreturn))) -> F(t)
+  // where F adds one of the following at most once:
+  //   - a pointer
+  //   - a member pointer
+  //   - a block pointer
+  CanQualType CanTo = Context.getCanonicalType(ToType);
+  CanQualType CanFrom = Context.getCanonicalType(FromType);
+  Type::TypeClass TyClass = CanTo->getTypeClass();
+  if (TyClass != CanFrom->getTypeClass()) return false;
+  if (TyClass != Type::FunctionProto && TyClass != Type::FunctionNoProto) {
+    if (TyClass == Type::Pointer) {
+      CanTo = CanTo.getAs<PointerType>()->getPointeeType();
+      CanFrom = CanFrom.getAs<PointerType>()->getPointeeType();
+    } else if (TyClass == Type::BlockPointer) {
+      CanTo = CanTo.getAs<BlockPointerType>()->getPointeeType();
+      CanFrom = CanFrom.getAs<BlockPointerType>()->getPointeeType();
+    } else if (TyClass == Type::MemberPointer) {
+      CanTo = CanTo.getAs<MemberPointerType>()->getPointeeType();
+      CanFrom = CanFrom.getAs<MemberPointerType>()->getPointeeType();
+    } else {
+      return false;
+    }
+
+    TyClass = CanTo->getTypeClass();
+    if (TyClass != CanFrom->getTypeClass()) return false;
+    if (TyClass != Type::FunctionProto && TyClass != Type::FunctionNoProto)
+      return false;
+  }
+
+  const FunctionType *FromFn = cast<FunctionType>(CanFrom);
+  FunctionType::ExtInfo EInfo = FromFn->getExtInfo();
+  if (!EInfo.getNoReturn()) return false;
+
+  FromFn = Context.adjustFunctionType(FromFn, EInfo.withNoReturn(false));
+  assert(QualType(FromFn, 0).isCanonical());
+  if (QualType(FromFn, 0) != CanTo) return false;
+
+  ResultTy = ToType;
+  return true;
+}
+
+/// \brief Determine whether the conversion from FromType to ToType is a valid
+/// vector conversion.
+///
+/// \param ICK Will be set to the vector conversion kind, if this is a vector
+/// conversion.
+static bool IsVectorConversion(ASTContext &Context, QualType FromType,
+                               QualType ToType, ImplicitConversionKind &ICK) {
+  // We need at least one of these types to be a vector type to have a vector
+  // conversion.
+  if (!ToType->isVectorType() && !FromType->isVectorType())
+    return false;
+
+  // Identical types require no conversions.
+  if (Context.hasSameUnqualifiedType(FromType, ToType))
+    return false;
+
+  // There are no conversions between extended vector types, only identity.
+  if (ToType->isExtVectorType()) {
+    // There are no conversions between extended vector types other than the
+    // identity conversion.
+    if (FromType->isExtVectorType())
+      return false;
+
+    // Vector splat from any arithmetic type to a vector.
+    if (FromType->isArithmeticType()) {
+      ICK = ICK_Vector_Splat;
+      return true;
+    }
+  }
+
+  // We can perform the conversion between vector types in the following cases:
+  // 1)vector types are equivalent AltiVec and GCC vector types
+  // 2)lax vector conversions are permitted and the vector types are of the
+  //   same size
+  if (ToType->isVectorType() && FromType->isVectorType()) {
+    if (Context.areCompatibleVectorTypes(FromType, ToType) ||
+        (Context.getLangOpts().LaxVectorConversions &&
+         (Context.getTypeSize(FromType) == Context.getTypeSize(ToType)))) {
+      ICK = ICK_Vector_Conversion;
+      return true;
+    }
+  }
+
+  return false;
+}
+
+static bool tryAtomicConversion(Sema &S, Expr *From, QualType ToType,
+                                bool InOverloadResolution,
+                                StandardConversionSequence &SCS,
+                                bool CStyle);
+  
+/// IsStandardConversion - Determines whether there is a standard
+/// conversion sequence (C++ [conv], C++ [over.ics.scs]) from the
+/// expression From to the type ToType. Standard conversion sequences
+/// only consider non-class types; for conversions that involve class
+/// types, use TryImplicitConversion. If a conversion exists, SCS will
+/// contain the standard conversion sequence required to perform this
+/// conversion and this routine will return true. Otherwise, this
+/// routine will return false and the value of SCS is unspecified.
+static bool IsStandardConversion(Sema &S, Expr* From, QualType ToType,
+                                 bool InOverloadResolution,
+                                 StandardConversionSequence &SCS,
+                                 bool CStyle,
+                                 bool AllowObjCWritebackConversion) {
+  QualType FromType = From->getType();
+
+  // Standard conversions (C++ [conv])
+  SCS.setAsIdentityConversion();
+  SCS.DeprecatedStringLiteralToCharPtr = false;
+  SCS.IncompatibleObjC = false;
+  SCS.setFromType(FromType);
+  SCS.CopyConstructor = 0;
+
+  // There are no standard conversions for class types in C++, so
+  // abort early. When overloading in C, however, we do permit
+  if (FromType->isRecordType() || ToType->isRecordType()) {
+    if (S.getLangOpts().CPlusPlus)
+      return false;
+
+    // When we're overloading in C, we allow, as standard conversions,
+  }
+
+  // The first conversion can be an lvalue-to-rvalue conversion,
+  // array-to-pointer conversion, or function-to-pointer conversion
+  // (C++ 4p1).
+
+  if (FromType == S.Context.OverloadTy) {
+    DeclAccessPair AccessPair;
+    if (FunctionDecl *Fn
+          = S.ResolveAddressOfOverloadedFunction(From, ToType, false,
+                                                 AccessPair)) {
+      // We were able to resolve the address of the overloaded function,
+      // so we can convert to the type of that function.
+      FromType = Fn->getType();
+
+      // we can sometimes resolve &foo<int> regardless of ToType, so check
+      // if the type matches (identity) or we are converting to bool
+      if (!S.Context.hasSameUnqualifiedType(
+                      S.ExtractUnqualifiedFunctionType(ToType), FromType)) {
+        QualType resultTy;
+        // if the function type matches except for [[noreturn]], it's ok
+        if (!S.IsNoReturnConversion(FromType,
+              S.ExtractUnqualifiedFunctionType(ToType), resultTy))
+          // otherwise, only a boolean conversion is standard   
+          if (!ToType->isBooleanType()) 
+            return false; 
+      }
+
+      // Check if the "from" expression is taking the address of an overloaded
+      // function and recompute the FromType accordingly. Take advantage of the
+      // fact that non-static member functions *must* have such an address-of
+      // expression. 
+      CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(Fn);
+      if (Method && !Method->isStatic()) {
+        assert(isa<UnaryOperator>(From->IgnoreParens()) &&
+               "Non-unary operator on non-static member address");
+        assert(cast<UnaryOperator>(From->IgnoreParens())->getOpcode()
+               == UO_AddrOf &&
+               "Non-address-of operator on non-static member address");
+        const Type *ClassType
+          = S.Context.getTypeDeclType(Method->getParent()).getTypePtr();
+        FromType = S.Context.getMemberPointerType(FromType, ClassType);
+      } else if (isa<UnaryOperator>(From->IgnoreParens())) {
+        assert(cast<UnaryOperator>(From->IgnoreParens())->getOpcode() ==
+               UO_AddrOf &&
+               "Non-address-of operator for overloaded function expression");
+        FromType = S.Context.getPointerType(FromType);
+      }
+
+      // Check that we've computed the proper type after overload resolution.
+      assert(S.Context.hasSameType(
+        FromType,
+        S.FixOverloadedFunctionReference(From, AccessPair, Fn)->getType()));
+    } else {
+      return false;
+    }
+  }
+  // Lvalue-to-rvalue conversion (C++11 4.1):
+  //   A glvalue (3.10) of a non-function, non-array type T can
+  //   be converted to a prvalue.
+  bool argIsLValue = From->isGLValue();
+  if (argIsLValue &&
+      !FromType->isFunctionType() && !FromType->isArrayType() &&
+      S.Context.getCanonicalType(FromType) != S.Context.OverloadTy) {
+    SCS.First = ICK_Lvalue_To_Rvalue;
+
+    // C11 6.3.2.1p2:
+    //   ... if the lvalue has atomic type, the value has the non-atomic version 
+    //   of the type of the lvalue ...
+    if (const AtomicType *Atomic = FromType->getAs<AtomicType>())
+      FromType = Atomic->getValueType();
+
+    // If T is a non-class type, the type of the rvalue is the
+    // cv-unqualified version of T. Otherwise, the type of the rvalue
+    // is T (C++ 4.1p1). C++ can't get here with class types; in C, we
+    // just strip the qualifiers because they don't matter.
+    FromType = FromType.getUnqualifiedType();
+  } else if (FromType->isArrayType()) {
+    // Array-to-pointer conversion (C++ 4.2)
+    SCS.First = ICK_Array_To_Pointer;
+
+    // An lvalue or rvalue of type "array of N T" or "array of unknown
+    // bound of T" can be converted to an rvalue of type "pointer to
+    // T" (C++ 4.2p1).
+    FromType = S.Context.getArrayDecayedType(FromType);
+
+    if (S.IsStringLiteralToNonConstPointerConversion(From, ToType)) {
+      // This conversion is deprecated. (C++ D.4).
+      SCS.DeprecatedStringLiteralToCharPtr = true;
+
+      // For the purpose of ranking in overload resolution
+      // (13.3.3.1.1), this conversion is considered an
+      // array-to-pointer conversion followed by a qualification
+      // conversion (4.4). (C++ 4.2p2)
+      SCS.Second = ICK_Identity;
+      SCS.Third = ICK_Qualification;
+      SCS.QualificationIncludesObjCLifetime = false;
+      SCS.setAllToTypes(FromType);
+      return true;
+    }
+  } else if (FromType->isFunctionType() && argIsLValue) {
+    // Function-to-pointer conversion (C++ 4.3).
+    SCS.First = ICK_Function_To_Pointer;
+
+    // An lvalue of function type T can be converted to an rvalue of
+    // type "pointer to T." The result is a pointer to the
+    // function. (C++ 4.3p1).
+    FromType = S.Context.getPointerType(FromType);
+  } else {
+    // We don't require any conversions for the first step.
+    SCS.First = ICK_Identity;
+  }
+  SCS.setToType(0, FromType);
+
+  // The second conversion can be an integral promotion, floating
+  // point promotion, integral conversion, floating point conversion,
+  // floating-integral conversion, pointer conversion,
+  // pointer-to-member conversion, or boolean conversion (C++ 4p1).
+  // For overloading in C, this can also be a "compatible-type"
+  // conversion.
+  bool IncompatibleObjC = false;
+  ImplicitConversionKind SecondICK = ICK_Identity;
+  if (S.Context.hasSameUnqualifiedType(FromType, ToType)) {
+    // The unqualified versions of the types are the same: there's no
+    // conversion to do.
+    SCS.Second = ICK_Identity;
+  } else if (S.IsIntegralPromotion(From, FromType, ToType)) {
+    // Integral promotion (C++ 4.5).
+    SCS.Second = ICK_Integral_Promotion;
+    FromType = ToType.getUnqualifiedType();
+  } else if (S.IsFloatingPointPromotion(FromType, ToType)) {
+    // Floating point promotion (C++ 4.6).
+    SCS.Second = ICK_Floating_Promotion;
+    FromType = ToType.getUnqualifiedType();
+  } else if (S.IsComplexPromotion(FromType, ToType)) {
+    // Complex promotion (Clang extension)
+    SCS.Second = ICK_Complex_Promotion;
+    FromType = ToType.getUnqualifiedType();
+  } else if (ToType->isBooleanType() &&
+             (FromType->isArithmeticType() ||
+              FromType->isAnyPointerType() ||
+              FromType->isBlockPointerType() ||
+              FromType->isMemberPointerType() ||
+              FromType->isNullPtrType())) {
+    // Boolean conversions (C++ 4.12).
+    SCS.Second = ICK_Boolean_Conversion;
+    FromType = S.Context.BoolTy;
+  } else if (FromType->isIntegralOrUnscopedEnumerationType() &&
+             ToType->isIntegralType(S.Context)) {
+    // Integral conversions (C++ 4.7).
+    SCS.Second = ICK_Integral_Conversion;
+    FromType = ToType.getUnqualifiedType();
+  } else if (FromType->isAnyComplexType() && ToType->isComplexType()) {
+    // Complex conversions (C99 6.3.1.6)
+    SCS.Second = ICK_Complex_Conversion;
+    FromType = ToType.getUnqualifiedType();
+  } else if ((FromType->isAnyComplexType() && ToType->isArithmeticType()) ||
+             (ToType->isAnyComplexType() && FromType->isArithmeticType())) {
+    // Complex-real conversions (C99 6.3.1.7)
+    SCS.Second = ICK_Complex_Real;
+    FromType = ToType.getUnqualifiedType();
+  } else if (FromType->isRealFloatingType() && ToType->isRealFloatingType()) {
+    // Floating point conversions (C++ 4.8).
+    SCS.Second = ICK_Floating_Conversion;
+    FromType = ToType.getUnqualifiedType();
+  } else if ((FromType->isRealFloatingType() &&
+              ToType->isIntegralType(S.Context)) ||
+             (FromType->isIntegralOrUnscopedEnumerationType() &&
+              ToType->isRealFloatingType())) {
+    // Floating-integral conversions (C++ 4.9).
+    SCS.Second = ICK_Floating_Integral;
+    FromType = ToType.getUnqualifiedType();
+  } else if (S.IsBlockPointerConversion(FromType, ToType, FromType)) {
+    SCS.Second = ICK_Block_Pointer_Conversion;
+  } else if (AllowObjCWritebackConversion &&
+             S.isObjCWritebackConversion(FromType, ToType, FromType)) {
+    SCS.Second = ICK_Writeback_Conversion;
+  } else if (S.IsPointerConversion(From, FromType, ToType, InOverloadResolution,
+                                   FromType, IncompatibleObjC)) {
+    // Pointer conversions (C++ 4.10).
+    SCS.Second = ICK_Pointer_Conversion;
+    SCS.IncompatibleObjC = IncompatibleObjC;
+    FromType = FromType.getUnqualifiedType();
+  } else if (S.IsMemberPointerConversion(From, FromType, ToType,
+                                         InOverloadResolution, FromType)) {
+    // Pointer to member conversions (4.11).
+    SCS.Second = ICK_Pointer_Member;
+  } else if (IsVectorConversion(S.Context, FromType, ToType, SecondICK)) {
+    SCS.Second = SecondICK;
+    FromType = ToType.getUnqualifiedType();
+  } else if (!S.getLangOpts().CPlusPlus &&
+             S.Context.typesAreCompatible(ToType, FromType)) {
+    // Compatible conversions (Clang extension for C function overloading)
+    SCS.Second = ICK_Compatible_Conversion;
+    FromType = ToType.getUnqualifiedType();
+  } else if (S.IsNoReturnConversion(FromType, ToType, FromType)) {
+    // Treat a conversion that strips "noreturn" as an identity conversion.
+    SCS.Second = ICK_NoReturn_Adjustment;
+  } else if (IsTransparentUnionStandardConversion(S, From, ToType,
+                                             InOverloadResolution,
+                                             SCS, CStyle)) {
+    SCS.Second = ICK_TransparentUnionConversion;
+    FromType = ToType;
+  } else if (tryAtomicConversion(S, From, ToType, InOverloadResolution, SCS,
+                                 CStyle)) {
+    // tryAtomicConversion has updated the standard conversion sequence
+    // appropriately.
+    return true;
+  } else {
+    // No second conversion required.
+    SCS.Second = ICK_Identity;
+  }
+  SCS.setToType(1, FromType);
+
+  QualType CanonFrom;
+  QualType CanonTo;
+  // The third conversion can be a qualification conversion (C++ 4p1).
+  bool ObjCLifetimeConversion;
+  if (S.IsQualificationConversion(FromType, ToType, CStyle, 
+                                  ObjCLifetimeConversion)) {
+    SCS.Third = ICK_Qualification;
+    SCS.QualificationIncludesObjCLifetime = ObjCLifetimeConversion;
+    FromType = ToType;
+    CanonFrom = S.Context.getCanonicalType(FromType);
+    CanonTo = S.Context.getCanonicalType(ToType);
+  } else {
+    // No conversion required
+    SCS.Third = ICK_Identity;
+
+    // C++ [over.best.ics]p6:
+    //   [...] Any difference in top-level cv-qualification is
+    //   subsumed by the initialization itself and does not constitute
+    //   a conversion. [...]
+    CanonFrom = S.Context.getCanonicalType(FromType);
+    CanonTo = S.Context.getCanonicalType(ToType);
+    if (CanonFrom.getLocalUnqualifiedType()
+                                       == CanonTo.getLocalUnqualifiedType() &&
+        (CanonFrom.getLocalCVRQualifiers() != CanonTo.getLocalCVRQualifiers()
+         || CanonFrom.getObjCGCAttr() != CanonTo.getObjCGCAttr()
+         || CanonFrom.getObjCLifetime() != CanonTo.getObjCLifetime())) {
+      FromType = ToType;
+      CanonFrom = CanonTo;
+    }
+  }
+  SCS.setToType(2, FromType);
+
+  // If we have not converted the argument type to the parameter type,
+  // this is a bad conversion sequence.
+  if (CanonFrom != CanonTo)
+    return false;
+
+  return true;
+}
+  
+static bool
+IsTransparentUnionStandardConversion(Sema &S, Expr* From, 
+                                     QualType &ToType,
+                                     bool InOverloadResolution,
+                                     StandardConversionSequence &SCS,
+                                     bool CStyle) {
+    
+  const RecordType *UT = ToType->getAsUnionType();
+  if (!UT || !UT->getDecl()->hasAttr<TransparentUnionAttr>())
+    return false;
+  // The field to initialize within the transparent union.
+  RecordDecl *UD = UT->getDecl();
+  // It's compatible if the expression matches any of the fields.
+  for (RecordDecl::field_iterator it = UD->field_begin(),
+       itend = UD->field_end();
+       it != itend; ++it) {
+    if (IsStandardConversion(S, From, it->getType(), InOverloadResolution, SCS,
+                             CStyle, /*ObjCWritebackConversion=*/false)) {
+      ToType = it->getType();
+      return true;
+    }
+  }
+  return false;
+}
+
+/// IsIntegralPromotion - Determines whether the conversion from the
+/// expression From (whose potentially-adjusted type is FromType) to
+/// ToType is an integral promotion (C++ 4.5). If so, returns true and
+/// sets PromotedType to the promoted type.
+bool Sema::IsIntegralPromotion(Expr *From, QualType FromType, QualType ToType) {
+  const BuiltinType *To = ToType->getAs<BuiltinType>();
+  // All integers are built-in.
+  if (!To) {
+    return false;
+  }
+
+  // An rvalue of type char, signed char, unsigned char, short int, or
+  // unsigned short int can be converted to an rvalue of type int if
+  // int can represent all the values of the source type; otherwise,
+  // the source rvalue can be converted to an rvalue of type unsigned
+  // int (C++ 4.5p1).
+  if (FromType->isPromotableIntegerType() && !FromType->isBooleanType() &&
+      !FromType->isEnumeralType()) {
+    if (// We can promote any signed, promotable integer type to an int
+        (FromType->isSignedIntegerType() ||
+         // We can promote any unsigned integer type whose size is
+         // less than int to an int.
+         (!FromType->isSignedIntegerType() &&
+          Context.getTypeSize(FromType) < Context.getTypeSize(ToType)))) {
+      return To->getKind() == BuiltinType::Int;
+    }
+
+    return To->getKind() == BuiltinType::UInt;
+  }
+
+  // C++0x [conv.prom]p3:
+  //   A prvalue of an unscoped enumeration type whose underlying type is not
+  //   fixed (7.2) can be converted to an rvalue a prvalue of the first of the
+  //   following types that can represent all the values of the enumeration
+  //   (i.e., the values in the range bmin to bmax as described in 7.2): int,
+  //   unsigned int, long int, unsigned long int, long long int, or unsigned
+  //   long long int. If none of the types in that list can represent all the
+  //   values of the enumeration, an rvalue a prvalue of an unscoped enumeration
+  //   type can be converted to an rvalue a prvalue of the extended integer type
+  //   with lowest integer conversion rank (4.13) greater than the rank of long
+  //   long in which all the values of the enumeration can be represented. If
+  //   there are two such extended types, the signed one is chosen.
+  if (const EnumType *FromEnumType = FromType->getAs<EnumType>()) {
+    // C++0x 7.2p9: Note that this implicit enum to int conversion is not
+    // provided for a scoped enumeration.
+    if (FromEnumType->getDecl()->isScoped())
+      return false;
+
+    // We have already pre-calculated the promotion type, so this is trivial.
+    if (ToType->isIntegerType() &&
+        !RequireCompleteType(From->getLocStart(), FromType, PDiag()))
+      return Context.hasSameUnqualifiedType(ToType,
+                                FromEnumType->getDecl()->getPromotionType());
+  }
+
+  // C++0x [conv.prom]p2:
+  //   A prvalue of type char16_t, char32_t, or wchar_t (3.9.1) can be converted
+  //   to an rvalue a prvalue of the first of the following types that can
+  //   represent all the values of its underlying type: int, unsigned int,
+  //   long int, unsigned long int, long long int, or unsigned long long int.
+  //   If none of the types in that list can represent all the values of its
+  //   underlying type, an rvalue a prvalue of type char16_t, char32_t,
+  //   or wchar_t can be converted to an rvalue a prvalue of its underlying
+  //   type.
+  if (FromType->isAnyCharacterType() && !FromType->isCharType() &&
+      ToType->isIntegerType()) {
+    // Determine whether the type we're converting from is signed or
+    // unsigned.
+    bool FromIsSigned = FromType->isSignedIntegerType();
+    uint64_t FromSize = Context.getTypeSize(FromType);
+
+    // The types we'll try to promote to, in the appropriate
+    // order. Try each of these types.
+    QualType PromoteTypes[6] = {
+      Context.IntTy, Context.UnsignedIntTy,
+      Context.LongTy, Context.UnsignedLongTy ,
+      Context.LongLongTy, Context.UnsignedLongLongTy
+    };
+    for (int Idx = 0; Idx < 6; ++Idx) {
+      uint64_t ToSize = Context.getTypeSize(PromoteTypes[Idx]);
+      if (FromSize < ToSize ||
+          (FromSize == ToSize &&
+           FromIsSigned == PromoteTypes[Idx]->isSignedIntegerType())) {
+        // We found the type that we can promote to. If this is the
+        // type we wanted, we have a promotion. Otherwise, no
+        // promotion.
+        return Context.hasSameUnqualifiedType(ToType, PromoteTypes[Idx]);
+      }
+    }
+  }
+
+  // An rvalue for an integral bit-field (9.6) can be converted to an
+  // rvalue of type int if int can represent all the values of the
+  // bit-field; otherwise, it can be converted to unsigned int if
+  // unsigned int can represent all the values of the bit-field. If
+  // the bit-field is larger yet, no integral promotion applies to
+  // it. If the bit-field has an enumerated type, it is treated as any
+  // other value of that type for promotion purposes (C++ 4.5p3).
+  // FIXME: We should delay checking of bit-fields until we actually perform the
+  // conversion.
+  using llvm::APSInt;
+  if (From)
+    if (FieldDecl *MemberDecl = From->getBitField()) {
+      APSInt BitWidth;
+      if (FromType->isIntegralType(Context) &&
+          MemberDecl->getBitWidth()->isIntegerConstantExpr(BitWidth, Context)) {
+        APSInt ToSize(BitWidth.getBitWidth(), BitWidth.isUnsigned());
+        ToSize = Context.getTypeSize(ToType);
+
+        // Are we promoting to an int from a bitfield that fits in an int?
+        if (BitWidth < ToSize ||
+            (FromType->isSignedIntegerType() && BitWidth <= ToSize)) {
+          return To->getKind() == BuiltinType::Int;
+        }
+
+        // Are we promoting to an unsigned int from an unsigned bitfield
+        // that fits into an unsigned int?
+        if (FromType->isUnsignedIntegerType() && BitWidth <= ToSize) {
+          return To->getKind() == BuiltinType::UInt;
+        }
+
+        return false;
+      }
+    }
+
+  // An rvalue of type bool can be converted to an rvalue of type int,
+  // with false becoming zero and true becoming one (C++ 4.5p4).
+  if (FromType->isBooleanType() && To->getKind() == BuiltinType::Int) {
+    return true;
+  }
+
+  return false;
+}
+
+/// IsFloatingPointPromotion - Determines whether the conversion from
+/// FromType to ToType is a floating point promotion (C++ 4.6). If so,
+/// returns true and sets PromotedType to the promoted type.
+bool Sema::IsFloatingPointPromotion(QualType FromType, QualType ToType) {
+  if (const BuiltinType *FromBuiltin = FromType->getAs<BuiltinType>())
+    if (const BuiltinType *ToBuiltin = ToType->getAs<BuiltinType>()) {
+      /// An rvalue of type float can be converted to an rvalue of type
+      /// double. (C++ 4.6p1).
+      if (FromBuiltin->getKind() == BuiltinType::Float &&
+          ToBuiltin->getKind() == BuiltinType::Double)
+        return true;
+
+      // C99 6.3.1.5p1:
+      //   When a float is promoted to double or long double, or a
+      //   double is promoted to long double [...].
+      if (!getLangOpts().CPlusPlus &&
+          (FromBuiltin->getKind() == BuiltinType::Float ||
+           FromBuiltin->getKind() == BuiltinType::Double) &&
+          (ToBuiltin->getKind() == BuiltinType::LongDouble))
+        return true;
+
+      // Half can be promoted to float.
+      if (FromBuiltin->getKind() == BuiltinType::Half &&
+          ToBuiltin->getKind() == BuiltinType::Float)
+        return true;
+    }
+
+  return false;
+}
+
+/// \brief Determine if a conversion is a complex promotion.
+///
+/// A complex promotion is defined as a complex -> complex conversion
+/// where the conversion between the underlying real types is a
+/// floating-point or integral promotion.
+bool Sema::IsComplexPromotion(QualType FromType, QualType ToType) {
+  const ComplexType *FromComplex = FromType->getAs<ComplexType>();
+  if (!FromComplex)
+    return false;
+
+  const ComplexType *ToComplex = ToType->getAs<ComplexType>();
+  if (!ToComplex)
+    return false;
+
+  return IsFloatingPointPromotion(FromComplex->getElementType(),
+                                  ToComplex->getElementType()) ||
+    IsIntegralPromotion(0, FromComplex->getElementType(),
+                        ToComplex->getElementType());
+}
+
+/// BuildSimilarlyQualifiedPointerType - In a pointer conversion from
+/// the pointer type FromPtr to a pointer to type ToPointee, with the
+/// same type qualifiers as FromPtr has on its pointee type. ToType,
+/// if non-empty, will be a pointer to ToType that may or may not have
+/// the right set of qualifiers on its pointee.
+///
+static QualType
+BuildSimilarlyQualifiedPointerType(const Type *FromPtr,
+                                   QualType ToPointee, QualType ToType,
+                                   ASTContext &Context,
+                                   bool StripObjCLifetime = false) {
+  assert((FromPtr->getTypeClass() == Type::Pointer ||
+          FromPtr->getTypeClass() == Type::ObjCObjectPointer) &&
+         "Invalid similarly-qualified pointer type");
+
+  /// Conversions to 'id' subsume cv-qualifier conversions.
+  if (ToType->isObjCIdType() || ToType->isObjCQualifiedIdType()) 
+    return ToType.getUnqualifiedType();
+
+  QualType CanonFromPointee
+    = Context.getCanonicalType(FromPtr->getPointeeType());
+  QualType CanonToPointee = Context.getCanonicalType(ToPointee);
+  Qualifiers Quals = CanonFromPointee.getQualifiers();
+
+  if (StripObjCLifetime)
+    Quals.removeObjCLifetime();
+  
+  // Exact qualifier match -> return the pointer type we're converting to.
+  if (CanonToPointee.getLocalQualifiers() == Quals) {
+    // ToType is exactly what we need. Return it.
+    if (!ToType.isNull())
+      return ToType.getUnqualifiedType();
+
+    // Build a pointer to ToPointee. It has the right qualifiers
+    // already.
+    if (isa<ObjCObjectPointerType>(ToType))
+      return Context.getObjCObjectPointerType(ToPointee);
+    return Context.getPointerType(ToPointee);
+  }
+
+  // Just build a canonical type that has the right qualifiers.
+  QualType QualifiedCanonToPointee
+    = Context.getQualifiedType(CanonToPointee.getLocalUnqualifiedType(), Quals);
+
+  if (isa<ObjCObjectPointerType>(ToType))
+    return Context.getObjCObjectPointerType(QualifiedCanonToPointee);
+  return Context.getPointerType(QualifiedCanonToPointee);
+}
+
+static bool isNullPointerConstantForConversion(Expr *Expr,
+                                               bool InOverloadResolution,
+                                               ASTContext &Context) {
+  // Handle value-dependent integral null pointer constants correctly.
+  // http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#903
+  if (Expr->isValueDependent() && !Expr->isTypeDependent() &&
+      Expr->getType()->isIntegerType() && !Expr->getType()->isEnumeralType())
+    return !InOverloadResolution;
+
+  return Expr->isNullPointerConstant(Context,
+                    InOverloadResolution? Expr::NPC_ValueDependentIsNotNull
+                                        : Expr::NPC_ValueDependentIsNull);
+}
+
+/// IsPointerConversion - Determines whether the conversion of the
+/// expression From, which has the (possibly adjusted) type FromType,
+/// can be converted to the type ToType via a pointer conversion (C++
+/// 4.10). If so, returns true and places the converted type (that
+/// might differ from ToType in its cv-qualifiers at some level) into
+/// ConvertedType.
+///
+/// This routine also supports conversions to and from block pointers
+/// and conversions with Objective-C's 'id', 'id<protocols...>', and
+/// pointers to interfaces. FIXME: Once we've determined the
+/// appropriate overloading rules for Objective-C, we may want to
+/// split the Objective-C checks into a different routine; however,
+/// GCC seems to consider all of these conversions to be pointer
+/// conversions, so for now they live here. IncompatibleObjC will be
+/// set if the conversion is an allowed Objective-C conversion that
+/// should result in a warning.
+bool Sema::IsPointerConversion(Expr *From, QualType FromType, QualType ToType,
+                               bool InOverloadResolution,
+                               QualType& ConvertedType,
+                               bool &IncompatibleObjC) {
+  IncompatibleObjC = false;
+  if (isObjCPointerConversion(FromType, ToType, ConvertedType,
+                              IncompatibleObjC))
+    return true;
+
+  // Conversion from a null pointer constant to any Objective-C pointer type.
+  if (ToType->isObjCObjectPointerType() &&
+      isNullPointerConstantForConversion(From, InOverloadResolution, Context)) {
+    ConvertedType = ToType;
+    return true;
+  }
+
+  // Blocks: Block pointers can be converted to void*.
+  if (FromType->isBlockPointerType() && ToType->isPointerType() &&
+      ToType->getAs<PointerType>()->getPointeeType()->isVoidType()) {
+    ConvertedType = ToType;
+    return true;
+  }
+  // Blocks: A null pointer constant can be converted to a block
+  // pointer type.
+  if (ToType->isBlockPointerType() &&
+      isNullPointerConstantForConversion(From, InOverloadResolution, Context)) {
+    ConvertedType = ToType;
+    return true;
+  }
+
+  // If the left-hand-side is nullptr_t, the right side can be a null
+  // pointer constant.
+  if (ToType->isNullPtrType() &&
+      isNullPointerConstantForConversion(From, InOverloadResolution, Context)) {
+    ConvertedType = ToType;
+    return true;
+  }
+
+  const PointerType* ToTypePtr = ToType->getAs<PointerType>();
+  if (!ToTypePtr)
+    return false;
+
+  // A null pointer constant can be converted to a pointer type (C++ 4.10p1).
+  if (isNullPointerConstantForConversion(From, InOverloadResolution, Context)) {
+    ConvertedType = ToType;
+    return true;
+  }
+
+  // Beyond this point, both types need to be pointers
+  // , including objective-c pointers.
+  QualType ToPointeeType = ToTypePtr->getPointeeType();
+  if (FromType->isObjCObjectPointerType() && ToPointeeType->isVoidType() &&
+      !getLangOpts().ObjCAutoRefCount) {
+    ConvertedType = BuildSimilarlyQualifiedPointerType(
+                                      FromType->getAs<ObjCObjectPointerType>(),
+                                                       ToPointeeType,
+                                                       ToType, Context);
+    return true;
+  }
+  const PointerType *FromTypePtr = FromType->getAs<PointerType>();
+  if (!FromTypePtr)
+    return false;
+
+  QualType FromPointeeType = FromTypePtr->getPointeeType();
+
+  // If the unqualified pointee types are the same, this can't be a
+  // pointer conversion, so don't do all of the work below.
+  if (Context.hasSameUnqualifiedType(FromPointeeType, ToPointeeType))
+    return false;
+
+  // An rvalue of type "pointer to cv T," where T is an object type,
+  // can be converted to an rvalue of type "pointer to cv void" (C++
+  // 4.10p2).
+  if (FromPointeeType->isIncompleteOrObjectType() &&
+      ToPointeeType->isVoidType()) {
+    ConvertedType = BuildSimilarlyQualifiedPointerType(FromTypePtr,
+                                                       ToPointeeType,
+                                                       ToType, Context,
+                                                   /*StripObjCLifetime=*/true);
+    return true;
+  }
+
+  // MSVC allows implicit function to void* type conversion.
+  if (getLangOpts().MicrosoftExt && FromPointeeType->isFunctionType() &&
+      ToPointeeType->isVoidType()) {
+    ConvertedType = BuildSimilarlyQualifiedPointerType(FromTypePtr,
+                                                       ToPointeeType,
+                                                       ToType, Context);
+    return true;
+  }
+
+  // When we're overloading in C, we allow a special kind of pointer
+  // conversion for compatible-but-not-identical pointee types.
+  if (!getLangOpts().CPlusPlus &&
+      Context.typesAreCompatible(FromPointeeType, ToPointeeType)) {
+    ConvertedType = BuildSimilarlyQualifiedPointerType(FromTypePtr,
+                                                       ToPointeeType,
+                                                       ToType, Context);
+    return true;
+  }
+
+  // C++ [conv.ptr]p3:
+  //
+  //   An rvalue of type "pointer to cv D," where D is a class type,
+  //   can be converted to an rvalue of type "pointer to cv B," where
+  //   B is a base class (clause 10) of D. If B is an inaccessible
+  //   (clause 11) or ambiguous (10.2) base class of D, a program that
+  //   necessitates this conversion is ill-formed. The result of the
+  //   conversion is a pointer to the base class sub-object of the
+  //   derived class object. The null pointer value is converted to
+  //   the null pointer value of the destination type.
+  //
+  // Note that we do not check for ambiguity or inaccessibility
+  // here. That is handled by CheckPointerConversion.
+  if (getLangOpts().CPlusPlus &&
+      FromPointeeType->isRecordType() && ToPointeeType->isRecordType() &&
+      !Context.hasSameUnqualifiedType(FromPointeeType, ToPointeeType) &&
+      !RequireCompleteType(From->getLocStart(), FromPointeeType, PDiag()) &&
+      IsDerivedFrom(FromPointeeType, ToPointeeType)) {
+    ConvertedType = BuildSimilarlyQualifiedPointerType(FromTypePtr,
+                                                       ToPointeeType,
+                                                       ToType, Context);
+    return true;
+  }
+
+  if (FromPointeeType->isVectorType() && ToPointeeType->isVectorType() &&
+      Context.areCompatibleVectorTypes(FromPointeeType, ToPointeeType)) {
+    ConvertedType = BuildSimilarlyQualifiedPointerType(FromTypePtr,
+                                                       ToPointeeType,
+                                                       ToType, Context);
+    return true;
+  }
+  
+  return false;
+}
+ 
+/// \brief Adopt the given qualifiers for the given type.
+static QualType AdoptQualifiers(ASTContext &Context, QualType T, Qualifiers Qs){
+  Qualifiers TQs = T.getQualifiers();
+  
+  // Check whether qualifiers already match.
+  if (TQs == Qs)
+    return T;
+  
+  if (Qs.compatiblyIncludes(TQs))
+    return Context.getQualifiedType(T, Qs);
+  
+  return Context.getQualifiedType(T.getUnqualifiedType(), Qs);
+}
+
+/// isObjCPointerConversion - Determines whether this is an
+/// Objective-C pointer conversion. Subroutine of IsPointerConversion,
+/// with the same arguments and return values.
+bool Sema::isObjCPointerConversion(QualType FromType, QualType ToType,
+                                   QualType& ConvertedType,
+                                   bool &IncompatibleObjC) {
+  if (!getLangOpts().ObjC1)
+    return false;
+
+  // The set of qualifiers on the type we're converting from.
+  Qualifiers FromQualifiers = FromType.getQualifiers();
+  
+  // First, we handle all conversions on ObjC object pointer types.
+  const ObjCObjectPointerType* ToObjCPtr =
+    ToType->getAs<ObjCObjectPointerType>();
+  const ObjCObjectPointerType *FromObjCPtr =
+    FromType->getAs<ObjCObjectPointerType>();
+
+  if (ToObjCPtr && FromObjCPtr) {
+    // If the pointee types are the same (ignoring qualifications),
+    // then this is not a pointer conversion.
+    if (Context.hasSameUnqualifiedType(ToObjCPtr->getPointeeType(),
+                                       FromObjCPtr->getPointeeType()))
+      return false;
+
+    // Check for compatible 
+    // Objective C++: We're able to convert between "id" or "Class" and a
+    // pointer to any interface (in both directions).
+    if (ToObjCPtr->isObjCBuiltinType() && FromObjCPtr->isObjCBuiltinType()) {
+      ConvertedType = AdoptQualifiers(Context, ToType, FromQualifiers);
+      return true;
+    }
+    // Conversions with Objective-C's id<...>.
+    if ((FromObjCPtr->isObjCQualifiedIdType() ||
+         ToObjCPtr->isObjCQualifiedIdType()) &&
+        Context.ObjCQualifiedIdTypesAreCompatible(ToType, FromType,
+                                                  /*compare=*/false)) {
+      ConvertedType = AdoptQualifiers(Context, ToType, FromQualifiers);
+      return true;
+    }
+    // Objective C++: We're able to convert from a pointer to an
+    // interface to a pointer to a different interface.
+    if (Context.canAssignObjCInterfaces(ToObjCPtr, FromObjCPtr)) {
+      const ObjCInterfaceType* LHS = ToObjCPtr->getInterfaceType();
+      const ObjCInterfaceType* RHS = FromObjCPtr->getInterfaceType();
+      if (getLangOpts().CPlusPlus && LHS && RHS &&
+          !ToObjCPtr->getPointeeType().isAtLeastAsQualifiedAs(
+                                                FromObjCPtr->getPointeeType()))
+        return false;
+      ConvertedType = BuildSimilarlyQualifiedPointerType(FromObjCPtr,
+                                                   ToObjCPtr->getPointeeType(),
+                                                         ToType, Context);
+      ConvertedType = AdoptQualifiers(Context, ConvertedType, FromQualifiers);
+      return true;
+    }
+
+    if (Context.canAssignObjCInterfaces(FromObjCPtr, ToObjCPtr)) {
+      // Okay: this is some kind of implicit downcast of Objective-C
+      // interfaces, which is permitted. However, we're going to
+      // complain about it.
+      IncompatibleObjC = true;
+      ConvertedType = BuildSimilarlyQualifiedPointerType(FromObjCPtr,
+                                                   ToObjCPtr->getPointeeType(),
+                                                         ToType, Context);
+      ConvertedType = AdoptQualifiers(Context, ConvertedType, FromQualifiers);
+      return true;
+    }
+  }
+  // Beyond this point, both types need to be C pointers or block pointers.
+  QualType ToPointeeType;
+  if (const PointerType *ToCPtr = ToType->getAs<PointerType>())
+    ToPointeeType = ToCPtr->getPointeeType();
+  else if (const BlockPointerType *ToBlockPtr =
+            ToType->getAs<BlockPointerType>()) {
+    // Objective C++: We're able to convert from a pointer to any object
+    // to a block pointer type.
+    if (FromObjCPtr && FromObjCPtr->isObjCBuiltinType()) {
+      ConvertedType = AdoptQualifiers(Context, ToType, FromQualifiers);
+      return true;
+    }
+    ToPointeeType = ToBlockPtr->getPointeeType();
+  }
+  else if (FromType->getAs<BlockPointerType>() &&
+           ToObjCPtr && ToObjCPtr->isObjCBuiltinType()) {
+    // Objective C++: We're able to convert from a block pointer type to a
+    // pointer to any object.
+    ConvertedType = AdoptQualifiers(Context, ToType, FromQualifiers);
+    return true;
+  }
+  else
+    return false;
+
+  QualType FromPointeeType;
+  if (const PointerType *FromCPtr = FromType->getAs<PointerType>())
+    FromPointeeType = FromCPtr->getPointeeType();
+  else if (const BlockPointerType *FromBlockPtr =
+           FromType->getAs<BlockPointerType>())
+    FromPointeeType = FromBlockPtr->getPointeeType();
+  else
+    return false;
+
+  // If we have pointers to pointers, recursively check whether this
+  // is an Objective-C conversion.
+  if (FromPointeeType->isPointerType() && ToPointeeType->isPointerType() &&
+      isObjCPointerConversion(FromPointeeType, ToPointeeType, ConvertedType,
+                              IncompatibleObjC)) {
+    // We always complain about this conversion.
+    IncompatibleObjC = true;
+    ConvertedType = Context.getPointerType(ConvertedType);
+    ConvertedType = AdoptQualifiers(Context, ConvertedType, FromQualifiers);
+    return true;
+  }
+  // Allow conversion of pointee being objective-c pointer to another one;
+  // as in I* to id.
+  if (FromPointeeType->getAs<ObjCObjectPointerType>() &&
+      ToPointeeType->getAs<ObjCObjectPointerType>() &&
+      isObjCPointerConversion(FromPointeeType, ToPointeeType, ConvertedType,
+                              IncompatibleObjC)) {
+        
+    ConvertedType = Context.getPointerType(ConvertedType);
+    ConvertedType = AdoptQualifiers(Context, ConvertedType, FromQualifiers);
+    return true;
+  }
+
+  // If we have pointers to functions or blocks, check whether the only
+  // differences in the argument and result types are in Objective-C
+  // pointer conversions. If so, we permit the conversion (but
+  // complain about it).
+  const FunctionProtoType *FromFunctionType
+    = FromPointeeType->getAs<FunctionProtoType>();
+  const FunctionProtoType *ToFunctionType
+    = ToPointeeType->getAs<FunctionProtoType>();
+  if (FromFunctionType && ToFunctionType) {
+    // If the function types are exactly the same, this isn't an
+    // Objective-C pointer conversion.
+    if (Context.getCanonicalType(FromPointeeType)
+          == Context.getCanonicalType(ToPointeeType))
+      return false;
+
+    // Perform the quick checks that will tell us whether these
+    // function types are obviously different.
+    if (FromFunctionType->getNumArgs() != ToFunctionType->getNumArgs() ||
+        FromFunctionType->isVariadic() != ToFunctionType->isVariadic() ||
+        FromFunctionType->getTypeQuals() != ToFunctionType->getTypeQuals())
+      return false;
+
+    bool HasObjCConversion = false;
+    if (Context.getCanonicalType(FromFunctionType->getResultType())
+          == Context.getCanonicalType(ToFunctionType->getResultType())) {
+      // Okay, the types match exactly. Nothing to do.
+    } else if (isObjCPointerConversion(FromFunctionType->getResultType(),
+                                       ToFunctionType->getResultType(),
+                                       ConvertedType, IncompatibleObjC)) {
+      // Okay, we have an Objective-C pointer conversion.
+      HasObjCConversion = true;
+    } else {
+      // Function types are too different. Abort.
+      return false;
+    }
+
+    // Check argument types.
+    for (unsigned ArgIdx = 0, NumArgs = FromFunctionType->getNumArgs();
+         ArgIdx != NumArgs; ++ArgIdx) {
+      QualType FromArgType = FromFunctionType->getArgType(ArgIdx);
+      QualType ToArgType = ToFunctionType->getArgType(ArgIdx);
+      if (Context.getCanonicalType(FromArgType)
+            == Context.getCanonicalType(ToArgType)) {
+        // Okay, the types match exactly. Nothing to do.
+      } else if (isObjCPointerConversion(FromArgType, ToArgType,
+                                         ConvertedType, IncompatibleObjC)) {
+        // Okay, we have an Objective-C pointer conversion.
+        HasObjCConversion = true;
+      } else {
+        // Argument types are too different. Abort.
+        return false;
+      }
+    }
+
+    if (HasObjCConversion) {
+      // We had an Objective-C conversion. Allow this pointer
+      // conversion, but complain about it.
+      ConvertedType = AdoptQualifiers(Context, ToType, FromQualifiers);
+      IncompatibleObjC = true;
+      return true;
+    }
+  }
+
+  return false;
+}
+
+/// \brief Determine whether this is an Objective-C writeback conversion,
+/// used for parameter passing when performing automatic reference counting.
+///
+/// \param FromType The type we're converting form.
+///
+/// \param ToType The type we're converting to.
+///
+/// \param ConvertedType The type that will be produced after applying
+/// this conversion.
+bool Sema::isObjCWritebackConversion(QualType FromType, QualType ToType,
+                                     QualType &ConvertedType) {
+  if (!getLangOpts().ObjCAutoRefCount || 
+      Context.hasSameUnqualifiedType(FromType, ToType))
+    return false;
+  
+  // Parameter must be a pointer to __autoreleasing (with no other qualifiers).
+  QualType ToPointee;
+  if (const PointerType *ToPointer = ToType->getAs<PointerType>())
+    ToPointee = ToPointer->getPointeeType();
+  else
+    return false;
+  
+  Qualifiers ToQuals = ToPointee.getQualifiers();
+  if (!ToPointee->isObjCLifetimeType() || 
+      ToQuals.getObjCLifetime() != Qualifiers::OCL_Autoreleasing ||
+      !ToQuals.withoutObjCLifetime().empty())
+    return false;
+  
+  // Argument must be a pointer to __strong to __weak.
+  QualType FromPointee;
+  if (const PointerType *FromPointer = FromType->getAs<PointerType>())
+    FromPointee = FromPointer->getPointeeType();
+  else
+    return false;
+  
+  Qualifiers FromQuals = FromPointee.getQualifiers();
+  if (!FromPointee->isObjCLifetimeType() ||
+      (FromQuals.getObjCLifetime() != Qualifiers::OCL_Strong &&
+       FromQuals.getObjCLifetime() != Qualifiers::OCL_Weak))
+    return false;
+  
+  // Make sure that we have compatible qualifiers.
+  FromQuals.setObjCLifetime(Qualifiers::OCL_Autoreleasing);
+  if (!ToQuals.compatiblyIncludes(FromQuals))
+    return false;
+  
+  // Remove qualifiers from the pointee type we're converting from; they
+  // aren't used in the compatibility check belong, and we'll be adding back
+  // qualifiers (with __autoreleasing) if the compatibility check succeeds.
+  FromPointee = FromPointee.getUnqualifiedType();
+  
+  // The unqualified form of the pointee types must be compatible.
+  ToPointee = ToPointee.getUnqualifiedType();
+  bool IncompatibleObjC;
+  if (Context.typesAreCompatible(FromPointee, ToPointee))
+    FromPointee = ToPointee;
+  else if (!isObjCPointerConversion(FromPointee, ToPointee, FromPointee,
+                                    IncompatibleObjC))
+    return false;
+  
+  /// \brief Construct the type we're converting to, which is a pointer to
+  /// __autoreleasing pointee.
+  FromPointee = Context.getQualifiedType(FromPointee, FromQuals);
+  ConvertedType = Context.getPointerType(FromPointee);
+  return true;
+}
+
+bool Sema::IsBlockPointerConversion(QualType FromType, QualType ToType,
+                                    QualType& ConvertedType) {
+  QualType ToPointeeType;
+  if (const BlockPointerType *ToBlockPtr =
+        ToType->getAs<BlockPointerType>())
+    ToPointeeType = ToBlockPtr->getPointeeType();
+  else
+    return false;
+  
+  QualType FromPointeeType;
+  if (const BlockPointerType *FromBlockPtr =
+      FromType->getAs<BlockPointerType>())
+    FromPointeeType = FromBlockPtr->getPointeeType();
+  else
+    return false;
+  // We have pointer to blocks, check whether the only
+  // differences in the argument and result types are in Objective-C
+  // pointer conversions. If so, we permit the conversion.
+  
+  const FunctionProtoType *FromFunctionType
+    = FromPointeeType->getAs<FunctionProtoType>();
+  const FunctionProtoType *ToFunctionType
+    = ToPointeeType->getAs<FunctionProtoType>();
+  
+  if (!FromFunctionType || !ToFunctionType)
+    return false;
+
+  if (Context.hasSameType(FromPointeeType, ToPointeeType))
+    return true;
+    
+  // Perform the quick checks that will tell us whether these
+  // function types are obviously different.
+  if (FromFunctionType->getNumArgs() != ToFunctionType->getNumArgs() ||
+      FromFunctionType->isVariadic() != ToFunctionType->isVariadic())
+    return false;
+    
+  FunctionType::ExtInfo FromEInfo = FromFunctionType->getExtInfo();
+  FunctionType::ExtInfo ToEInfo = ToFunctionType->getExtInfo();
+  if (FromEInfo != ToEInfo)
+    return false;
+
+  bool IncompatibleObjC = false;
+  if (Context.hasSameType(FromFunctionType->getResultType(), 
+                          ToFunctionType->getResultType())) {
+    // Okay, the types match exactly. Nothing to do.
+  } else {
+    QualType RHS = FromFunctionType->getResultType();
+    QualType LHS = ToFunctionType->getResultType();
+    if ((!getLangOpts().CPlusPlus || !RHS->isRecordType()) &&
+        !RHS.hasQualifiers() && LHS.hasQualifiers())
+       LHS = LHS.getUnqualifiedType();
+
+     if (Context.hasSameType(RHS,LHS)) {
+       // OK exact match.
+     } else if (isObjCPointerConversion(RHS, LHS,
+                                        ConvertedType, IncompatibleObjC)) {
+     if (IncompatibleObjC)
+       return false;
+     // Okay, we have an Objective-C pointer conversion.
+     }
+     else
+       return false;
+   }
+    
+   // Check argument types.
+   for (unsigned ArgIdx = 0, NumArgs = FromFunctionType->getNumArgs();
+        ArgIdx != NumArgs; ++ArgIdx) {
+     IncompatibleObjC = false;
+     QualType FromArgType = FromFunctionType->getArgType(ArgIdx);
+     QualType ToArgType = ToFunctionType->getArgType(ArgIdx);
+     if (Context.hasSameType(FromArgType, ToArgType)) {
+       // Okay, the types match exactly. Nothing to do.
+     } else if (isObjCPointerConversion(ToArgType, FromArgType,
+                                        ConvertedType, IncompatibleObjC)) {
+       if (IncompatibleObjC)
+         return false;
+       // Okay, we have an Objective-C pointer conversion.
+     } else
+       // Argument types are too different. Abort.
+       return false;
+   }
+   if (LangOpts.ObjCAutoRefCount && 
+       !Context.FunctionTypesMatchOnNSConsumedAttrs(FromFunctionType, 
+                                                    ToFunctionType))
+     return false;
+   
+   ConvertedType = ToType;
+   return true;
+}
+
+enum {
+  ft_default,
+  ft_different_class,
+  ft_parameter_arity,
+  ft_parameter_mismatch,
+  ft_return_type,
+  ft_qualifer_mismatch
+};
+
+/// HandleFunctionTypeMismatch - Gives diagnostic information for differeing
+/// function types.  Catches different number of parameter, mismatch in
+/// parameter types, and different return types.
+void Sema::HandleFunctionTypeMismatch(PartialDiagnostic &PDiag,
+                                      QualType FromType, QualType ToType) {
+  // If either type is not valid, include no extra info.
+  if (FromType.isNull() || ToType.isNull()) {
+    PDiag << ft_default;
+    return;
+  }
+
+  // Get the function type from the pointers.
+  if (FromType->isMemberPointerType() && ToType->isMemberPointerType()) {
+    const MemberPointerType *FromMember = FromType->getAs<MemberPointerType>(),
+                            *ToMember = ToType->getAs<MemberPointerType>();
+    if (FromMember->getClass() != ToMember->getClass()) {
+      PDiag << ft_different_class << QualType(ToMember->getClass(), 0)
+            << QualType(FromMember->getClass(), 0);
+      return;
+    }
+    FromType = FromMember->getPointeeType();
+    ToType = ToMember->getPointeeType();
+  }
+
+  if (FromType->isPointerType())
+    FromType = FromType->getPointeeType();
+  if (ToType->isPointerType())
+    ToType = ToType->getPointeeType();
+
+  // Remove references.
+  FromType = FromType.getNonReferenceType();
+  ToType = ToType.getNonReferenceType();
+
+  // Don't print extra info for non-specialized template functions.
+  if (FromType->isInstantiationDependentType() &&
+      !FromType->getAs<TemplateSpecializationType>()) {
+    PDiag << ft_default;
+    return;
+  }
+
+  // No extra info for same types.
+  if (Context.hasSameType(FromType, ToType)) {
+    PDiag << ft_default;
+    return;
+  }
+
+  const FunctionProtoType *FromFunction = FromType->getAs<FunctionProtoType>(),
+                          *ToFunction = ToType->getAs<FunctionProtoType>();
+
+  // Both types need to be function types.
+  if (!FromFunction || !ToFunction) {
+    PDiag << ft_default;
+    return;
+  }
+
+  if (FromFunction->getNumArgs() != ToFunction->getNumArgs()) {
+    PDiag << ft_parameter_arity << ToFunction->getNumArgs()
+          << FromFunction->getNumArgs();
+    return;
+  }
+
+  // Handle different parameter types.
+  unsigned ArgPos;
+  if (!FunctionArgTypesAreEqual(FromFunction, ToFunction, &ArgPos)) {
+    PDiag << ft_parameter_mismatch << ArgPos + 1
+          << ToFunction->getArgType(ArgPos)
+          << FromFunction->getArgType(ArgPos);
+    return;
+  }
+
+  // Handle different return type.
+  if (!Context.hasSameType(FromFunction->getResultType(),
+                           ToFunction->getResultType())) {
+    PDiag << ft_return_type << ToFunction->getResultType()
+          << FromFunction->getResultType();
+    return;
+  }
+
+  unsigned FromQuals = FromFunction->getTypeQuals(),
+           ToQuals = ToFunction->getTypeQuals();
+  if (FromQuals != ToQuals) {
+    PDiag << ft_qualifer_mismatch << ToQuals << FromQuals;
+    return;
+  }
+
+  // Unable to find a difference, so add no extra info.
+  PDiag << ft_default;
+}
+
+/// FunctionArgTypesAreEqual - This routine checks two function proto types
+/// for equality of their argument types. Caller has already checked that
+/// they have same number of arguments. This routine assumes that Objective-C
+/// pointer types which only differ in their protocol qualifiers are equal.
+/// If the parameters are different, ArgPos will have the the parameter index
+/// of the first different parameter.
+bool Sema::FunctionArgTypesAreEqual(const FunctionProtoType *OldType,
+                                    const FunctionProtoType *NewType,
+                                    unsigned *ArgPos) {
+  if (!getLangOpts().ObjC1) {
+    for (FunctionProtoType::arg_type_iterator O = OldType->arg_type_begin(),
+         N = NewType->arg_type_begin(),
+         E = OldType->arg_type_end(); O && (O != E); ++O, ++N) {
+      if (!Context.hasSameType(*O, *N)) {
+        if (ArgPos) *ArgPos = O - OldType->arg_type_begin();
+        return false;
+      }
+    }
+    return true;
+  }
+
+  for (FunctionProtoType::arg_type_iterator O = OldType->arg_type_begin(),
+       N = NewType->arg_type_begin(),
+       E = OldType->arg_type_end(); O && (O != E); ++O, ++N) {
+    QualType ToType = (*O);
+    QualType FromType = (*N);
+    if (!Context.hasSameType(ToType, FromType)) {
+      if (const PointerType *PTTo = ToType->getAs<PointerType>()) {
+        if (const PointerType *PTFr = FromType->getAs<PointerType>())
+          if ((PTTo->getPointeeType()->isObjCQualifiedIdType() &&
+               PTFr->getPointeeType()->isObjCQualifiedIdType()) ||
+              (PTTo->getPointeeType()->isObjCQualifiedClassType() &&
+               PTFr->getPointeeType()->isObjCQualifiedClassType()))
+            continue;
+      }
+      else if (const ObjCObjectPointerType *PTTo =
+                 ToType->getAs<ObjCObjectPointerType>()) {
+        if (const ObjCObjectPointerType *PTFr =
+              FromType->getAs<ObjCObjectPointerType>())
+          if (Context.hasSameUnqualifiedType(
+                PTTo->getObjectType()->getBaseType(),
+                PTFr->getObjectType()->getBaseType()))
+            continue;
+      }
+      if (ArgPos) *ArgPos = O - OldType->arg_type_begin();
+      return false;
+    }
+  }
+  return true;
+}
+
+/// CheckPointerConversion - Check the pointer conversion from the
+/// expression From to the type ToType. This routine checks for
+/// ambiguous or inaccessible derived-to-base pointer
+/// conversions for which IsPointerConversion has already returned
+/// true. It returns true and produces a diagnostic if there was an
+/// error, or returns false otherwise.
+bool Sema::CheckPointerConversion(Expr *From, QualType ToType,
+                                  CastKind &Kind,
+                                  CXXCastPath& BasePath,
+                                  bool IgnoreBaseAccess) {
+  QualType FromType = From->getType();
+  bool IsCStyleOrFunctionalCast = IgnoreBaseAccess;
+
+  Kind = CK_BitCast;
+
+  if (!IsCStyleOrFunctionalCast &&
+      Context.hasSameUnqualifiedType(From->getType(), Context.BoolTy) &&
+      From->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNotNull))
+    DiagRuntimeBehavior(From->getExprLoc(), From,
+                        PDiag(diag::warn_impcast_bool_to_null_pointer)
+                          << ToType << From->getSourceRange());
+
+  if (const PointerType *ToPtrType = ToType->getAs<PointerType>()) {
+    if (const PointerType *FromPtrType = FromType->getAs<PointerType>()) {
+      QualType FromPointeeType = FromPtrType->getPointeeType(),
+               ToPointeeType   = ToPtrType->getPointeeType();
+
+      if (FromPointeeType->isRecordType() && ToPointeeType->isRecordType() &&
+          !Context.hasSameUnqualifiedType(FromPointeeType, ToPointeeType)) {
+        // We must have a derived-to-base conversion. Check an
+        // ambiguous or inaccessible conversion.
+        if (CheckDerivedToBaseConversion(FromPointeeType, ToPointeeType,
+                                         From->getExprLoc(),
+                                         From->getSourceRange(), &BasePath,
+                                         IgnoreBaseAccess))
+          return true;
+
+        // The conversion was successful.
+        Kind = CK_DerivedToBase;
+      }
+    }
+  } else if (const ObjCObjectPointerType *ToPtrType =
+               ToType->getAs<ObjCObjectPointerType>()) {
+    if (const ObjCObjectPointerType *FromPtrType =
+          FromType->getAs<ObjCObjectPointerType>()) {
+      // Objective-C++ conversions are always okay.
+      // FIXME: We should have a different class of conversions for the
+      // Objective-C++ implicit conversions.
+      if (FromPtrType->isObjCBuiltinType() || ToPtrType->isObjCBuiltinType())
+        return false;
+    } else if (FromType->isBlockPointerType()) {
+      Kind = CK_BlockPointerToObjCPointerCast;
+    } else {
+      Kind = CK_CPointerToObjCPointerCast;
+    }
+  } else if (ToType->isBlockPointerType()) {
+    if (!FromType->isBlockPointerType())
+      Kind = CK_AnyPointerToBlockPointerCast;
+  }
+
+  // We shouldn't fall into this case unless it's valid for other
+  // reasons.
+  if (From->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull))
+    Kind = CK_NullToPointer;
+
+  return false;
+}
+
+/// IsMemberPointerConversion - Determines whether the conversion of the
+/// expression From, which has the (possibly adjusted) type FromType, can be
+/// converted to the type ToType via a member pointer conversion (C++ 4.11).
+/// If so, returns true and places the converted type (that might differ from
+/// ToType in its cv-qualifiers at some level) into ConvertedType.
+bool Sema::IsMemberPointerConversion(Expr *From, QualType FromType,
+                                     QualType ToType,
+                                     bool InOverloadResolution,
+                                     QualType &ConvertedType) {
+  const MemberPointerType *ToTypePtr = ToType->getAs<MemberPointerType>();
+  if (!ToTypePtr)
+    return false;
+
+  // A null pointer constant can be converted to a member pointer (C++ 4.11p1)
+  if (From->isNullPointerConstant(Context,
+                    InOverloadResolution? Expr::NPC_ValueDependentIsNotNull
+                                        : Expr::NPC_ValueDependentIsNull)) {
+    ConvertedType = ToType;
+    return true;
+  }
+
+  // Otherwise, both types have to be member pointers.
+  const MemberPointerType *FromTypePtr = FromType->getAs<MemberPointerType>();
+  if (!FromTypePtr)
+    return false;
+
+  // A pointer to member of B can be converted to a pointer to member of D,
+  // where D is derived from B (C++ 4.11p2).
+  QualType FromClass(FromTypePtr->getClass(), 0);
+  QualType ToClass(ToTypePtr->getClass(), 0);
+
+  if (!Context.hasSameUnqualifiedType(FromClass, ToClass) &&
+      !RequireCompleteType(From->getLocStart(), ToClass, PDiag()) &&
+      IsDerivedFrom(ToClass, FromClass)) {
+    ConvertedType = Context.getMemberPointerType(FromTypePtr->getPointeeType(),
+                                                 ToClass.getTypePtr());
+    return true;
+  }
+
+  return false;
+}
+
+/// CheckMemberPointerConversion - Check the member pointer conversion from the
+/// expression From to the type ToType. This routine checks for ambiguous or
+/// virtual or inaccessible base-to-derived member pointer conversions
+/// for which IsMemberPointerConversion has already returned true. It returns
+/// true and produces a diagnostic if there was an error, or returns false
+/// otherwise.
+bool Sema::CheckMemberPointerConversion(Expr *From, QualType ToType,
+                                        CastKind &Kind,
+                                        CXXCastPath &BasePath,
+                                        bool IgnoreBaseAccess) {
+  QualType FromType = From->getType();
+  const MemberPointerType *FromPtrType = FromType->getAs<MemberPointerType>();
+  if (!FromPtrType) {
+    // This must be a null pointer to member pointer conversion
+    assert(From->isNullPointerConstant(Context,
+                                       Expr::NPC_ValueDependentIsNull) &&
+           "Expr must be null pointer constant!");
+    Kind = CK_NullToMemberPointer;
+    return false;
+  }
+
+  const MemberPointerType *ToPtrType = ToType->getAs<MemberPointerType>();
+  assert(ToPtrType && "No member pointer cast has a target type "
+                      "that is not a member pointer.");
+
+  QualType FromClass = QualType(FromPtrType->getClass(), 0);
+  QualType ToClass   = QualType(ToPtrType->getClass(), 0);
+
+  // FIXME: What about dependent types?
+  assert(FromClass->isRecordType() && "Pointer into non-class.");
+  assert(ToClass->isRecordType() && "Pointer into non-class.");
+
+  CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
+                     /*DetectVirtual=*/true);
+  bool DerivationOkay = IsDerivedFrom(ToClass, FromClass, Paths);
+  assert(DerivationOkay &&
+         "Should not have been called if derivation isn't OK.");
+  (void)DerivationOkay;
+
+  if (Paths.isAmbiguous(Context.getCanonicalType(FromClass).
+                                  getUnqualifiedType())) {
+    std::string PathDisplayStr = getAmbiguousPathsDisplayString(Paths);
+    Diag(From->getExprLoc(), diag::err_ambiguous_memptr_conv)
+      << 0 << FromClass << ToClass << PathDisplayStr << From->getSourceRange();
+    return true;
+  }
+
+  if (const RecordType *VBase = Paths.getDetectedVirtual()) {
+    Diag(From->getExprLoc(), diag::err_memptr_conv_via_virtual)
+      << FromClass << ToClass << QualType(VBase, 0)
+      << From->getSourceRange();
+    return true;
+  }
+
+  if (!IgnoreBaseAccess)
+    CheckBaseClassAccess(From->getExprLoc(), FromClass, ToClass,
+                         Paths.front(),
+                         diag::err_downcast_from_inaccessible_base);
+
+  // Must be a base to derived member conversion.
+  BuildBasePathArray(Paths, BasePath);
+  Kind = CK_BaseToDerivedMemberPointer;
+  return false;
+}
+
+/// IsQualificationConversion - Determines whether the conversion from
+/// an rvalue of type FromType to ToType is a qualification conversion
+/// (C++ 4.4).
+///
+/// \param ObjCLifetimeConversion Output parameter that will be set to indicate
+/// when the qualification conversion involves a change in the Objective-C
+/// object lifetime.
+bool
+Sema::IsQualificationConversion(QualType FromType, QualType ToType,
+                                bool CStyle, bool &ObjCLifetimeConversion) {
+  FromType = Context.getCanonicalType(FromType);
+  ToType = Context.getCanonicalType(ToType);
+  ObjCLifetimeConversion = false;
+  
+  // If FromType and ToType are the same type, this is not a
+  // qualification conversion.
+  if (FromType.getUnqualifiedType() == ToType.getUnqualifiedType())
+    return false;
+
+  // (C++ 4.4p4):
+  //   A conversion can add cv-qualifiers at levels other than the first
+  //   in multi-level pointers, subject to the following rules: [...]
+  bool PreviousToQualsIncludeConst = true;
+  bool UnwrappedAnyPointer = false;
+  while (Context.UnwrapSimilarPointerTypes(FromType, ToType)) {
+    // Within each iteration of the loop, we check the qualifiers to
+    // determine if this still looks like a qualification
+    // conversion. Then, if all is well, we unwrap one more level of
+    // pointers or pointers-to-members and do it all again
+    // until there are no more pointers or pointers-to-members left to
+    // unwrap.
+    UnwrappedAnyPointer = true;
+
+    Qualifiers FromQuals = FromType.getQualifiers();
+    Qualifiers ToQuals = ToType.getQualifiers();
+    
+    // Objective-C ARC:
+    //   Check Objective-C lifetime conversions.
+    if (FromQuals.getObjCLifetime() != ToQuals.getObjCLifetime() &&
+        UnwrappedAnyPointer) {
+      if (ToQuals.compatiblyIncludesObjCLifetime(FromQuals)) {
+        ObjCLifetimeConversion = true;
+        FromQuals.removeObjCLifetime();
+        ToQuals.removeObjCLifetime();
+      } else {
+        // Qualification conversions cannot cast between different
+        // Objective-C lifetime qualifiers.
+        return false;
+      }
+    }
+    
+    // Allow addition/removal of GC attributes but not changing GC attributes.
+    if (FromQuals.getObjCGCAttr() != ToQuals.getObjCGCAttr() &&
+        (!FromQuals.hasObjCGCAttr() || !ToQuals.hasObjCGCAttr())) {
+      FromQuals.removeObjCGCAttr();
+      ToQuals.removeObjCGCAttr();
+    }
+    
+    //   -- for every j > 0, if const is in cv 1,j then const is in cv
+    //      2,j, and similarly for volatile.
+    if (!CStyle && !ToQuals.compatiblyIncludes(FromQuals))
+      return false;
+
+    //   -- if the cv 1,j and cv 2,j are different, then const is in
+    //      every cv for 0 < k < j.
+    if (!CStyle && FromQuals.getCVRQualifiers() != ToQuals.getCVRQualifiers()
+        && !PreviousToQualsIncludeConst)
+      return false;
+
+    // Keep track of whether all prior cv-qualifiers in the "to" type
+    // include const.
+    PreviousToQualsIncludeConst
+      = PreviousToQualsIncludeConst && ToQuals.hasConst();
+  }
+
+  // We are left with FromType and ToType being the pointee types
+  // after unwrapping the original FromType and ToType the same number
+  // of types. If we unwrapped any pointers, and if FromType and
+  // ToType have the same unqualified type (since we checked
+  // qualifiers above), then this is a qualification conversion.
+  return UnwrappedAnyPointer && Context.hasSameUnqualifiedType(FromType,ToType);
+}
+
+/// \brief - Determine whether this is a conversion from a scalar type to an
+/// atomic type.
+///
+/// If successful, updates \c SCS's second and third steps in the conversion
+/// sequence to finish the conversion.
+static bool tryAtomicConversion(Sema &S, Expr *From, QualType ToType,
+                                bool InOverloadResolution,
+                                StandardConversionSequence &SCS,
+                                bool CStyle) {
+  const AtomicType *ToAtomic = ToType->getAs<AtomicType>();
+  if (!ToAtomic)
+    return false;
+  
+  StandardConversionSequence InnerSCS;
+  if (!IsStandardConversion(S, From, ToAtomic->getValueType(), 
+                            InOverloadResolution, InnerSCS,
+                            CStyle, /*AllowObjCWritebackConversion=*/false))
+    return false;
+  
+  SCS.Second = InnerSCS.Second;
+  SCS.setToType(1, InnerSCS.getToType(1));
+  SCS.Third = InnerSCS.Third;
+  SCS.QualificationIncludesObjCLifetime
+    = InnerSCS.QualificationIncludesObjCLifetime;
+  SCS.setToType(2, InnerSCS.getToType(2));
+  return true;
+}
+
+static bool isFirstArgumentCompatibleWithType(ASTContext &Context,
+                                              CXXConstructorDecl *Constructor,
+                                              QualType Type) {
+  const FunctionProtoType *CtorType =
+      Constructor->getType()->getAs<FunctionProtoType>();
+  if (CtorType->getNumArgs() > 0) {
+    QualType FirstArg = CtorType->getArgType(0);
+    if (Context.hasSameUnqualifiedType(Type, FirstArg.getNonReferenceType()))
+      return true;
+  }
+  return false;
+}
+
+static OverloadingResult
+IsInitializerListConstructorConversion(Sema &S, Expr *From, QualType ToType,
+                                       CXXRecordDecl *To,
+                                       UserDefinedConversionSequence &User,
+                                       OverloadCandidateSet &CandidateSet,
+                                       bool AllowExplicit) {
+  DeclContext::lookup_iterator Con, ConEnd;
+  for (llvm::tie(Con, ConEnd) = S.LookupConstructors(To);
+       Con != ConEnd; ++Con) {
+    NamedDecl *D = *Con;
+    DeclAccessPair FoundDecl = DeclAccessPair::make(D, D->getAccess());
+
+    // Find the constructor (which may be a template).
+    CXXConstructorDecl *Constructor = 0;
+    FunctionTemplateDecl *ConstructorTmpl
+      = dyn_cast<FunctionTemplateDecl>(D);
+    if (ConstructorTmpl)
+      Constructor
+        = cast<CXXConstructorDecl>(ConstructorTmpl->getTemplatedDecl());
+    else
+      Constructor = cast<CXXConstructorDecl>(D);
+
+    bool Usable = !Constructor->isInvalidDecl() &&
+                  S.isInitListConstructor(Constructor) &&
+                  (AllowExplicit || !Constructor->isExplicit());
+    if (Usable) {
+      // If the first argument is (a reference to) the target type,
+      // suppress conversions.
+      bool SuppressUserConversions =
+          isFirstArgumentCompatibleWithType(S.Context, Constructor, ToType);
+      if (ConstructorTmpl)
+        S.AddTemplateOverloadCandidate(ConstructorTmpl, FoundDecl,
+                                       /*ExplicitArgs*/ 0,
+                                       From, CandidateSet,
+                                       SuppressUserConversions);
+      else
+        S.AddOverloadCandidate(Constructor, FoundDecl,
+                               From, CandidateSet,
+                               SuppressUserConversions);
+    }
+  }
+
+  bool HadMultipleCandidates = (CandidateSet.size() > 1);
+
+  OverloadCandidateSet::iterator Best;
+  switch (CandidateSet.BestViableFunction(S, From->getLocStart(), Best, true)) {
+  case OR_Success: {
+    // Record the standard conversion we used and the conversion function.
+    CXXConstructorDecl *Constructor = cast<CXXConstructorDecl>(Best->Function);
+    S.MarkFunctionReferenced(From->getLocStart(), Constructor);
+
+    QualType ThisType = Constructor->getThisType(S.Context);
+    // Initializer lists don't have conversions as such.
+    User.Before.setAsIdentityConversion();
+    User.HadMultipleCandidates = HadMultipleCandidates;
+    User.ConversionFunction = Constructor;
+    User.FoundConversionFunction = Best->FoundDecl;
+    User.After.setAsIdentityConversion();
+    User.After.setFromType(ThisType->getAs<PointerType>()->getPointeeType());
+    User.After.setAllToTypes(ToType);
+    return OR_Success;
+  }
+
+  case OR_No_Viable_Function:
+    return OR_No_Viable_Function;
+  case OR_Deleted:
+    return OR_Deleted;
+  case OR_Ambiguous:
+    return OR_Ambiguous;
+  }
+
+  llvm_unreachable("Invalid OverloadResult!");
+}
+
+/// Determines whether there is a user-defined conversion sequence
+/// (C++ [over.ics.user]) that converts expression From to the type
+/// ToType. If such a conversion exists, User will contain the
+/// user-defined conversion sequence that performs such a conversion
+/// and this routine will return true. Otherwise, this routine returns
+/// false and User is unspecified.
+///
+/// \param AllowExplicit  true if the conversion should consider C++0x
+/// "explicit" conversion functions as well as non-explicit conversion
+/// functions (C++0x [class.conv.fct]p2).
+static OverloadingResult
+IsUserDefinedConversion(Sema &S, Expr *From, QualType ToType,
+                        UserDefinedConversionSequence &User,
+                        OverloadCandidateSet &CandidateSet,
+                        bool AllowExplicit) {
+  // Whether we will only visit constructors.
+  bool ConstructorsOnly = false;
+
+  // If the type we are conversion to is a class type, enumerate its
+  // constructors.
+  if (const RecordType *ToRecordType = ToType->getAs<RecordType>()) {
+    // C++ [over.match.ctor]p1:
+    //   When objects of class type are direct-initialized (8.5), or
+    //   copy-initialized from an expression of the same or a
+    //   derived class type (8.5), overload resolution selects the
+    //   constructor. [...] For copy-initialization, the candidate
+    //   functions are all the converting constructors (12.3.1) of
+    //   that class. The argument list is the expression-list within
+    //   the parentheses of the initializer.
+    if (S.Context.hasSameUnqualifiedType(ToType, From->getType()) ||
+        (From->getType()->getAs<RecordType>() &&
+         S.IsDerivedFrom(From->getType(), ToType)))
+      ConstructorsOnly = true;
+
+    S.RequireCompleteType(From->getLocStart(), ToType, S.PDiag());
+    // RequireCompleteType may have returned true due to some invalid decl
+    // during template instantiation, but ToType may be complete enough now
+    // to try to recover.
+    if (ToType->isIncompleteType()) {
+      // We're not going to find any constructors.
+    } else if (CXXRecordDecl *ToRecordDecl
+                 = dyn_cast<CXXRecordDecl>(ToRecordType->getDecl())) {
+
+      Expr **Args = &From;
+      unsigned NumArgs = 1;
+      bool ListInitializing = false;
+      if (InitListExpr *InitList = dyn_cast<InitListExpr>(From)) {
+        // But first, see if there is an init-list-contructor that will work.
+        OverloadingResult Result = IsInitializerListConstructorConversion(
+            S, From, ToType, ToRecordDecl, User, CandidateSet, AllowExplicit);
+        if (Result != OR_No_Viable_Function)
+          return Result;
+        // Never mind.
+        CandidateSet.clear();
+
+        // If we're list-initializing, we pass the individual elements as
+        // arguments, not the entire list.
+        Args = InitList->getInits();
+        NumArgs = InitList->getNumInits();
+        ListInitializing = true;
+      }
+
+      DeclContext::lookup_iterator Con, ConEnd;
+      for (llvm::tie(Con, ConEnd) = S.LookupConstructors(ToRecordDecl);
+           Con != ConEnd; ++Con) {
+        NamedDecl *D = *Con;
+        DeclAccessPair FoundDecl = DeclAccessPair::make(D, D->getAccess());
+
+        // Find the constructor (which may be a template).
+        CXXConstructorDecl *Constructor = 0;
+        FunctionTemplateDecl *ConstructorTmpl
+          = dyn_cast<FunctionTemplateDecl>(D);
+        if (ConstructorTmpl)
+          Constructor
+            = cast<CXXConstructorDecl>(ConstructorTmpl->getTemplatedDecl());
+        else
+          Constructor = cast<CXXConstructorDecl>(D);
+
+        bool Usable = !Constructor->isInvalidDecl();
+        if (ListInitializing)
+          Usable = Usable && (AllowExplicit || !Constructor->isExplicit());
+        else
+          Usable = Usable &&Constructor->isConvertingConstructor(AllowExplicit);
+        if (Usable) {
+          bool SuppressUserConversions = !ConstructorsOnly;
+          if (SuppressUserConversions && ListInitializing) {
+            SuppressUserConversions = false;
+            if (NumArgs == 1) {
+              // If the first argument is (a reference to) the target type,
+              // suppress conversions.
+              SuppressUserConversions = isFirstArgumentCompatibleWithType(
+                                                S.Context, Constructor, ToType);
+            }
+          }
+          if (ConstructorTmpl)
+            S.AddTemplateOverloadCandidate(ConstructorTmpl, FoundDecl,
+                                           /*ExplicitArgs*/ 0,
+                                           llvm::makeArrayRef(Args, NumArgs),
+                                           CandidateSet, SuppressUserConversions);
+          else
+            // Allow one user-defined conversion when user specifies a
+            // From->ToType conversion via an static cast (c-style, etc).
+            S.AddOverloadCandidate(Constructor, FoundDecl,
+                                   llvm::makeArrayRef(Args, NumArgs),
+                                   CandidateSet, SuppressUserConversions);
+        }
+      }
+    }
+  }
+
+  // Enumerate conversion functions, if we're allowed to.
+  if (ConstructorsOnly || isa<InitListExpr>(From)) {
+  } else if (S.RequireCompleteType(From->getLocStart(), From->getType(),
+                                   S.PDiag(0) << From->getSourceRange())) {
+    // No conversion functions from incomplete types.
+  } else if (const RecordType *FromRecordType
+                                   = From->getType()->getAs<RecordType>()) {
+    if (CXXRecordDecl *FromRecordDecl
+         = dyn_cast<CXXRecordDecl>(FromRecordType->getDecl())) {
+      // Add all of the conversion functions as candidates.
+      const UnresolvedSetImpl *Conversions
+        = FromRecordDecl->getVisibleConversionFunctions();
+      for (UnresolvedSetImpl::iterator I = Conversions->begin(),
+             E = Conversions->end(); I != E; ++I) {
+        DeclAccessPair FoundDecl = I.getPair();
+        NamedDecl *D = FoundDecl.getDecl();
+        CXXRecordDecl *ActingContext = cast<CXXRecordDecl>(D->getDeclContext());
+        if (isa<UsingShadowDecl>(D))
+          D = cast<UsingShadowDecl>(D)->getTargetDecl();
+
+        CXXConversionDecl *Conv;
+        FunctionTemplateDecl *ConvTemplate;
+        if ((ConvTemplate = dyn_cast<FunctionTemplateDecl>(D)))
+          Conv = cast<CXXConversionDecl>(ConvTemplate->getTemplatedDecl());
+        else
+          Conv = cast<CXXConversionDecl>(D);
+
+        if (AllowExplicit || !Conv->isExplicit()) {
+          if (ConvTemplate)
+            S.AddTemplateConversionCandidate(ConvTemplate, FoundDecl,
+                                             ActingContext, From, ToType,
+                                             CandidateSet);
+          else
+            S.AddConversionCandidate(Conv, FoundDecl, ActingContext,
+                                     From, ToType, CandidateSet);
+        }
+      }
+    }
+  }
+
+  bool HadMultipleCandidates = (CandidateSet.size() > 1);
+
+  OverloadCandidateSet::iterator Best;
+  switch (CandidateSet.BestViableFunction(S, From->getLocStart(), Best, true)) {
+  case OR_Success:
+    // Record the standard conversion we used and the conversion function.
+    if (CXXConstructorDecl *Constructor
+          = dyn_cast<CXXConstructorDecl>(Best->Function)) {
+      S.MarkFunctionReferenced(From->getLocStart(), Constructor);
+
+      // C++ [over.ics.user]p1:
+      //   If the user-defined conversion is specified by a
+      //   constructor (12.3.1), the initial standard conversion
+      //   sequence converts the source type to the type required by
+      //   the argument of the constructor.
+      //
+      QualType ThisType = Constructor->getThisType(S.Context);
+      if (isa<InitListExpr>(From)) {
+        // Initializer lists don't have conversions as such.
+        User.Before.setAsIdentityConversion();
+      } else {
+        if (Best->Conversions[0].isEllipsis())
+          User.EllipsisConversion = true;
+        else {
+          User.Before = Best->Conversions[0].Standard;
+          User.EllipsisConversion = false;
+        }
+      }
+      User.HadMultipleCandidates = HadMultipleCandidates;
+      User.ConversionFunction = Constructor;
+      User.FoundConversionFunction = Best->FoundDecl;
+      User.After.setAsIdentityConversion();
+      User.After.setFromType(ThisType->getAs<PointerType>()->getPointeeType());
+      User.After.setAllToTypes(ToType);
+      return OR_Success;
+    }
+    if (CXXConversionDecl *Conversion
+                 = dyn_cast<CXXConversionDecl>(Best->Function)) {
+      S.MarkFunctionReferenced(From->getLocStart(), Conversion);
+
+      // C++ [over.ics.user]p1:
+      //
+      //   [...] If the user-defined conversion is specified by a
+      //   conversion function (12.3.2), the initial standard
+      //   conversion sequence converts the source type to the
+      //   implicit object parameter of the conversion function.
+      User.Before = Best->Conversions[0].Standard;
+      User.HadMultipleCandidates = HadMultipleCandidates;
+      User.ConversionFunction = Conversion;
+      User.FoundConversionFunction = Best->FoundDecl;
+      User.EllipsisConversion = false;
+
+      // C++ [over.ics.user]p2:
+      //   The second standard conversion sequence converts the
+      //   result of the user-defined conversion to the target type
+      //   for the sequence. Since an implicit conversion sequence
+      //   is an initialization, the special rules for
+      //   initialization by user-defined conversion apply when
+      //   selecting the best user-defined conversion for a
+      //   user-defined conversion sequence (see 13.3.3 and
+      //   13.3.3.1).
+      User.After = Best->FinalConversion;
+      return OR_Success;
+    }
+    llvm_unreachable("Not a constructor or conversion function?");
+
+  case OR_No_Viable_Function:
+    return OR_No_Viable_Function;
+  case OR_Deleted:
+    // No conversion here! We're done.
+    return OR_Deleted;
+
+  case OR_Ambiguous:
+    return OR_Ambiguous;
+  }
+
+  llvm_unreachable("Invalid OverloadResult!");
+}
+
+bool
+Sema::DiagnoseMultipleUserDefinedConversion(Expr *From, QualType ToType) {
+  ImplicitConversionSequence ICS;
+  OverloadCandidateSet CandidateSet(From->getExprLoc());
+  OverloadingResult OvResult =
+    IsUserDefinedConversion(*this, From, ToType, ICS.UserDefined,
+                            CandidateSet, false);
+  if (OvResult == OR_Ambiguous)
+    Diag(From->getLocStart(),
+         diag::err_typecheck_ambiguous_condition)
+          << From->getType() << ToType << From->getSourceRange();
+  else if (OvResult == OR_No_Viable_Function && !CandidateSet.empty())
+    Diag(From->getLocStart(),
+         diag::err_typecheck_nonviable_condition)
+    << From->getType() << ToType << From->getSourceRange();
+  else
+    return false;
+  CandidateSet.NoteCandidates(*this, OCD_AllCandidates, From);
+  return true;
+}
+
+/// \brief Compare the user-defined conversion functions or constructors
+/// of two user-defined conversion sequences to determine whether any ordering
+/// is possible.
+static ImplicitConversionSequence::CompareKind
+compareConversionFunctions(Sema &S,
+                           FunctionDecl *Function1,
+                           FunctionDecl *Function2) {
+  if (!S.getLangOpts().ObjC1 || !S.getLangOpts().CPlusPlus0x)
+    return ImplicitConversionSequence::Indistinguishable;
+  
+  // Objective-C++:
+  //   If both conversion functions are implicitly-declared conversions from
+  //   a lambda closure type to a function pointer and a block pointer, 
+  //   respectively, always prefer the conversion to a function pointer,
+  //   because the function pointer is more lightweight and is more likely
+  //   to keep code working.
+  CXXConversionDecl *Conv1 = dyn_cast<CXXConversionDecl>(Function1);
+  if (!Conv1)
+    return ImplicitConversionSequence::Indistinguishable;
+    
+  CXXConversionDecl *Conv2 = dyn_cast<CXXConversionDecl>(Function2);
+  if (!Conv2)
+    return ImplicitConversionSequence::Indistinguishable;
+  
+  if (Conv1->getParent()->isLambda() && Conv2->getParent()->isLambda()) {
+    bool Block1 = Conv1->getConversionType()->isBlockPointerType();
+    bool Block2 = Conv2->getConversionType()->isBlockPointerType();
+    if (Block1 != Block2)
+      return Block1? ImplicitConversionSequence::Worse 
+                   : ImplicitConversionSequence::Better;
+  }
+
+  return ImplicitConversionSequence::Indistinguishable;
+}
+  
+/// CompareImplicitConversionSequences - Compare two implicit
+/// conversion sequences to determine whether one is better than the
+/// other or if they are indistinguishable (C++ 13.3.3.2).
+static ImplicitConversionSequence::CompareKind
+CompareImplicitConversionSequences(Sema &S,
+                                   const ImplicitConversionSequence& ICS1,
+                                   const ImplicitConversionSequence& ICS2)
+{
+  // (C++ 13.3.3.2p2): When comparing the basic forms of implicit
+  // conversion sequences (as defined in 13.3.3.1)
+  //   -- a standard conversion sequence (13.3.3.1.1) is a better
+  //      conversion sequence than a user-defined conversion sequence or
+  //      an ellipsis conversion sequence, and
+  //   -- a user-defined conversion sequence (13.3.3.1.2) is a better
+  //      conversion sequence than an ellipsis conversion sequence
+  //      (13.3.3.1.3).
+  //
+  // C++0x [over.best.ics]p10:
+  //   For the purpose of ranking implicit conversion sequences as
+  //   described in 13.3.3.2, the ambiguous conversion sequence is
+  //   treated as a user-defined sequence that is indistinguishable
+  //   from any other user-defined conversion sequence.
+  if (ICS1.getKindRank() < ICS2.getKindRank())
+    return ImplicitConversionSequence::Better;
+  if (ICS2.getKindRank() < ICS1.getKindRank())
+    return ImplicitConversionSequence::Worse;
+
+  // The following checks require both conversion sequences to be of
+  // the same kind.
+  if (ICS1.getKind() != ICS2.getKind())
+    return ImplicitConversionSequence::Indistinguishable;
+
+  ImplicitConversionSequence::CompareKind Result =
+      ImplicitConversionSequence::Indistinguishable;
+
+  // Two implicit conversion sequences of the same form are
+  // indistinguishable conversion sequences unless one of the
+  // following rules apply: (C++ 13.3.3.2p3):
+  if (ICS1.isStandard())
+    Result = CompareStandardConversionSequences(S,
+                                                ICS1.Standard, ICS2.Standard);
+  else if (ICS1.isUserDefined()) {
+    // User-defined conversion sequence U1 is a better conversion
+    // sequence than another user-defined conversion sequence U2 if
+    // they contain the same user-defined conversion function or
+    // constructor and if the second standard conversion sequence of
+    // U1 is better than the second standard conversion sequence of
+    // U2 (C++ 13.3.3.2p3).
+    if (ICS1.UserDefined.ConversionFunction ==
+          ICS2.UserDefined.ConversionFunction)
+      Result = CompareStandardConversionSequences(S,
+                                                  ICS1.UserDefined.After,
+                                                  ICS2.UserDefined.After);
+    else
+      Result = compareConversionFunctions(S, 
+                                          ICS1.UserDefined.ConversionFunction,
+                                          ICS2.UserDefined.ConversionFunction);
+  }
+
+  // List-initialization sequence L1 is a better conversion sequence than
+  // list-initialization sequence L2 if L1 converts to std::initializer_list<X>
+  // for some X and L2 does not.
+  if (Result == ImplicitConversionSequence::Indistinguishable &&
+      !ICS1.isBad() &&
+      ICS1.isListInitializationSequence() &&
+      ICS2.isListInitializationSequence()) {
+    if (ICS1.isStdInitializerListElement() &&
+        !ICS2.isStdInitializerListElement())
+      return ImplicitConversionSequence::Better;
+    if (!ICS1.isStdInitializerListElement() &&
+        ICS2.isStdInitializerListElement())
+      return ImplicitConversionSequence::Worse;
+  }
+
+  return Result;
+}
+
+static bool hasSimilarType(ASTContext &Context, QualType T1, QualType T2) {
+  while (Context.UnwrapSimilarPointerTypes(T1, T2)) {
+    Qualifiers Quals;
+    T1 = Context.getUnqualifiedArrayType(T1, Quals);
+    T2 = Context.getUnqualifiedArrayType(T2, Quals);
+  }
+
+  return Context.hasSameUnqualifiedType(T1, T2);
+}
+
+// Per 13.3.3.2p3, compare the given standard conversion sequences to
+// determine if one is a proper subset of the other.
+static ImplicitConversionSequence::CompareKind
+compareStandardConversionSubsets(ASTContext &Context,
+                                 const StandardConversionSequence& SCS1,
+                                 const StandardConversionSequence& SCS2) {
+  ImplicitConversionSequence::CompareKind Result
+    = ImplicitConversionSequence::Indistinguishable;
+
+  // the identity conversion sequence is considered to be a subsequence of
+  // any non-identity conversion sequence
+  if (SCS1.isIdentityConversion() && !SCS2.isIdentityConversion())
+    return ImplicitConversionSequence::Better;
+  else if (!SCS1.isIdentityConversion() && SCS2.isIdentityConversion())
+    return ImplicitConversionSequence::Worse;
+
+  if (SCS1.Second != SCS2.Second) {
+    if (SCS1.Second == ICK_Identity)
+      Result = ImplicitConversionSequence::Better;
+    else if (SCS2.Second == ICK_Identity)
+      Result = ImplicitConversionSequence::Worse;
+    else
+      return ImplicitConversionSequence::Indistinguishable;
+  } else if (!hasSimilarType(Context, SCS1.getToType(1), SCS2.getToType(1)))
+    return ImplicitConversionSequence::Indistinguishable;
+
+  if (SCS1.Third == SCS2.Third) {
+    return Context.hasSameType(SCS1.getToType(2), SCS2.getToType(2))? Result
+                             : ImplicitConversionSequence::Indistinguishable;
+  }
+
+  if (SCS1.Third == ICK_Identity)
+    return Result == ImplicitConversionSequence::Worse
+             ? ImplicitConversionSequence::Indistinguishable
+             : ImplicitConversionSequence::Better;
+
+  if (SCS2.Third == ICK_Identity)
+    return Result == ImplicitConversionSequence::Better
+             ? ImplicitConversionSequence::Indistinguishable
+             : ImplicitConversionSequence::Worse;
+
+  return ImplicitConversionSequence::Indistinguishable;
+}
+
+/// \brief Determine whether one of the given reference bindings is better
+/// than the other based on what kind of bindings they are.
+static bool isBetterReferenceBindingKind(const StandardConversionSequence &SCS1,
+                                       const StandardConversionSequence &SCS2) {
+  // C++0x [over.ics.rank]p3b4:
+  //   -- S1 and S2 are reference bindings (8.5.3) and neither refers to an
+  //      implicit object parameter of a non-static member function declared
+  //      without a ref-qualifier, and *either* S1 binds an rvalue reference
+  //      to an rvalue and S2 binds an lvalue reference *or S1 binds an
+  //      lvalue reference to a function lvalue and S2 binds an rvalue
+  //      reference*.
+  //
+  // FIXME: Rvalue references. We're going rogue with the above edits,
+  // because the semantics in the current C++0x working paper (N3225 at the
+  // time of this writing) break the standard definition of std::forward
+  // and std::reference_wrapper when dealing with references to functions.
+  // Proposed wording changes submitted to CWG for consideration.
+  if (SCS1.BindsImplicitObjectArgumentWithoutRefQualifier ||
+      SCS2.BindsImplicitObjectArgumentWithoutRefQualifier)
+    return false;
+
+  return (!SCS1.IsLvalueReference && SCS1.BindsToRvalue &&
+          SCS2.IsLvalueReference) ||
+         (SCS1.IsLvalueReference && SCS1.BindsToFunctionLvalue &&
+          !SCS2.IsLvalueReference);
+}
+
+/// CompareStandardConversionSequences - Compare two standard
+/// conversion sequences to determine whether one is better than the
+/// other or if they are indistinguishable (C++ 13.3.3.2p3).
+static ImplicitConversionSequence::CompareKind
+CompareStandardConversionSequences(Sema &S,
+                                   const StandardConversionSequence& SCS1,
+                                   const StandardConversionSequence& SCS2)
+{
+  // Standard conversion sequence S1 is a better conversion sequence
+  // than standard conversion sequence S2 if (C++ 13.3.3.2p3):
+
+  //  -- S1 is a proper subsequence of S2 (comparing the conversion
+  //     sequences in the canonical form defined by 13.3.3.1.1,
+  //     excluding any Lvalue Transformation; the identity conversion
+  //     sequence is considered to be a subsequence of any
+  //     non-identity conversion sequence) or, if not that,
+  if (ImplicitConversionSequence::CompareKind CK
+        = compareStandardConversionSubsets(S.Context, SCS1, SCS2))
+    return CK;
+
+  //  -- the rank of S1 is better than the rank of S2 (by the rules
+  //     defined below), or, if not that,
+  ImplicitConversionRank Rank1 = SCS1.getRank();
+  ImplicitConversionRank Rank2 = SCS2.getRank();
+  if (Rank1 < Rank2)
+    return ImplicitConversionSequence::Better;
+  else if (Rank2 < Rank1)
+    return ImplicitConversionSequence::Worse;
+
+  // (C++ 13.3.3.2p4): Two conversion sequences with the same rank
+  // are indistinguishable unless one of the following rules
+  // applies:
+
+  //   A conversion that is not a conversion of a pointer, or
+  //   pointer to member, to bool is better than another conversion
+  //   that is such a conversion.
+  if (SCS1.isPointerConversionToBool() != SCS2.isPointerConversionToBool())
+    return SCS2.isPointerConversionToBool()
+             ? ImplicitConversionSequence::Better
+             : ImplicitConversionSequence::Worse;
+
+  // C++ [over.ics.rank]p4b2:
+  //
+  //   If class B is derived directly or indirectly from class A,
+  //   conversion of B* to A* is better than conversion of B* to
+  //   void*, and conversion of A* to void* is better than conversion
+  //   of B* to void*.
+  bool SCS1ConvertsToVoid
+    = SCS1.isPointerConversionToVoidPointer(S.Context);
+  bool SCS2ConvertsToVoid
+    = SCS2.isPointerConversionToVoidPointer(S.Context);
+  if (SCS1ConvertsToVoid != SCS2ConvertsToVoid) {
+    // Exactly one of the conversion sequences is a conversion to
+    // a void pointer; it's the worse conversion.
+    return SCS2ConvertsToVoid ? ImplicitConversionSequence::Better
+                              : ImplicitConversionSequence::Worse;
+  } else if (!SCS1ConvertsToVoid && !SCS2ConvertsToVoid) {
+    // Neither conversion sequence converts to a void pointer; compare
+    // their derived-to-base conversions.
+    if (ImplicitConversionSequence::CompareKind DerivedCK
+          = CompareDerivedToBaseConversions(S, SCS1, SCS2))
+      return DerivedCK;
+  } else if (SCS1ConvertsToVoid && SCS2ConvertsToVoid &&
+             !S.Context.hasSameType(SCS1.getFromType(), SCS2.getFromType())) {
+    // Both conversion sequences are conversions to void
+    // pointers. Compare the source types to determine if there's an
+    // inheritance relationship in their sources.
+    QualType FromType1 = SCS1.getFromType();
+    QualType FromType2 = SCS2.getFromType();
+
+    // Adjust the types we're converting from via the array-to-pointer
+    // conversion, if we need to.
+    if (SCS1.First == ICK_Array_To_Pointer)
+      FromType1 = S.Context.getArrayDecayedType(FromType1);
+    if (SCS2.First == ICK_Array_To_Pointer)
+      FromType2 = S.Context.getArrayDecayedType(FromType2);
+
+    QualType FromPointee1 = FromType1->getPointeeType().getUnqualifiedType();
+    QualType FromPointee2 = FromType2->getPointeeType().getUnqualifiedType();
+
+    if (S.IsDerivedFrom(FromPointee2, FromPointee1))
+      return ImplicitConversionSequence::Better;
+    else if (S.IsDerivedFrom(FromPointee1, FromPointee2))
+      return ImplicitConversionSequence::Worse;
+
+    // Objective-C++: If one interface is more specific than the
+    // other, it is the better one.
+    const ObjCObjectPointerType* FromObjCPtr1
+      = FromType1->getAs<ObjCObjectPointerType>();
+    const ObjCObjectPointerType* FromObjCPtr2
+      = FromType2->getAs<ObjCObjectPointerType>();
+    if (FromObjCPtr1 && FromObjCPtr2) {
+      bool AssignLeft = S.Context.canAssignObjCInterfaces(FromObjCPtr1, 
+                                                          FromObjCPtr2);
+      bool AssignRight = S.Context.canAssignObjCInterfaces(FromObjCPtr2, 
+                                                           FromObjCPtr1);
+      if (AssignLeft != AssignRight) {
+        return AssignLeft? ImplicitConversionSequence::Better
+                         : ImplicitConversionSequence::Worse;
+      }
+    }
+  }
+
+  // Compare based on qualification conversions (C++ 13.3.3.2p3,
+  // bullet 3).
+  if (ImplicitConversionSequence::CompareKind QualCK
+        = CompareQualificationConversions(S, SCS1, SCS2))
+    return QualCK;
+
+  if (SCS1.ReferenceBinding && SCS2.ReferenceBinding) {
+    // Check for a better reference binding based on the kind of bindings.
+    if (isBetterReferenceBindingKind(SCS1, SCS2))
+      return ImplicitConversionSequence::Better;
+    else if (isBetterReferenceBindingKind(SCS2, SCS1))
+      return ImplicitConversionSequence::Worse;
+
+    // C++ [over.ics.rank]p3b4:
+    //   -- S1 and S2 are reference bindings (8.5.3), and the types to
+    //      which the references refer are the same type except for
+    //      top-level cv-qualifiers, and the type to which the reference
+    //      initialized by S2 refers is more cv-qualified than the type
+    //      to which the reference initialized by S1 refers.
+    QualType T1 = SCS1.getToType(2);
+    QualType T2 = SCS2.getToType(2);
+    T1 = S.Context.getCanonicalType(T1);
+    T2 = S.Context.getCanonicalType(T2);
+    Qualifiers T1Quals, T2Quals;
+    QualType UnqualT1 = S.Context.getUnqualifiedArrayType(T1, T1Quals);
+    QualType UnqualT2 = S.Context.getUnqualifiedArrayType(T2, T2Quals);
+    if (UnqualT1 == UnqualT2) {
+      // Objective-C++ ARC: If the references refer to objects with different
+      // lifetimes, prefer bindings that don't change lifetime.
+      if (SCS1.ObjCLifetimeConversionBinding != 
+                                          SCS2.ObjCLifetimeConversionBinding) {
+        return SCS1.ObjCLifetimeConversionBinding
+                                           ? ImplicitConversionSequence::Worse
+                                           : ImplicitConversionSequence::Better;
+      }
+      
+      // If the type is an array type, promote the element qualifiers to the
+      // type for comparison.
+      if (isa<ArrayType>(T1) && T1Quals)
+        T1 = S.Context.getQualifiedType(UnqualT1, T1Quals);
+      if (isa<ArrayType>(T2) && T2Quals)
+        T2 = S.Context.getQualifiedType(UnqualT2, T2Quals);
+      if (T2.isMoreQualifiedThan(T1))
+        return ImplicitConversionSequence::Better;
+      else if (T1.isMoreQualifiedThan(T2))
+        return ImplicitConversionSequence::Worse;      
+    }
+  }
+
+  // In Microsoft mode, prefer an integral conversion to a
+  // floating-to-integral conversion if the integral conversion
+  // is between types of the same size.
+  // For example:
+  // void f(float);
+  // void f(int);
+  // int main {
+  //    long a;
+  //    f(a);
+  // }
+  // Here, MSVC will call f(int) instead of generating a compile error
+  // as clang will do in standard mode.
+  if (S.getLangOpts().MicrosoftMode &&
+      SCS1.Second == ICK_Integral_Conversion &&
+      SCS2.Second == ICK_Floating_Integral && 
+      S.Context.getTypeSize(SCS1.getFromType()) ==
+      S.Context.getTypeSize(SCS1.getToType(2)))
+    return ImplicitConversionSequence::Better;
+
+  return ImplicitConversionSequence::Indistinguishable;
+}
+
+/// CompareQualificationConversions - Compares two standard conversion
+/// sequences to determine whether they can be ranked based on their
+/// qualification conversions (C++ 13.3.3.2p3 bullet 3).
+ImplicitConversionSequence::CompareKind
+CompareQualificationConversions(Sema &S,
+                                const StandardConversionSequence& SCS1,
+                                const StandardConversionSequence& SCS2) {
+  // C++ 13.3.3.2p3:
+  //  -- S1 and S2 differ only in their qualification conversion and
+  //     yield similar types T1 and T2 (C++ 4.4), respectively, and the
+  //     cv-qualification signature of type T1 is a proper subset of
+  //     the cv-qualification signature of type T2, and S1 is not the
+  //     deprecated string literal array-to-pointer conversion (4.2).
+  if (SCS1.First != SCS2.First || SCS1.Second != SCS2.Second ||
+      SCS1.Third != SCS2.Third || SCS1.Third != ICK_Qualification)
+    return ImplicitConversionSequence::Indistinguishable;
+
+  // FIXME: the example in the standard doesn't use a qualification
+  // conversion (!)
+  QualType T1 = SCS1.getToType(2);
+  QualType T2 = SCS2.getToType(2);
+  T1 = S.Context.getCanonicalType(T1);
+  T2 = S.Context.getCanonicalType(T2);
+  Qualifiers T1Quals, T2Quals;
+  QualType UnqualT1 = S.Context.getUnqualifiedArrayType(T1, T1Quals);
+  QualType UnqualT2 = S.Context.getUnqualifiedArrayType(T2, T2Quals);
+
+  // If the types are the same, we won't learn anything by unwrapped
+  // them.
+  if (UnqualT1 == UnqualT2)
+    return ImplicitConversionSequence::Indistinguishable;
+
+  // If the type is an array type, promote the element qualifiers to the type
+  // for comparison.
+  if (isa<ArrayType>(T1) && T1Quals)
+    T1 = S.Context.getQualifiedType(UnqualT1, T1Quals);
+  if (isa<ArrayType>(T2) && T2Quals)
+    T2 = S.Context.getQualifiedType(UnqualT2, T2Quals);
+
+  ImplicitConversionSequence::CompareKind Result
+    = ImplicitConversionSequence::Indistinguishable;
+  
+  // Objective-C++ ARC:
+  //   Prefer qualification conversions not involving a change in lifetime
+  //   to qualification conversions that do not change lifetime.
+  if (SCS1.QualificationIncludesObjCLifetime != 
+                                      SCS2.QualificationIncludesObjCLifetime) {
+    Result = SCS1.QualificationIncludesObjCLifetime
+               ? ImplicitConversionSequence::Worse
+               : ImplicitConversionSequence::Better;
+  }
+  
+  while (S.Context.UnwrapSimilarPointerTypes(T1, T2)) {
+    // Within each iteration of the loop, we check the qualifiers to
+    // determine if this still looks like a qualification
+    // conversion. Then, if all is well, we unwrap one more level of
+    // pointers or pointers-to-members and do it all again
+    // until there are no more pointers or pointers-to-members left
+    // to unwrap. This essentially mimics what
+    // IsQualificationConversion does, but here we're checking for a
+    // strict subset of qualifiers.
+    if (T1.getCVRQualifiers() == T2.getCVRQualifiers())
+      // The qualifiers are the same, so this doesn't tell us anything
+      // about how the sequences rank.
+      ;
+    else if (T2.isMoreQualifiedThan(T1)) {
+      // T1 has fewer qualifiers, so it could be the better sequence.
+      if (Result == ImplicitConversionSequence::Worse)
+        // Neither has qualifiers that are a subset of the other's
+        // qualifiers.
+        return ImplicitConversionSequence::Indistinguishable;
+
+      Result = ImplicitConversionSequence::Better;
+    } else if (T1.isMoreQualifiedThan(T2)) {
+      // T2 has fewer qualifiers, so it could be the better sequence.
+      if (Result == ImplicitConversionSequence::Better)
+        // Neither has qualifiers that are a subset of the other's
+        // qualifiers.
+        return ImplicitConversionSequence::Indistinguishable;
+
+      Result = ImplicitConversionSequence::Worse;
+    } else {
+      // Qualifiers are disjoint.
+      return ImplicitConversionSequence::Indistinguishable;
+    }
+
+    // If the types after this point are equivalent, we're done.
+    if (S.Context.hasSameUnqualifiedType(T1, T2))
+      break;
+  }
+
+  // Check that the winning standard conversion sequence isn't using
+  // the deprecated string literal array to pointer conversion.
+  switch (Result) {
+  case ImplicitConversionSequence::Better:
+    if (SCS1.DeprecatedStringLiteralToCharPtr)
+      Result = ImplicitConversionSequence::Indistinguishable;
+    break;
+
+  case ImplicitConversionSequence::Indistinguishable:
+    break;
+
+  case ImplicitConversionSequence::Worse:
+    if (SCS2.DeprecatedStringLiteralToCharPtr)
+      Result = ImplicitConversionSequence::Indistinguishable;
+    break;
+  }
+
+  return Result;
+}
+
+/// CompareDerivedToBaseConversions - Compares two standard conversion
+/// sequences to determine whether they can be ranked based on their
+/// various kinds of derived-to-base conversions (C++
+/// [over.ics.rank]p4b3).  As part of these checks, we also look at
+/// conversions between Objective-C interface types.
+ImplicitConversionSequence::CompareKind
+CompareDerivedToBaseConversions(Sema &S,
+                                const StandardConversionSequence& SCS1,
+                                const StandardConversionSequence& SCS2) {
+  QualType FromType1 = SCS1.getFromType();
+  QualType ToType1 = SCS1.getToType(1);
+  QualType FromType2 = SCS2.getFromType();
+  QualType ToType2 = SCS2.getToType(1);
+
+  // Adjust the types we're converting from via the array-to-pointer
+  // conversion, if we need to.
+  if (SCS1.First == ICK_Array_To_Pointer)
+    FromType1 = S.Context.getArrayDecayedType(FromType1);
+  if (SCS2.First == ICK_Array_To_Pointer)
+    FromType2 = S.Context.getArrayDecayedType(FromType2);
+
+  // Canonicalize all of the types.
+  FromType1 = S.Context.getCanonicalType(FromType1);
+  ToType1 = S.Context.getCanonicalType(ToType1);
+  FromType2 = S.Context.getCanonicalType(FromType2);
+  ToType2 = S.Context.getCanonicalType(ToType2);
+
+  // C++ [over.ics.rank]p4b3:
+  //
+  //   If class B is derived directly or indirectly from class A and
+  //   class C is derived directly or indirectly from B,
+  //
+  // Compare based on pointer conversions.
+  if (SCS1.Second == ICK_Pointer_Conversion &&
+      SCS2.Second == ICK_Pointer_Conversion &&
+      /*FIXME: Remove if Objective-C id conversions get their own rank*/
+      FromType1->isPointerType() && FromType2->isPointerType() &&
+      ToType1->isPointerType() && ToType2->isPointerType()) {
+    QualType FromPointee1
+      = FromType1->getAs<PointerType>()->getPointeeType().getUnqualifiedType();
+    QualType ToPointee1
+      = ToType1->getAs<PointerType>()->getPointeeType().getUnqualifiedType();
+    QualType FromPointee2
+      = FromType2->getAs<PointerType>()->getPointeeType().getUnqualifiedType();
+    QualType ToPointee2
+      = ToType2->getAs<PointerType>()->getPointeeType().getUnqualifiedType();
+
+    //   -- conversion of C* to B* is better than conversion of C* to A*,
+    if (FromPointee1 == FromPointee2 && ToPointee1 != ToPointee2) {
+      if (S.IsDerivedFrom(ToPointee1, ToPointee2))
+        return ImplicitConversionSequence::Better;
+      else if (S.IsDerivedFrom(ToPointee2, ToPointee1))
+        return ImplicitConversionSequence::Worse;
+    }
+
+    //   -- conversion of B* to A* is better than conversion of C* to A*,
+    if (FromPointee1 != FromPointee2 && ToPointee1 == ToPointee2) {
+      if (S.IsDerivedFrom(FromPointee2, FromPointee1))
+        return ImplicitConversionSequence::Better;
+      else if (S.IsDerivedFrom(FromPointee1, FromPointee2))
+        return ImplicitConversionSequence::Worse;
+    }
+  } else if (SCS1.Second == ICK_Pointer_Conversion &&
+             SCS2.Second == ICK_Pointer_Conversion) {
+    const ObjCObjectPointerType *FromPtr1
+      = FromType1->getAs<ObjCObjectPointerType>();
+    const ObjCObjectPointerType *FromPtr2
+      = FromType2->getAs<ObjCObjectPointerType>();
+    const ObjCObjectPointerType *ToPtr1
+      = ToType1->getAs<ObjCObjectPointerType>();
+    const ObjCObjectPointerType *ToPtr2
+      = ToType2->getAs<ObjCObjectPointerType>();
+    
+    if (FromPtr1 && FromPtr2 && ToPtr1 && ToPtr2) {
+      // Apply the same conversion ranking rules for Objective-C pointer types
+      // that we do for C++ pointers to class types. However, we employ the
+      // Objective-C pseudo-subtyping relationship used for assignment of
+      // Objective-C pointer types.
+      bool FromAssignLeft
+        = S.Context.canAssignObjCInterfaces(FromPtr1, FromPtr2);
+      bool FromAssignRight
+        = S.Context.canAssignObjCInterfaces(FromPtr2, FromPtr1);
+      bool ToAssignLeft
+        = S.Context.canAssignObjCInterfaces(ToPtr1, ToPtr2);
+      bool ToAssignRight
+        = S.Context.canAssignObjCInterfaces(ToPtr2, ToPtr1);
+      
+      // A conversion to an a non-id object pointer type or qualified 'id' 
+      // type is better than a conversion to 'id'.
+      if (ToPtr1->isObjCIdType() &&
+          (ToPtr2->isObjCQualifiedIdType() || ToPtr2->getInterfaceDecl()))
+        return ImplicitConversionSequence::Worse;
+      if (ToPtr2->isObjCIdType() &&
+          (ToPtr1->isObjCQualifiedIdType() || ToPtr1->getInterfaceDecl()))
+        return ImplicitConversionSequence::Better;
+      
+      // A conversion to a non-id object pointer type is better than a 
+      // conversion to a qualified 'id' type 
+      if (ToPtr1->isObjCQualifiedIdType() && ToPtr2->getInterfaceDecl())
+        return ImplicitConversionSequence::Worse;
+      if (ToPtr2->isObjCQualifiedIdType() && ToPtr1->getInterfaceDecl())
+        return ImplicitConversionSequence::Better;
+  
+      // A conversion to an a non-Class object pointer type or qualified 'Class' 
+      // type is better than a conversion to 'Class'.
+      if (ToPtr1->isObjCClassType() &&
+          (ToPtr2->isObjCQualifiedClassType() || ToPtr2->getInterfaceDecl()))
+        return ImplicitConversionSequence::Worse;
+      if (ToPtr2->isObjCClassType() &&
+          (ToPtr1->isObjCQualifiedClassType() || ToPtr1->getInterfaceDecl()))
+        return ImplicitConversionSequence::Better;
+      
+      // A conversion to a non-Class object pointer type is better than a 
+      // conversion to a qualified 'Class' type.
+      if (ToPtr1->isObjCQualifiedClassType() && ToPtr2->getInterfaceDecl())
+        return ImplicitConversionSequence::Worse;
+      if (ToPtr2->isObjCQualifiedClassType() && ToPtr1->getInterfaceDecl())
+        return ImplicitConversionSequence::Better;
+
+      //   -- "conversion of C* to B* is better than conversion of C* to A*,"
+      if (S.Context.hasSameType(FromType1, FromType2) && 
+          !FromPtr1->isObjCIdType() && !FromPtr1->isObjCClassType() &&
+          (ToAssignLeft != ToAssignRight))
+        return ToAssignLeft? ImplicitConversionSequence::Worse
+                           : ImplicitConversionSequence::Better;
+
+      //   -- "conversion of B* to A* is better than conversion of C* to A*,"
+      if (S.Context.hasSameUnqualifiedType(ToType1, ToType2) &&
+          (FromAssignLeft != FromAssignRight))
+        return FromAssignLeft? ImplicitConversionSequence::Better
+        : ImplicitConversionSequence::Worse;
+    }
+  }
+  
+  // Ranking of member-pointer types.
+  if (SCS1.Second == ICK_Pointer_Member && SCS2.Second == ICK_Pointer_Member &&
+      FromType1->isMemberPointerType() && FromType2->isMemberPointerType() &&
+      ToType1->isMemberPointerType() && ToType2->isMemberPointerType()) {
+    const MemberPointerType * FromMemPointer1 =
+                                        FromType1->getAs<MemberPointerType>();
+    const MemberPointerType * ToMemPointer1 =
+                                          ToType1->getAs<MemberPointerType>();
+    const MemberPointerType * FromMemPointer2 =
+                                          FromType2->getAs<MemberPointerType>();
+    const MemberPointerType * ToMemPointer2 =
+                                          ToType2->getAs<MemberPointerType>();
+    const Type *FromPointeeType1 = FromMemPointer1->getClass();
+    const Type *ToPointeeType1 = ToMemPointer1->getClass();
+    const Type *FromPointeeType2 = FromMemPointer2->getClass();
+    const Type *ToPointeeType2 = ToMemPointer2->getClass();
+    QualType FromPointee1 = QualType(FromPointeeType1, 0).getUnqualifiedType();
+    QualType ToPointee1 = QualType(ToPointeeType1, 0).getUnqualifiedType();
+    QualType FromPointee2 = QualType(FromPointeeType2, 0).getUnqualifiedType();
+    QualType ToPointee2 = QualType(ToPointeeType2, 0).getUnqualifiedType();
+    // conversion of A::* to B::* is better than conversion of A::* to C::*,
+    if (FromPointee1 == FromPointee2 && ToPointee1 != ToPointee2) {
+      if (S.IsDerivedFrom(ToPointee1, ToPointee2))
+        return ImplicitConversionSequence::Worse;
+      else if (S.IsDerivedFrom(ToPointee2, ToPointee1))
+        return ImplicitConversionSequence::Better;
+    }
+    // conversion of B::* to C::* is better than conversion of A::* to C::*
+    if (ToPointee1 == ToPointee2 && FromPointee1 != FromPointee2) {
+      if (S.IsDerivedFrom(FromPointee1, FromPointee2))
+        return ImplicitConversionSequence::Better;
+      else if (S.IsDerivedFrom(FromPointee2, FromPointee1))
+        return ImplicitConversionSequence::Worse;
+    }
+  }
+
+  if (SCS1.Second == ICK_Derived_To_Base) {
+    //   -- conversion of C to B is better than conversion of C to A,
+    //   -- binding of an expression of type C to a reference of type
+    //      B& is better than binding an expression of type C to a
+    //      reference of type A&,
+    if (S.Context.hasSameUnqualifiedType(FromType1, FromType2) &&
+        !S.Context.hasSameUnqualifiedType(ToType1, ToType2)) {
+      if (S.IsDerivedFrom(ToType1, ToType2))
+        return ImplicitConversionSequence::Better;
+      else if (S.IsDerivedFrom(ToType2, ToType1))
+        return ImplicitConversionSequence::Worse;
+    }
+
+    //   -- conversion of B to A is better than conversion of C to A.
+    //   -- binding of an expression of type B to a reference of type
+    //      A& is better than binding an expression of type C to a
+    //      reference of type A&,
+    if (!S.Context.hasSameUnqualifiedType(FromType1, FromType2) &&
+        S.Context.hasSameUnqualifiedType(ToType1, ToType2)) {
+      if (S.IsDerivedFrom(FromType2, FromType1))
+        return ImplicitConversionSequence::Better;
+      else if (S.IsDerivedFrom(FromType1, FromType2))
+        return ImplicitConversionSequence::Worse;
+    }
+  }
+
+  return ImplicitConversionSequence::Indistinguishable;
+}
+
+/// CompareReferenceRelationship - Compare the two types T1 and T2 to
+/// determine whether they are reference-related,
+/// reference-compatible, reference-compatible with added
+/// qualification, or incompatible, for use in C++ initialization by
+/// reference (C++ [dcl.ref.init]p4). Neither type can be a reference
+/// type, and the first type (T1) is the pointee type of the reference
+/// type being initialized.
+Sema::ReferenceCompareResult
+Sema::CompareReferenceRelationship(SourceLocation Loc,
+                                   QualType OrigT1, QualType OrigT2,
+                                   bool &DerivedToBase,
+                                   bool &ObjCConversion,
+                                   bool &ObjCLifetimeConversion) {
+  assert(!OrigT1->isReferenceType() &&
+    "T1 must be the pointee type of the reference type");
+  assert(!OrigT2->isReferenceType() && "T2 cannot be a reference type");
+
+  QualType T1 = Context.getCanonicalType(OrigT1);
+  QualType T2 = Context.getCanonicalType(OrigT2);
+  Qualifiers T1Quals, T2Quals;
+  QualType UnqualT1 = Context.getUnqualifiedArrayType(T1, T1Quals);
+  QualType UnqualT2 = Context.getUnqualifiedArrayType(T2, T2Quals);
+
+  // C++ [dcl.init.ref]p4:
+  //   Given types "cv1 T1" and "cv2 T2," "cv1 T1" is
+  //   reference-related to "cv2 T2" if T1 is the same type as T2, or
+  //   T1 is a base class of T2.
+  DerivedToBase = false;
+  ObjCConversion = false;
+  ObjCLifetimeConversion = false;
+  if (UnqualT1 == UnqualT2) {
+    // Nothing to do.
+  } else if (!RequireCompleteType(Loc, OrigT2, PDiag()) &&
+           IsDerivedFrom(UnqualT2, UnqualT1))
+    DerivedToBase = true;
+  else if (UnqualT1->isObjCObjectOrInterfaceType() &&
+           UnqualT2->isObjCObjectOrInterfaceType() &&
+           Context.canBindObjCObjectType(UnqualT1, UnqualT2))
+    ObjCConversion = true;
+  else
+    return Ref_Incompatible;
+
+  // At this point, we know that T1 and T2 are reference-related (at
+  // least).
+
+  // If the type is an array type, promote the element qualifiers to the type
+  // for comparison.
+  if (isa<ArrayType>(T1) && T1Quals)
+    T1 = Context.getQualifiedType(UnqualT1, T1Quals);
+  if (isa<ArrayType>(T2) && T2Quals)
+    T2 = Context.getQualifiedType(UnqualT2, T2Quals);
+
+  // C++ [dcl.init.ref]p4:
+  //   "cv1 T1" is reference-compatible with "cv2 T2" if T1 is
+  //   reference-related to T2 and cv1 is the same cv-qualification
+  //   as, or greater cv-qualification than, cv2. For purposes of
+  //   overload resolution, cases for which cv1 is greater
+  //   cv-qualification than cv2 are identified as
+  //   reference-compatible with added qualification (see 13.3.3.2).
+  //
+  // Note that we also require equivalence of Objective-C GC and address-space
+  // qualifiers when performing these computations, so that e.g., an int in
+  // address space 1 is not reference-compatible with an int in address
+  // space 2.
+  if (T1Quals.getObjCLifetime() != T2Quals.getObjCLifetime() &&
+      T1Quals.compatiblyIncludesObjCLifetime(T2Quals)) {
+    T1Quals.removeObjCLifetime();
+    T2Quals.removeObjCLifetime();    
+    ObjCLifetimeConversion = true;
+  }
+    
+  if (T1Quals == T2Quals)
+    return Ref_Compatible;
+  else if (T1Quals.compatiblyIncludes(T2Quals))
+    return Ref_Compatible_With_Added_Qualification;
+  else
+    return Ref_Related;
+}
+
+/// \brief Look for a user-defined conversion to an value reference-compatible
+///        with DeclType. Return true if something definite is found.
+static bool
+FindConversionForRefInit(Sema &S, ImplicitConversionSequence &ICS,
+                         QualType DeclType, SourceLocation DeclLoc,
+                         Expr *Init, QualType T2, bool AllowRvalues,
+                         bool AllowExplicit) {
+  assert(T2->isRecordType() && "Can only find conversions of record types.");
+  CXXRecordDecl *T2RecordDecl
+    = dyn_cast<CXXRecordDecl>(T2->getAs<RecordType>()->getDecl());
+
+  OverloadCandidateSet CandidateSet(DeclLoc);
+  const UnresolvedSetImpl *Conversions
+    = T2RecordDecl->getVisibleConversionFunctions();
+  for (UnresolvedSetImpl::iterator I = Conversions->begin(),
+         E = Conversions->end(); I != E; ++I) {
+    NamedDecl *D = *I;
+    CXXRecordDecl *ActingDC = cast<CXXRecordDecl>(D->getDeclContext());
+    if (isa<UsingShadowDecl>(D))
+      D = cast<UsingShadowDecl>(D)->getTargetDecl();
+
+    FunctionTemplateDecl *ConvTemplate
+      = dyn_cast<FunctionTemplateDecl>(D);
+    CXXConversionDecl *Conv;
+    if (ConvTemplate)
+      Conv = cast<CXXConversionDecl>(ConvTemplate->getTemplatedDecl());
+    else
+      Conv = cast<CXXConversionDecl>(D);
+
+    // If this is an explicit conversion, and we're not allowed to consider
+    // explicit conversions, skip it.
+    if (!AllowExplicit && Conv->isExplicit())
+      continue;
+
+    if (AllowRvalues) {
+      bool DerivedToBase = false;
+      bool ObjCConversion = false;
+      bool ObjCLifetimeConversion = false;
+      
+      // If we are initializing an rvalue reference, don't permit conversion
+      // functions that return lvalues.
+      if (!ConvTemplate && DeclType->isRValueReferenceType()) {
+        const ReferenceType *RefType
+          = Conv->getConversionType()->getAs<LValueReferenceType>();
+        if (RefType && !RefType->getPointeeType()->isFunctionType())
+          continue;
+      }
+      
+      if (!ConvTemplate &&
+          S.CompareReferenceRelationship(
+            DeclLoc,
+            Conv->getConversionType().getNonReferenceType()
+              .getUnqualifiedType(),
+            DeclType.getNonReferenceType().getUnqualifiedType(),
+            DerivedToBase, ObjCConversion, ObjCLifetimeConversion) ==
+          Sema::Ref_Incompatible)
+        continue;
+    } else {
+      // If the conversion function doesn't return a reference type,
+      // it can't be considered for this conversion. An rvalue reference
+      // is only acceptable if its referencee is a function type.
+
+      const ReferenceType *RefType =
+        Conv->getConversionType()->getAs<ReferenceType>();
+      if (!RefType ||
+          (!RefType->isLValueReferenceType() &&
+           !RefType->getPointeeType()->isFunctionType()))
+        continue;
+    }
+
+    if (ConvTemplate)
+      S.AddTemplateConversionCandidate(ConvTemplate, I.getPair(), ActingDC,
+                                       Init, DeclType, CandidateSet);
+    else
+      S.AddConversionCandidate(Conv, I.getPair(), ActingDC, Init,
+                               DeclType, CandidateSet);
+  }
+
+  bool HadMultipleCandidates = (CandidateSet.size() > 1);
+
+  OverloadCandidateSet::iterator Best;
+  switch (CandidateSet.BestViableFunction(S, DeclLoc, Best, true)) {
+  case OR_Success:
+    // C++ [over.ics.ref]p1:
+    //
+    //   [...] If the parameter binds directly to the result of
+    //   applying a conversion function to the argument
+    //   expression, the implicit conversion sequence is a
+    //   user-defined conversion sequence (13.3.3.1.2), with the
+    //   second standard conversion sequence either an identity
+    //   conversion or, if the conversion function returns an
+    //   entity of a type that is a derived class of the parameter
+    //   type, a derived-to-base Conversion.
+    if (!Best->FinalConversion.DirectBinding)
+      return false;
+
+    if (Best->Function)
+      S.MarkFunctionReferenced(DeclLoc, Best->Function);
+    ICS.setUserDefined();
+    ICS.UserDefined.Before = Best->Conversions[0].Standard;
+    ICS.UserDefined.After = Best->FinalConversion;
+    ICS.UserDefined.HadMultipleCandidates = HadMultipleCandidates;
+    ICS.UserDefined.ConversionFunction = Best->Function;
+    ICS.UserDefined.FoundConversionFunction = Best->FoundDecl;
+    ICS.UserDefined.EllipsisConversion = false;
+    assert(ICS.UserDefined.After.ReferenceBinding &&
+           ICS.UserDefined.After.DirectBinding &&
+           "Expected a direct reference binding!");
+    return true;
+
+  case OR_Ambiguous:
+    ICS.setAmbiguous();
+    for (OverloadCandidateSet::iterator Cand = CandidateSet.begin();
+         Cand != CandidateSet.end(); ++Cand)
+      if (Cand->Viable)
+        ICS.Ambiguous.addConversion(Cand->Function);
+    return true;
+
+  case OR_No_Viable_Function:
+  case OR_Deleted:
+    // There was no suitable conversion, or we found a deleted
+    // conversion; continue with other checks.
+    return false;
+  }
+
+  llvm_unreachable("Invalid OverloadResult!");
+}
+
+/// \brief Compute an implicit conversion sequence for reference
+/// initialization.
+static ImplicitConversionSequence
+TryReferenceInit(Sema &S, Expr *Init, QualType DeclType,
+                 SourceLocation DeclLoc,
+                 bool SuppressUserConversions,
+                 bool AllowExplicit) {
+  assert(DeclType->isReferenceType() && "Reference init needs a reference");
+
+  // Most paths end in a failed conversion.
+  ImplicitConversionSequence ICS;
+  ICS.setBad(BadConversionSequence::no_conversion, Init, DeclType);
+
+  QualType T1 = DeclType->getAs<ReferenceType>()->getPointeeType();
+  QualType T2 = Init->getType();
+
+  // If the initializer is the address of an overloaded function, try
+  // to resolve the overloaded function. If all goes well, T2 is the
+  // type of the resulting function.
+  if (S.Context.getCanonicalType(T2) == S.Context.OverloadTy) {
+    DeclAccessPair Found;
+    if (FunctionDecl *Fn = S.ResolveAddressOfOverloadedFunction(Init, DeclType,
+                                                                false, Found))
+      T2 = Fn->getType();
+  }
+
+  // Compute some basic properties of the types and the initializer.
+  bool isRValRef = DeclType->isRValueReferenceType();
+  bool DerivedToBase = false;
+  bool ObjCConversion = false;
+  bool ObjCLifetimeConversion = false;
+  Expr::Classification InitCategory = Init->Classify(S.Context);
+  Sema::ReferenceCompareResult RefRelationship
+    = S.CompareReferenceRelationship(DeclLoc, T1, T2, DerivedToBase,
+                                     ObjCConversion, ObjCLifetimeConversion);
+
+
+  // C++0x [dcl.init.ref]p5:
+  //   A reference to type "cv1 T1" is initialized by an expression
+  //   of type "cv2 T2" as follows:
+
+  //     -- If reference is an lvalue reference and the initializer expression
+  if (!isRValRef) {
+    //     -- is an lvalue (but is not a bit-field), and "cv1 T1" is
+    //        reference-compatible with "cv2 T2," or
+    //
+    // Per C++ [over.ics.ref]p4, we don't check the bit-field property here.
+    if (InitCategory.isLValue() &&
+        RefRelationship >= Sema::Ref_Compatible_With_Added_Qualification) {
+      // C++ [over.ics.ref]p1:
+      //   When a parameter of reference type binds directly (8.5.3)
+      //   to an argument expression, the implicit conversion sequence
+      //   is the identity conversion, unless the argument expression
+      //   has a type that is a derived class of the parameter type,
+      //   in which case the implicit conversion sequence is a
+      //   derived-to-base Conversion (13.3.3.1).
+      ICS.setStandard();
+      ICS.Standard.First = ICK_Identity;
+      ICS.Standard.Second = DerivedToBase? ICK_Derived_To_Base
+                         : ObjCConversion? ICK_Compatible_Conversion
+                         : ICK_Identity;
+      ICS.Standard.Third = ICK_Identity;
+      ICS.Standard.FromTypePtr = T2.getAsOpaquePtr();
+      ICS.Standard.setToType(0, T2);
+      ICS.Standard.setToType(1, T1);
+      ICS.Standard.setToType(2, T1);
+      ICS.Standard.ReferenceBinding = true;
+      ICS.Standard.DirectBinding = true;
+      ICS.Standard.IsLvalueReference = !isRValRef;
+      ICS.Standard.BindsToFunctionLvalue = T2->isFunctionType();
+      ICS.Standard.BindsToRvalue = false;
+      ICS.Standard.BindsImplicitObjectArgumentWithoutRefQualifier = false;
+      ICS.Standard.ObjCLifetimeConversionBinding = ObjCLifetimeConversion;
+      ICS.Standard.CopyConstructor = 0;
+
+      // Nothing more to do: the inaccessibility/ambiguity check for
+      // derived-to-base conversions is suppressed when we're
+      // computing the implicit conversion sequence (C++
+      // [over.best.ics]p2).
+      return ICS;
+    }
+
+    //       -- has a class type (i.e., T2 is a class type), where T1 is
+    //          not reference-related to T2, and can be implicitly
+    //          converted to an lvalue of type "cv3 T3," where "cv1 T1"
+    //          is reference-compatible with "cv3 T3" 92) (this
+    //          conversion is selected by enumerating the applicable
+    //          conversion functions (13.3.1.6) and choosing the best
+    //          one through overload resolution (13.3)),
+    if (!SuppressUserConversions && T2->isRecordType() &&
+        !S.RequireCompleteType(DeclLoc, T2, 0) &&
+        RefRelationship == Sema::Ref_Incompatible) {
+      if (FindConversionForRefInit(S, ICS, DeclType, DeclLoc,
+                                   Init, T2, /*AllowRvalues=*/false,
+                                   AllowExplicit))
+        return ICS;
+    }
+  }
+
+  //     -- Otherwise, the reference shall be an lvalue reference to a
+  //        non-volatile const type (i.e., cv1 shall be const), or the reference
+  //        shall be an rvalue reference.
+  //
+  // We actually handle one oddity of C++ [over.ics.ref] at this
+  // point, which is that, due to p2 (which short-circuits reference
+  // binding by only attempting a simple conversion for non-direct
+  // bindings) and p3's strange wording, we allow a const volatile
+  // reference to bind to an rvalue. Hence the check for the presence
+  // of "const" rather than checking for "const" being the only
+  // qualifier.
+  // This is also the point where rvalue references and lvalue inits no longer
+  // go together.
+  if (!isRValRef && !T1.isConstQualified())
+    return ICS;
+
+  //       -- If the initializer expression
+  //
+  //            -- is an xvalue, class prvalue, array prvalue or function
+  //               lvalue and "cv1 T1" is reference-compatible with "cv2 T2", or
+  if (RefRelationship >= Sema::Ref_Compatible_With_Added_Qualification &&
+      (InitCategory.isXValue() ||
+      (InitCategory.isPRValue() && (T2->isRecordType() || T2->isArrayType())) ||
+      (InitCategory.isLValue() && T2->isFunctionType()))) {
+    ICS.setStandard();
+    ICS.Standard.First = ICK_Identity;
+    ICS.Standard.Second = DerivedToBase? ICK_Derived_To_Base
+                      : ObjCConversion? ICK_Compatible_Conversion
+                      : ICK_Identity;
+    ICS.Standard.Third = ICK_Identity;
+    ICS.Standard.FromTypePtr = T2.getAsOpaquePtr();
+    ICS.Standard.setToType(0, T2);
+    ICS.Standard.setToType(1, T1);
+    ICS.Standard.setToType(2, T1);
+    ICS.Standard.ReferenceBinding = true;
+    // In C++0x, this is always a direct binding. In C++98/03, it's a direct
+    // binding unless we're binding to a class prvalue.
+    // Note: Although xvalues wouldn't normally show up in C++98/03 code, we
+    // allow the use of rvalue references in C++98/03 for the benefit of
+    // standard library implementors; therefore, we need the xvalue check here.
+    ICS.Standard.DirectBinding =
+      S.getLangOpts().CPlusPlus0x ||
+      (InitCategory.isPRValue() && !T2->isRecordType());
+    ICS.Standard.IsLvalueReference = !isRValRef;
+    ICS.Standard.BindsToFunctionLvalue = T2->isFunctionType();
+    ICS.Standard.BindsToRvalue = InitCategory.isRValue();
+    ICS.Standard.BindsImplicitObjectArgumentWithoutRefQualifier = false;
+    ICS.Standard.ObjCLifetimeConversionBinding = ObjCLifetimeConversion;
+    ICS.Standard.CopyConstructor = 0;
+    return ICS;
+  }
+
+  //            -- has a class type (i.e., T2 is a class type), where T1 is not
+  //               reference-related to T2, and can be implicitly converted to
+  //               an xvalue, class prvalue, or function lvalue of type
+  //               "cv3 T3", where "cv1 T1" is reference-compatible with
+  //               "cv3 T3",
+  //
+  //          then the reference is bound to the value of the initializer
+  //          expression in the first case and to the result of the conversion
+  //          in the second case (or, in either case, to an appropriate base
+  //          class subobject).
+  if (!SuppressUserConversions && RefRelationship == Sema::Ref_Incompatible &&
+      T2->isRecordType() && !S.RequireCompleteType(DeclLoc, T2, 0) &&
+      FindConversionForRefInit(S, ICS, DeclType, DeclLoc,
+                               Init, T2, /*AllowRvalues=*/true,
+                               AllowExplicit)) {
+    // In the second case, if the reference is an rvalue reference
+    // and the second standard conversion sequence of the
+    // user-defined conversion sequence includes an lvalue-to-rvalue
+    // conversion, the program is ill-formed.
+    if (ICS.isUserDefined() && isRValRef &&
+        ICS.UserDefined.After.First == ICK_Lvalue_To_Rvalue)
+      ICS.setBad(BadConversionSequence::no_conversion, Init, DeclType);
+
+    return ICS;
+  }
+
+  //       -- Otherwise, a temporary of type "cv1 T1" is created and
+  //          initialized from the initializer expression using the
+  //          rules for a non-reference copy initialization (8.5). The
+  //          reference is then bound to the temporary. If T1 is
+  //          reference-related to T2, cv1 must be the same
+  //          cv-qualification as, or greater cv-qualification than,
+  //          cv2; otherwise, the program is ill-formed.
+  if (RefRelationship == Sema::Ref_Related) {
+    // If cv1 == cv2 or cv1 is a greater cv-qualified than cv2, then
+    // we would be reference-compatible or reference-compatible with
+    // added qualification. But that wasn't the case, so the reference
+    // initialization fails.
+    //
+    // Note that we only want to check address spaces and cvr-qualifiers here.
+    // ObjC GC and lifetime qualifiers aren't important.
+    Qualifiers T1Quals = T1.getQualifiers();
+    Qualifiers T2Quals = T2.getQualifiers();
+    T1Quals.removeObjCGCAttr();
+    T1Quals.removeObjCLifetime();
+    T2Quals.removeObjCGCAttr();
+    T2Quals.removeObjCLifetime();
+    if (!T1Quals.compatiblyIncludes(T2Quals))
+      return ICS;
+  }
+
+  // If at least one of the types is a class type, the types are not
+  // related, and we aren't allowed any user conversions, the
+  // reference binding fails. This case is important for breaking
+  // recursion, since TryImplicitConversion below will attempt to
+  // create a temporary through the use of a copy constructor.
+  if (SuppressUserConversions && RefRelationship == Sema::Ref_Incompatible &&
+      (T1->isRecordType() || T2->isRecordType()))
+    return ICS;
+
+  // If T1 is reference-related to T2 and the reference is an rvalue
+  // reference, the initializer expression shall not be an lvalue.
+  if (RefRelationship >= Sema::Ref_Related &&
+      isRValRef && Init->Classify(S.Context).isLValue())
+    return ICS;
+
+  // C++ [over.ics.ref]p2:
+  //   When a parameter of reference type is not bound directly to
+  //   an argument expression, the conversion sequence is the one
+  //   required to convert the argument expression to the
+  //   underlying type of the reference according to
+  //   13.3.3.1. Conceptually, this conversion sequence corresponds
+  //   to copy-initializing a temporary of the underlying type with
+  //   the argument expression. Any difference in top-level
+  //   cv-qualification is subsumed by the initialization itself
+  //   and does not constitute a conversion.
+  ICS = TryImplicitConversion(S, Init, T1, SuppressUserConversions,
+                              /*AllowExplicit=*/false,
+                              /*InOverloadResolution=*/false,
+                              /*CStyle=*/false,
+                              /*AllowObjCWritebackConversion=*/false);
+
+  // Of course, that's still a reference binding.
+  if (ICS.isStandard()) {
+    ICS.Standard.ReferenceBinding = true;
+    ICS.Standard.IsLvalueReference = !isRValRef;
+    ICS.Standard.BindsToFunctionLvalue = T2->isFunctionType();
+    ICS.Standard.BindsToRvalue = true;
+    ICS.Standard.BindsImplicitObjectArgumentWithoutRefQualifier = false;
+    ICS.Standard.ObjCLifetimeConversionBinding = false;
+  } else if (ICS.isUserDefined()) {
+    // Don't allow rvalue references to bind to lvalues.
+    if (DeclType->isRValueReferenceType()) {
+      if (const ReferenceType *RefType
+            = ICS.UserDefined.ConversionFunction->getResultType()
+                ->getAs<LValueReferenceType>()) {
+        if (!RefType->getPointeeType()->isFunctionType()) {
+          ICS.setBad(BadConversionSequence::lvalue_ref_to_rvalue, Init, 
+                     DeclType);
+          return ICS;
+        }
+      }
+    }
+    
+    ICS.UserDefined.After.ReferenceBinding = true;
+    ICS.UserDefined.After.IsLvalueReference = !isRValRef;
+    ICS.UserDefined.After.BindsToFunctionLvalue = T2->isFunctionType();
+    ICS.UserDefined.After.BindsToRvalue = true;
+    ICS.UserDefined.After.BindsImplicitObjectArgumentWithoutRefQualifier = false;
+    ICS.UserDefined.After.ObjCLifetimeConversionBinding = false;
+  }
+
+  return ICS;
+}
+
+static ImplicitConversionSequence
+TryCopyInitialization(Sema &S, Expr *From, QualType ToType,
+                      bool SuppressUserConversions,
+                      bool InOverloadResolution,
+                      bool AllowObjCWritebackConversion,
+                      bool AllowExplicit = false);
+
+/// TryListConversion - Try to copy-initialize a value of type ToType from the
+/// initializer list From.
+static ImplicitConversionSequence
+TryListConversion(Sema &S, InitListExpr *From, QualType ToType,
+                  bool SuppressUserConversions,
+                  bool InOverloadResolution,
+                  bool AllowObjCWritebackConversion) {
+  // C++11 [over.ics.list]p1:
+  //   When an argument is an initializer list, it is not an expression and
+  //   special rules apply for converting it to a parameter type.
+
+  ImplicitConversionSequence Result;
+  Result.setBad(BadConversionSequence::no_conversion, From, ToType);
+  Result.setListInitializationSequence();
+
+  // We need a complete type for what follows. Incomplete types can never be
+  // initialized from init lists.
+  if (S.RequireCompleteType(From->getLocStart(), ToType, S.PDiag()))
+    return Result;
+
+  // C++11 [over.ics.list]p2:
+  //   If the parameter type is std::initializer_list<X> or "array of X" and
+  //   all the elements can be implicitly converted to X, the implicit
+  //   conversion sequence is the worst conversion necessary to convert an
+  //   element of the list to X.
+  bool toStdInitializerList = false;
+  QualType X;
+  if (ToType->isArrayType())
+    X = S.Context.getBaseElementType(ToType);
+  else
+    toStdInitializerList = S.isStdInitializerList(ToType, &X);
+  if (!X.isNull()) {
+    for (unsigned i = 0, e = From->getNumInits(); i < e; ++i) {
+      Expr *Init = From->getInit(i);
+      ImplicitConversionSequence ICS =
+          TryCopyInitialization(S, Init, X, SuppressUserConversions,
+                                InOverloadResolution,
+                                AllowObjCWritebackConversion);
+      // If a single element isn't convertible, fail.
+      if (ICS.isBad()) {
+        Result = ICS;
+        break;
+      }
+      // Otherwise, look for the worst conversion.
+      if (Result.isBad() ||
+          CompareImplicitConversionSequences(S, ICS, Result) ==
+              ImplicitConversionSequence::Worse)
+        Result = ICS;
+    }
+
+    // For an empty list, we won't have computed any conversion sequence.
+    // Introduce the identity conversion sequence.
+    if (From->getNumInits() == 0) {
+      Result.setStandard();
+      Result.Standard.setAsIdentityConversion();
+      Result.Standard.setFromType(ToType);
+      Result.Standard.setAllToTypes(ToType);
+    }
+
+    Result.setListInitializationSequence();
+    Result.setStdInitializerListElement(toStdInitializerList);
+    return Result;
+  }
+
+  // C++11 [over.ics.list]p3:
+  //   Otherwise, if the parameter is a non-aggregate class X and overload
+  //   resolution chooses a single best constructor [...] the implicit
+  //   conversion sequence is a user-defined conversion sequence. If multiple
+  //   constructors are viable but none is better than the others, the
+  //   implicit conversion sequence is a user-defined conversion sequence.
+  if (ToType->isRecordType() && !ToType->isAggregateType()) {
+    // This function can deal with initializer lists.
+    Result = TryUserDefinedConversion(S, From, ToType, SuppressUserConversions,
+                                      /*AllowExplicit=*/false,
+                                      InOverloadResolution, /*CStyle=*/false,
+                                      AllowObjCWritebackConversion);
+    Result.setListInitializationSequence();
+    return Result;
+  }
+
+  // C++11 [over.ics.list]p4:
+  //   Otherwise, if the parameter has an aggregate type which can be
+  //   initialized from the initializer list [...] the implicit conversion
+  //   sequence is a user-defined conversion sequence.
+  if (ToType->isAggregateType()) {
+    // Type is an aggregate, argument is an init list. At this point it comes
+    // down to checking whether the initialization works.
+    // FIXME: Find out whether this parameter is consumed or not.
+    InitializedEntity Entity =
+        InitializedEntity::InitializeParameter(S.Context, ToType,
+                                               /*Consumed=*/false);
+    if (S.CanPerformCopyInitialization(Entity, S.Owned(From))) {
+      Result.setUserDefined();
+      Result.UserDefined.Before.setAsIdentityConversion();
+      // Initializer lists don't have a type.
+      Result.UserDefined.Before.setFromType(QualType());
+      Result.UserDefined.Before.setAllToTypes(QualType());
+
+      Result.UserDefined.After.setAsIdentityConversion();
+      Result.UserDefined.After.setFromType(ToType);
+      Result.UserDefined.After.setAllToTypes(ToType);
+      Result.UserDefined.ConversionFunction = 0;
+    }
+    return Result;
+  }
+
+  // C++11 [over.ics.list]p5:
+  //   Otherwise, if the parameter is a reference, see 13.3.3.1.4.
+  if (ToType->isReferenceType()) {
+    // The standard is notoriously unclear here, since 13.3.3.1.4 doesn't
+    // mention initializer lists in any way. So we go by what list-
+    // initialization would do and try to extrapolate from that.
+
+    QualType T1 = ToType->getAs<ReferenceType>()->getPointeeType();
+
+    // If the initializer list has a single element that is reference-related
+    // to the parameter type, we initialize the reference from that.
+    if (From->getNumInits() == 1) {
+      Expr *Init = From->getInit(0);
+
+      QualType T2 = Init->getType();
+
+      // If the initializer is the address of an overloaded function, try
+      // to resolve the overloaded function. If all goes well, T2 is the
+      // type of the resulting function.
+      if (S.Context.getCanonicalType(T2) == S.Context.OverloadTy) {
+        DeclAccessPair Found;
+        if (FunctionDecl *Fn = S.ResolveAddressOfOverloadedFunction(
+                                   Init, ToType, false, Found))
+          T2 = Fn->getType();
+      }
+
+      // Compute some basic properties of the types and the initializer.
+      bool dummy1 = false;
+      bool dummy2 = false;
+      bool dummy3 = false;
+      Sema::ReferenceCompareResult RefRelationship
+        = S.CompareReferenceRelationship(From->getLocStart(), T1, T2, dummy1,
+                                         dummy2, dummy3);
+
+      if (RefRelationship >= Sema::Ref_Related)
+        return TryReferenceInit(S, Init, ToType,
+                                /*FIXME:*/From->getLocStart(),
+                                SuppressUserConversions,
+                                /*AllowExplicit=*/false);
+    }
+
+    // Otherwise, we bind the reference to a temporary created from the
+    // initializer list.
+    Result = TryListConversion(S, From, T1, SuppressUserConversions,
+                               InOverloadResolution,
+                               AllowObjCWritebackConversion);
+    if (Result.isFailure())
+      return Result;
+    assert(!Result.isEllipsis() &&
+           "Sub-initialization cannot result in ellipsis conversion.");
+
+    // Can we even bind to a temporary?
+    if (ToType->isRValueReferenceType() ||
+        (T1.isConstQualified() && !T1.isVolatileQualified())) {
+      StandardConversionSequence &SCS = Result.isStandard() ? Result.Standard :
+                                            Result.UserDefined.After;
+      SCS.ReferenceBinding = true;
+      SCS.IsLvalueReference = ToType->isLValueReferenceType();
+      SCS.BindsToRvalue = true;
+      SCS.BindsToFunctionLvalue = false;
+      SCS.BindsImplicitObjectArgumentWithoutRefQualifier = false;
+      SCS.ObjCLifetimeConversionBinding = false;
+    } else
+      Result.setBad(BadConversionSequence::lvalue_ref_to_rvalue,
+                    From, ToType);
+    return Result;
+  }
+
+  // C++11 [over.ics.list]p6:
+  //   Otherwise, if the parameter type is not a class:
+  if (!ToType->isRecordType()) {
+    //    - if the initializer list has one element, the implicit conversion
+    //      sequence is the one required to convert the element to the
+    //      parameter type.
+    unsigned NumInits = From->getNumInits();
+    if (NumInits == 1)
+      Result = TryCopyInitialization(S, From->getInit(0), ToType,
+                                     SuppressUserConversions,
+                                     InOverloadResolution,
+                                     AllowObjCWritebackConversion);
+    //    - if the initializer list has no elements, the implicit conversion
+    //      sequence is the identity conversion.
+    else if (NumInits == 0) {
+      Result.setStandard();
+      Result.Standard.setAsIdentityConversion();
+      Result.Standard.setFromType(ToType);
+      Result.Standard.setAllToTypes(ToType);
+    }
+    Result.setListInitializationSequence();
+    return Result;
+  }
+
+  // C++11 [over.ics.list]p7:
+  //   In all cases other than those enumerated above, no conversion is possible
+  return Result;
+}
+
+/// TryCopyInitialization - Try to copy-initialize a value of type
+/// ToType from the expression From. Return the implicit conversion
+/// sequence required to pass this argument, which may be a bad
+/// conversion sequence (meaning that the argument cannot be passed to
+/// a parameter of this type). If @p SuppressUserConversions, then we
+/// do not permit any user-defined conversion sequences.
+static ImplicitConversionSequence
+TryCopyInitialization(Sema &S, Expr *From, QualType ToType,
+                      bool SuppressUserConversions,
+                      bool InOverloadResolution,
+                      bool AllowObjCWritebackConversion,
+                      bool AllowExplicit) {
+  if (InitListExpr *FromInitList = dyn_cast<InitListExpr>(From))
+    return TryListConversion(S, FromInitList, ToType, SuppressUserConversions,
+                             InOverloadResolution,AllowObjCWritebackConversion);
+
+  if (ToType->isReferenceType())
+    return TryReferenceInit(S, From, ToType,
+                            /*FIXME:*/From->getLocStart(),
+                            SuppressUserConversions,
+                            AllowExplicit);
+
+  return TryImplicitConversion(S, From, ToType,
+                               SuppressUserConversions,
+                               /*AllowExplicit=*/false,
+                               InOverloadResolution,
+                               /*CStyle=*/false,
+                               AllowObjCWritebackConversion);
+}
+
+static bool TryCopyInitialization(const CanQualType FromQTy,
+                                  const CanQualType ToQTy,
+                                  Sema &S,
+                                  SourceLocation Loc,
+                                  ExprValueKind FromVK) {
+  OpaqueValueExpr TmpExpr(Loc, FromQTy, FromVK);
+  ImplicitConversionSequence ICS =
+    TryCopyInitialization(S, &TmpExpr, ToQTy, true, true, false);
+
+  return !ICS.isBad();
+}
+
+/// TryObjectArgumentInitialization - Try to initialize the object
+/// parameter of the given member function (@c Method) from the
+/// expression @p From.
+static ImplicitConversionSequence
+TryObjectArgumentInitialization(Sema &S, QualType OrigFromType,
+                                Expr::Classification FromClassification,
+                                CXXMethodDecl *Method,
+                                CXXRecordDecl *ActingContext) {
+  QualType ClassType = S.Context.getTypeDeclType(ActingContext);
+  // [class.dtor]p2: A destructor can be invoked for a const, volatile or
+  //                 const volatile object.
+  unsigned Quals = isa<CXXDestructorDecl>(Method) ?
+    Qualifiers::Const | Qualifiers::Volatile : Method->getTypeQualifiers();
+  QualType ImplicitParamType =  S.Context.getCVRQualifiedType(ClassType, Quals);
+
+  // Set up the conversion sequence as a "bad" conversion, to allow us
+  // to exit early.
+  ImplicitConversionSequence ICS;
+
+  // We need to have an object of class type.
+  QualType FromType = OrigFromType;
+  if (const PointerType *PT = FromType->getAs<PointerType>()) {
+    FromType = PT->getPointeeType();
+
+    // When we had a pointer, it's implicitly dereferenced, so we
+    // better have an lvalue.
+    assert(FromClassification.isLValue());
+  }
+
+  assert(FromType->isRecordType());
+
+  // C++0x [over.match.funcs]p4:
+  //   For non-static member functions, the type of the implicit object
+  //   parameter is
+  //
+  //     - "lvalue reference to cv X" for functions declared without a
+  //        ref-qualifier or with the & ref-qualifier
+  //     - "rvalue reference to cv X" for functions declared with the &&
+  //        ref-qualifier
+  //
+  // where X is the class of which the function is a member and cv is the
+  // cv-qualification on the member function declaration.
+  //
+  // However, when finding an implicit conversion sequence for the argument, we
+  // are not allowed to create temporaries or perform user-defined conversions
+  // (C++ [over.match.funcs]p5). We perform a simplified version of
+  // reference binding here, that allows class rvalues to bind to
+  // non-constant references.
+
+  // First check the qualifiers.
+  QualType FromTypeCanon = S.Context.getCanonicalType(FromType);
+  if (ImplicitParamType.getCVRQualifiers()
+                                    != FromTypeCanon.getLocalCVRQualifiers() &&
+      !ImplicitParamType.isAtLeastAsQualifiedAs(FromTypeCanon)) {
+    ICS.setBad(BadConversionSequence::bad_qualifiers,
+               OrigFromType, ImplicitParamType);
+    return ICS;
+  }
+
+  // Check that we have either the same type or a derived type. It
+  // affects the conversion rank.
+  QualType ClassTypeCanon = S.Context.getCanonicalType(ClassType);
+  ImplicitConversionKind SecondKind;
+  if (ClassTypeCanon == FromTypeCanon.getLocalUnqualifiedType()) {
+    SecondKind = ICK_Identity;
+  } else if (S.IsDerivedFrom(FromType, ClassType))
+    SecondKind = ICK_Derived_To_Base;
+  else {
+    ICS.setBad(BadConversionSequence::unrelated_class,
+               FromType, ImplicitParamType);
+    return ICS;
+  }
+
+  // Check the ref-qualifier.
+  switch (Method->getRefQualifier()) {
+  case RQ_None:
+    // Do nothing; we don't care about lvalueness or rvalueness.
+    break;
+
+  case RQ_LValue:
+    if (!FromClassification.isLValue() && Quals != Qualifiers::Const) {
+      // non-const lvalue reference cannot bind to an rvalue
+      ICS.setBad(BadConversionSequence::lvalue_ref_to_rvalue, FromType,
+                 ImplicitParamType);
+      return ICS;
+    }
+    break;
+
+  case RQ_RValue:
+    if (!FromClassification.isRValue()) {
+      // rvalue reference cannot bind to an lvalue
+      ICS.setBad(BadConversionSequence::rvalue_ref_to_lvalue, FromType,
+                 ImplicitParamType);
+      return ICS;
+    }
+    break;
+  }
+
+  // Success. Mark this as a reference binding.
+  ICS.setStandard();
+  ICS.Standard.setAsIdentityConversion();
+  ICS.Standard.Second = SecondKind;
+  ICS.Standard.setFromType(FromType);
+  ICS.Standard.setAllToTypes(ImplicitParamType);
+  ICS.Standard.ReferenceBinding = true;
+  ICS.Standard.DirectBinding = true;
+  ICS.Standard.IsLvalueReference = Method->getRefQualifier() != RQ_RValue;
+  ICS.Standard.BindsToFunctionLvalue = false;
+  ICS.Standard.BindsToRvalue = FromClassification.isRValue();
+  ICS.Standard.BindsImplicitObjectArgumentWithoutRefQualifier
+    = (Method->getRefQualifier() == RQ_None);
+  return ICS;
+}
+
+/// PerformObjectArgumentInitialization - Perform initialization of
+/// the implicit object parameter for the given Method with the given
+/// expression.
+ExprResult
+Sema::PerformObjectArgumentInitialization(Expr *From,
+                                          NestedNameSpecifier *Qualifier,
+                                          NamedDecl *FoundDecl,
+                                          CXXMethodDecl *Method) {
+  QualType FromRecordType, DestType;
+  QualType ImplicitParamRecordType  =
+    Method->getThisType(Context)->getAs<PointerType>()->getPointeeType();
+
+  Expr::Classification FromClassification;
+  if (const PointerType *PT = From->getType()->getAs<PointerType>()) {
+    FromRecordType = PT->getPointeeType();
+    DestType = Method->getThisType(Context);
+    FromClassification = Expr::Classification::makeSimpleLValue();
+  } else {
+    FromRecordType = From->getType();
+    DestType = ImplicitParamRecordType;
+    FromClassification = From->Classify(Context);
+  }
+
+  // Note that we always use the true parent context when performing
+  // the actual argument initialization.
+  ImplicitConversionSequence ICS
+    = TryObjectArgumentInitialization(*this, From->getType(), FromClassification,
+                                      Method, Method->getParent());
+  if (ICS.isBad()) {
+    if (ICS.Bad.Kind == BadConversionSequence::bad_qualifiers) {
+      Qualifiers FromQs = FromRecordType.getQualifiers();
+      Qualifiers ToQs = DestType.getQualifiers();
+      unsigned CVR = FromQs.getCVRQualifiers() & ~ToQs.getCVRQualifiers();
+      if (CVR) {
+        Diag(From->getLocStart(),
+             diag::err_member_function_call_bad_cvr)
+          << Method->getDeclName() << FromRecordType << (CVR - 1)
+          << From->getSourceRange();
+        Diag(Method->getLocation(), diag::note_previous_decl)
+          << Method->getDeclName();
+        return ExprError();
+      }
+    }
+
+    return Diag(From->getLocStart(),
+                diag::err_implicit_object_parameter_init)
+       << ImplicitParamRecordType << FromRecordType << From->getSourceRange();
+  }
+
+  if (ICS.Standard.Second == ICK_Derived_To_Base) {
+    ExprResult FromRes =
+      PerformObjectMemberConversion(From, Qualifier, FoundDecl, Method);
+    if (FromRes.isInvalid())
+      return ExprError();
+    From = FromRes.take();
+  }
+
+  if (!Context.hasSameType(From->getType(), DestType))
+    From = ImpCastExprToType(From, DestType, CK_NoOp,
+                             From->getValueKind()).take();
+  return Owned(From);
+}
+
+/// TryContextuallyConvertToBool - Attempt to contextually convert the
+/// expression From to bool (C++0x [conv]p3).
+static ImplicitConversionSequence
+TryContextuallyConvertToBool(Sema &S, Expr *From) {
+  // FIXME: This is pretty broken.
+  return TryImplicitConversion(S, From, S.Context.BoolTy,
+                               // FIXME: Are these flags correct?
+                               /*SuppressUserConversions=*/false,
+                               /*AllowExplicit=*/true,
+                               /*InOverloadResolution=*/false,
+                               /*CStyle=*/false,
+                               /*AllowObjCWritebackConversion=*/false);
+}
+
+/// PerformContextuallyConvertToBool - Perform a contextual conversion
+/// of the expression From to bool (C++0x [conv]p3).
+ExprResult Sema::PerformContextuallyConvertToBool(Expr *From) {
+  if (checkPlaceholderForOverload(*this, From))
+    return ExprError();
+
+  ImplicitConversionSequence ICS = TryContextuallyConvertToBool(*this, From);
+  if (!ICS.isBad())
+    return PerformImplicitConversion(From, Context.BoolTy, ICS, AA_Converting);
+
+  if (!DiagnoseMultipleUserDefinedConversion(From, Context.BoolTy))
+    return Diag(From->getLocStart(),
+                diag::err_typecheck_bool_condition)
+                  << From->getType() << From->getSourceRange();
+  return ExprError();
+}
+
+/// Check that the specified conversion is permitted in a converted constant
+/// expression, according to C++11 [expr.const]p3. Return true if the conversion
+/// is acceptable.
+static bool CheckConvertedConstantConversions(Sema &S,
+                                              StandardConversionSequence &SCS) {
+  // Since we know that the target type is an integral or unscoped enumeration
+  // type, most conversion kinds are impossible. All possible First and Third
+  // conversions are fine.
+  switch (SCS.Second) {
+  case ICK_Identity:
+  case ICK_Integral_Promotion:
+  case ICK_Integral_Conversion:
+    return true;
+
+  case ICK_Boolean_Conversion:
+    // Conversion from an integral or unscoped enumeration type to bool is
+    // classified as ICK_Boolean_Conversion, but it's also an integral
+    // conversion, so it's permitted in a converted constant expression.
+    return SCS.getFromType()->isIntegralOrUnscopedEnumerationType() &&
+           SCS.getToType(2)->isBooleanType();
+
+  case ICK_Floating_Integral:
+  case ICK_Complex_Real:
+    return false;
+
+  case ICK_Lvalue_To_Rvalue:
+  case ICK_Array_To_Pointer:
+  case ICK_Function_To_Pointer:
+  case ICK_NoReturn_Adjustment:
+  case ICK_Qualification:
+  case ICK_Compatible_Conversion:
+  case ICK_Vector_Conversion:
+  case ICK_Vector_Splat:
+  case ICK_Derived_To_Base:
+  case ICK_Pointer_Conversion:
+  case ICK_Pointer_Member:
+  case ICK_Block_Pointer_Conversion:
+  case ICK_Writeback_Conversion:
+  case ICK_Floating_Promotion:
+  case ICK_Complex_Promotion:
+  case ICK_Complex_Conversion:
+  case ICK_Floating_Conversion:
+  case ICK_TransparentUnionConversion:
+    llvm_unreachable("unexpected second conversion kind");
+
+  case ICK_Num_Conversion_Kinds:
+    break;
+  }
+
+  llvm_unreachable("unknown conversion kind");
+}
+
+/// CheckConvertedConstantExpression - Check that the expression From is a
+/// converted constant expression of type T, perform the conversion and produce
+/// the converted expression, per C++11 [expr.const]p3.
+ExprResult Sema::CheckConvertedConstantExpression(Expr *From, QualType T,
+                                                  llvm::APSInt &Value,
+                                                  CCEKind CCE) {
+  assert(LangOpts.CPlusPlus0x && "converted constant expression outside C++11");
+  assert(T->isIntegralOrEnumerationType() && "unexpected converted const type");
+
+  if (checkPlaceholderForOverload(*this, From))
+    return ExprError();
+
+  // C++11 [expr.const]p3 with proposed wording fixes:
+  //  A converted constant expression of type T is a core constant expression,
+  //  implicitly converted to a prvalue of type T, where the converted
+  //  expression is a literal constant expression and the implicit conversion
+  //  sequence contains only user-defined conversions, lvalue-to-rvalue
+  //  conversions, integral promotions, and integral conversions other than
+  //  narrowing conversions.
+  ImplicitConversionSequence ICS =
+    TryImplicitConversion(From, T,
+                          /*SuppressUserConversions=*/false,
+                          /*AllowExplicit=*/false,
+                          /*InOverloadResolution=*/false,
+                          /*CStyle=*/false,
+                          /*AllowObjcWritebackConversion=*/false);
+  StandardConversionSequence *SCS = 0;
+  switch (ICS.getKind()) {
+  case ImplicitConversionSequence::StandardConversion:
+    if (!CheckConvertedConstantConversions(*this, ICS.Standard))
+      return Diag(From->getLocStart(),
+                  diag::err_typecheck_converted_constant_expression_disallowed)
+               << From->getType() << From->getSourceRange() << T;
+    SCS = &ICS.Standard;
+    break;
+  case ImplicitConversionSequence::UserDefinedConversion:
+    // We are converting from class type to an integral or enumeration type, so
+    // the Before sequence must be trivial.
+    if (!CheckConvertedConstantConversions(*this, ICS.UserDefined.After))
+      return Diag(From->getLocStart(),
+                  diag::err_typecheck_converted_constant_expression_disallowed)
+               << From->getType() << From->getSourceRange() << T;
+    SCS = &ICS.UserDefined.After;
+    break;
+  case ImplicitConversionSequence::AmbiguousConversion:
+  case ImplicitConversionSequence::BadConversion:
+    if (!DiagnoseMultipleUserDefinedConversion(From, T))
+      return Diag(From->getLocStart(),
+                  diag::err_typecheck_converted_constant_expression)
+                    << From->getType() << From->getSourceRange() << T;
+    return ExprError();
+
+  case ImplicitConversionSequence::EllipsisConversion:
+    llvm_unreachable("ellipsis conversion in converted constant expression");
+  }
+
+  ExprResult Result = PerformImplicitConversion(From, T, ICS, AA_Converting);
+  if (Result.isInvalid())
+    return Result;
+
+  // Check for a narrowing implicit conversion.
+  APValue PreNarrowingValue;
+  QualType PreNarrowingType;
+  switch (SCS->getNarrowingKind(Context, Result.get(), PreNarrowingValue,
+                                PreNarrowingType)) {
+  case NK_Variable_Narrowing:
+    // Implicit conversion to a narrower type, and the value is not a constant
+    // expression. We'll diagnose this in a moment.
+  case NK_Not_Narrowing:
+    break;
+
+  case NK_Constant_Narrowing:
+    Diag(From->getLocStart(),
+         isSFINAEContext() ? diag::err_cce_narrowing_sfinae :
+                             diag::err_cce_narrowing)
+      << CCE << /*Constant*/1
+      << PreNarrowingValue.getAsString(Context, PreNarrowingType) << T;
+    break;
+
+  case NK_Type_Narrowing:
+    Diag(From->getLocStart(),
+         isSFINAEContext() ? diag::err_cce_narrowing_sfinae :
+                             diag::err_cce_narrowing)
+      << CCE << /*Constant*/0 << From->getType() << T;
+    break;
+  }
+
+  // Check the expression is a constant expression.
+  llvm::SmallVector<PartialDiagnosticAt, 8> Notes;
+  Expr::EvalResult Eval;
+  Eval.Diag = &Notes;
+
+  if (!Result.get()->EvaluateAsRValue(Eval, Context)) {
+    // The expression can't be folded, so we can't keep it at this position in
+    // the AST.
+    Result = ExprError();
+  } else {
+    Value = Eval.Val.getInt();
+
+    if (Notes.empty()) {
+      // It's a constant expression.
+      return Result;
+    }
+  }
+
+  // It's not a constant expression. Produce an appropriate diagnostic.
+  if (Notes.size() == 1 &&
+      Notes[0].second.getDiagID() == diag::note_invalid_subexpr_in_const_expr)
+    Diag(Notes[0].first, diag::err_expr_not_cce) << CCE;
+  else {
+    Diag(From->getLocStart(), diag::err_expr_not_cce)
+      << CCE << From->getSourceRange();
+    for (unsigned I = 0; I < Notes.size(); ++I)
+      Diag(Notes[I].first, Notes[I].second);
+  }
+  return Result;
+}
+
+/// dropPointerConversions - If the given standard conversion sequence
+/// involves any pointer conversions, remove them.  This may change
+/// the result type of the conversion sequence.
+static void dropPointerConversion(StandardConversionSequence &SCS) {
+  if (SCS.Second == ICK_Pointer_Conversion) {
+    SCS.Second = ICK_Identity;
+    SCS.Third = ICK_Identity;
+    SCS.ToTypePtrs[2] = SCS.ToTypePtrs[1] = SCS.ToTypePtrs[0];
+  }
+}
+
+/// TryContextuallyConvertToObjCPointer - Attempt to contextually
+/// convert the expression From to an Objective-C pointer type.
+static ImplicitConversionSequence
+TryContextuallyConvertToObjCPointer(Sema &S, Expr *From) {
+  // Do an implicit conversion to 'id'.
+  QualType Ty = S.Context.getObjCIdType();
+  ImplicitConversionSequence ICS
+    = TryImplicitConversion(S, From, Ty,
+                            // FIXME: Are these flags correct?
+                            /*SuppressUserConversions=*/false,
+                            /*AllowExplicit=*/true,
+                            /*InOverloadResolution=*/false,
+                            /*CStyle=*/false,
+                            /*AllowObjCWritebackConversion=*/false);
+
+  // Strip off any final conversions to 'id'.
+  switch (ICS.getKind()) {
+  case ImplicitConversionSequence::BadConversion:
+  case ImplicitConversionSequence::AmbiguousConversion:
+  case ImplicitConversionSequence::EllipsisConversion:
+    break;
+
+  case ImplicitConversionSequence::UserDefinedConversion:
+    dropPointerConversion(ICS.UserDefined.After);
+    break;
+
+  case ImplicitConversionSequence::StandardConversion:
+    dropPointerConversion(ICS.Standard);
+    break;
+  }
+
+  return ICS;
+}
+
+/// PerformContextuallyConvertToObjCPointer - Perform a contextual
+/// conversion of the expression From to an Objective-C pointer type.
+ExprResult Sema::PerformContextuallyConvertToObjCPointer(Expr *From) {
+  if (checkPlaceholderForOverload(*this, From))
+    return ExprError();
+
+  QualType Ty = Context.getObjCIdType();
+  ImplicitConversionSequence ICS =
+    TryContextuallyConvertToObjCPointer(*this, From);
+  if (!ICS.isBad())
+    return PerformImplicitConversion(From, Ty, ICS, AA_Converting);
+  return ExprError();
+}
+
+/// Determine whether the provided type is an integral type, or an enumeration
+/// type of a permitted flavor.
+static bool isIntegralOrEnumerationType(QualType T, bool AllowScopedEnum) {
+  return AllowScopedEnum ? T->isIntegralOrEnumerationType()
+                         : T->isIntegralOrUnscopedEnumerationType();
+}
+
+/// \brief Attempt to convert the given expression to an integral or
+/// enumeration type.
+///
+/// This routine will attempt to convert an expression of class type to an
+/// integral or enumeration type, if that class type only has a single
+/// conversion to an integral or enumeration type.
+///
+/// \param Loc The source location of the construct that requires the
+/// conversion.
+///
+/// \param FromE The expression we're converting from.
+///
+/// \param NotIntDiag The diagnostic to be emitted if the expression does not
+/// have integral or enumeration type.
+///
+/// \param IncompleteDiag The diagnostic to be emitted if the expression has
+/// incomplete class type.
+///
+/// \param ExplicitConvDiag The diagnostic to be emitted if we're calling an
+/// explicit conversion function (because no implicit conversion functions
+/// were available). This is a recovery mode.
+///
+/// \param ExplicitConvNote The note to be emitted with \p ExplicitConvDiag,
+/// showing which conversion was picked.
+///
+/// \param AmbigDiag The diagnostic to be emitted if there is more than one
+/// conversion function that could convert to integral or enumeration type.
+///
+/// \param AmbigNote The note to be emitted with \p AmbigDiag for each
+/// usable conversion function.
+///
+/// \param ConvDiag The diagnostic to be emitted if we are calling a conversion
+/// function, which may be an extension in this case.
+///
+/// \param AllowScopedEnumerations Specifies whether conversions to scoped
+/// enumerations should be considered.
+///
+/// \returns The expression, converted to an integral or enumeration type if
+/// successful.
+ExprResult
+Sema::ConvertToIntegralOrEnumerationType(SourceLocation Loc, Expr *From,
+                                         const PartialDiagnostic &NotIntDiag,
+                                       const PartialDiagnostic &IncompleteDiag,
+                                     const PartialDiagnostic &ExplicitConvDiag,
+                                     const PartialDiagnostic &ExplicitConvNote,
+                                         const PartialDiagnostic &AmbigDiag,
+                                         const PartialDiagnostic &AmbigNote,
+                                         const PartialDiagnostic &ConvDiag,
+                                         bool AllowScopedEnumerations) {
+  // We can't perform any more checking for type-dependent expressions.
+  if (From->isTypeDependent())
+    return Owned(From);
+
+  // Process placeholders immediately.
+  if (From->hasPlaceholderType()) {
+    ExprResult result = CheckPlaceholderExpr(From);
+    if (result.isInvalid()) return result;
+    From = result.take();
+  }
+
+  // If the expression already has integral or enumeration type, we're golden.
+  QualType T = From->getType();
+  if (isIntegralOrEnumerationType(T, AllowScopedEnumerations))
+    return DefaultLvalueConversion(From);
+
+  // FIXME: Check for missing '()' if T is a function type?
+
+  // If we don't have a class type in C++, there's no way we can get an
+  // expression of integral or enumeration type.
+  const RecordType *RecordTy = T->getAs<RecordType>();
+  if (!RecordTy || !getLangOpts().CPlusPlus) {
+    if (NotIntDiag.getDiagID())
+      Diag(Loc, NotIntDiag) << T << From->getSourceRange();
+    return Owned(From);
+  }
+
+  // We must have a complete class type.
+  if (RequireCompleteType(Loc, T, IncompleteDiag))
+    return Owned(From);
+
+  // Look for a conversion to an integral or enumeration type.
+  UnresolvedSet<4> ViableConversions;
+  UnresolvedSet<4> ExplicitConversions;
+  const UnresolvedSetImpl *Conversions
+    = cast<CXXRecordDecl>(RecordTy->getDecl())->getVisibleConversionFunctions();
+
+  bool HadMultipleCandidates = (Conversions->size() > 1);
+
+  for (UnresolvedSetImpl::iterator I = Conversions->begin(),
+                                   E = Conversions->end();
+       I != E;
+       ++I) {
+    if (CXXConversionDecl *Conversion
+          = dyn_cast<CXXConversionDecl>((*I)->getUnderlyingDecl())) {
+      if (isIntegralOrEnumerationType(
+            Conversion->getConversionType().getNonReferenceType(),
+            AllowScopedEnumerations)) {
+        if (Conversion->isExplicit())
+          ExplicitConversions.addDecl(I.getDecl(), I.getAccess());
+        else
+          ViableConversions.addDecl(I.getDecl(), I.getAccess());
+      }
+    }
+  }
+
+  switch (ViableConversions.size()) {
+  case 0:
+    if (ExplicitConversions.size() == 1 && ExplicitConvDiag.getDiagID()) {
+      DeclAccessPair Found = ExplicitConversions[0];
+      CXXConversionDecl *Conversion
+        = cast<CXXConversionDecl>(Found->getUnderlyingDecl());
+
+      // The user probably meant to invoke the given explicit
+      // conversion; use it.
+      QualType ConvTy
+        = Conversion->getConversionType().getNonReferenceType();
+      std::string TypeStr;
+      ConvTy.getAsStringInternal(TypeStr, getPrintingPolicy());
+
+      Diag(Loc, ExplicitConvDiag)
+        << T << ConvTy
+        << FixItHint::CreateInsertion(From->getLocStart(),
+                                      "static_cast<" + TypeStr + ">(")
+        << FixItHint::CreateInsertion(PP.getLocForEndOfToken(From->getLocEnd()),
+                                      ")");
+      Diag(Conversion->getLocation(), ExplicitConvNote)
+        << ConvTy->isEnumeralType() << ConvTy;
+
+      // If we aren't in a SFINAE context, build a call to the
+      // explicit conversion function.
+      if (isSFINAEContext())
+        return ExprError();
+
+      CheckMemberOperatorAccess(From->getExprLoc(), From, 0, Found);
+      ExprResult Result = BuildCXXMemberCallExpr(From, Found, Conversion,
+                                                 HadMultipleCandidates);
+      if (Result.isInvalid())
+        return ExprError();
+      // Record usage of conversion in an implicit cast.
+      From = ImplicitCastExpr::Create(Context, Result.get()->getType(),
+                                      CK_UserDefinedConversion,
+                                      Result.get(), 0,
+                                      Result.get()->getValueKind());
+    }
+
+    // We'll complain below about a non-integral condition type.
+    break;
+
+  case 1: {
+    // Apply this conversion.
+    DeclAccessPair Found = ViableConversions[0];
+    CheckMemberOperatorAccess(From->getExprLoc(), From, 0, Found);
+
+    CXXConversionDecl *Conversion
+      = cast<CXXConversionDecl>(Found->getUnderlyingDecl());
+    QualType ConvTy
+      = Conversion->getConversionType().getNonReferenceType();
+    if (ConvDiag.getDiagID()) {
+      if (isSFINAEContext())
+        return ExprError();
+
+      Diag(Loc, ConvDiag)
+        << T << ConvTy->isEnumeralType() << ConvTy << From->getSourceRange();
+    }
+
+    ExprResult Result = BuildCXXMemberCallExpr(From, Found, Conversion,
+                                               HadMultipleCandidates);
+    if (Result.isInvalid())
+      return ExprError();
+    // Record usage of conversion in an implicit cast.
+    From = ImplicitCastExpr::Create(Context, Result.get()->getType(),
+                                    CK_UserDefinedConversion,
+                                    Result.get(), 0,
+                                    Result.get()->getValueKind());
+    break;
+  }
+
+  default:
+    if (!AmbigDiag.getDiagID())
+      return Owned(From);
+
+    Diag(Loc, AmbigDiag)
+      << T << From->getSourceRange();
+    for (unsigned I = 0, N = ViableConversions.size(); I != N; ++I) {
+      CXXConversionDecl *Conv
+        = cast<CXXConversionDecl>(ViableConversions[I]->getUnderlyingDecl());
+      QualType ConvTy = Conv->getConversionType().getNonReferenceType();
+      Diag(Conv->getLocation(), AmbigNote)
+        << ConvTy->isEnumeralType() << ConvTy;
+    }
+    return Owned(From);
+  }
+
+  if (!isIntegralOrEnumerationType(From->getType(), AllowScopedEnumerations) &&
+      NotIntDiag.getDiagID())
+    Diag(Loc, NotIntDiag) << From->getType() << From->getSourceRange();
+
+  return DefaultLvalueConversion(From);
+}
+
+/// AddOverloadCandidate - Adds the given function to the set of
+/// candidate functions, using the given function call arguments.  If
+/// @p SuppressUserConversions, then don't allow user-defined
+/// conversions via constructors or conversion operators.
+///
+/// \para PartialOverloading true if we are performing "partial" overloading
+/// based on an incomplete set of function arguments. This feature is used by
+/// code completion.
+void
+Sema::AddOverloadCandidate(FunctionDecl *Function,
+                           DeclAccessPair FoundDecl,
+                           llvm::ArrayRef<Expr *> Args,
+                           OverloadCandidateSet& CandidateSet,
+                           bool SuppressUserConversions,
+                           bool PartialOverloading,
+                           bool AllowExplicit) {
+  const FunctionProtoType* Proto
+    = dyn_cast<FunctionProtoType>(Function->getType()->getAs<FunctionType>());
+  assert(Proto && "Functions without a prototype cannot be overloaded");
+  assert(!Function->getDescribedFunctionTemplate() &&
+         "Use AddTemplateOverloadCandidate for function templates");
+
+  if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(Function)) {
+    if (!isa<CXXConstructorDecl>(Method)) {
+      // If we get here, it's because we're calling a member function
+      // that is named without a member access expression (e.g.,
+      // "this->f") that was either written explicitly or created
+      // implicitly. This can happen with a qualified call to a member
+      // function, e.g., X::f(). We use an empty type for the implied
+      // object argument (C++ [over.call.func]p3), and the acting context
+      // is irrelevant.
+      AddMethodCandidate(Method, FoundDecl, Method->getParent(),
+                         QualType(), Expr::Classification::makeSimpleLValue(),
+                         Args, CandidateSet, SuppressUserConversions);
+      return;
+    }
+    // We treat a constructor like a non-member function, since its object
+    // argument doesn't participate in overload resolution.
+  }
+
+  if (!CandidateSet.isNewCandidate(Function))
+    return;
+
+  // Overload resolution is always an unevaluated context.
+  EnterExpressionEvaluationContext Unevaluated(*this, Sema::Unevaluated);
+
+  if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(Function)){
+    // C++ [class.copy]p3:
+    //   A member function template is never instantiated to perform the copy
+    //   of a class object to an object of its class type.
+    QualType ClassType = Context.getTypeDeclType(Constructor->getParent());
+    if (Args.size() == 1 &&
+        Constructor->isSpecializationCopyingObject() &&
+        (Context.hasSameUnqualifiedType(ClassType, Args[0]->getType()) ||
+         IsDerivedFrom(Args[0]->getType(), ClassType)))
+      return;
+  }
+
+  // Add this candidate
+  OverloadCandidate &Candidate = CandidateSet.addCandidate(Args.size());
+  Candidate.FoundDecl = FoundDecl;
+  Candidate.Function = Function;
+  Candidate.Viable = true;
+  Candidate.IsSurrogate = false;
+  Candidate.IgnoreObjectArgument = false;
+  Candidate.ExplicitCallArguments = Args.size();
+
+  unsigned NumArgsInProto = Proto->getNumArgs();
+
+  // (C++ 13.3.2p2): A candidate function having fewer than m
+  // parameters is viable only if it has an ellipsis in its parameter
+  // list (8.3.5).
+  if ((Args.size() + (PartialOverloading && Args.size())) > NumArgsInProto &&
+      !Proto->isVariadic()) {
+    Candidate.Viable = false;
+    Candidate.FailureKind = ovl_fail_too_many_arguments;
+    return;
+  }
+
+  // (C++ 13.3.2p2): A candidate function having more than m parameters
+  // is viable only if the (m+1)st parameter has a default argument
+  // (8.3.6). For the purposes of overload resolution, the
+  // parameter list is truncated on the right, so that there are
+  // exactly m parameters.
+  unsigned MinRequiredArgs = Function->getMinRequiredArguments();
+  if (Args.size() < MinRequiredArgs && !PartialOverloading) {
+    // Not enough arguments.
+    Candidate.Viable = false;
+    Candidate.FailureKind = ovl_fail_too_few_arguments;
+    return;
+  }
+
+  // (CUDA B.1): Check for invalid calls between targets.
+  if (getLangOpts().CUDA)
+    if (const FunctionDecl *Caller = dyn_cast<FunctionDecl>(CurContext))
+      if (CheckCUDATarget(Caller, Function)) {
+        Candidate.Viable = false;
+        Candidate.FailureKind = ovl_fail_bad_target;
+        return;
+      }
+
+  // Determine the implicit conversion sequences for each of the
+  // arguments.
+  for (unsigned ArgIdx = 0; ArgIdx < Args.size(); ++ArgIdx) {
+    if (ArgIdx < NumArgsInProto) {
+      // (C++ 13.3.2p3): for F to be a viable function, there shall
+      // exist for each argument an implicit conversion sequence
+      // (13.3.3.1) that converts that argument to the corresponding
+      // parameter of F.
+      QualType ParamType = Proto->getArgType(ArgIdx);
+      Candidate.Conversions[ArgIdx]
+        = TryCopyInitialization(*this, Args[ArgIdx], ParamType,
+                                SuppressUserConversions,
+                                /*InOverloadResolution=*/true,
+                                /*AllowObjCWritebackConversion=*/
+                                  getLangOpts().ObjCAutoRefCount,
+                                AllowExplicit);
+      if (Candidate.Conversions[ArgIdx].isBad()) {
+        Candidate.Viable = false;
+        Candidate.FailureKind = ovl_fail_bad_conversion;
+        break;
+      }
+    } else {
+      // (C++ 13.3.2p2): For the purposes of overload resolution, any
+      // argument for which there is no corresponding parameter is
+      // considered to ""match the ellipsis" (C+ 13.3.3.1.3).
+      Candidate.Conversions[ArgIdx].setEllipsis();
+    }
+  }
+}
+
+/// \brief Add all of the function declarations in the given function set to
+/// the overload canddiate set.
+void Sema::AddFunctionCandidates(const UnresolvedSetImpl &Fns,
+                                 llvm::ArrayRef<Expr *> Args,
+                                 OverloadCandidateSet& CandidateSet,
+                                 bool SuppressUserConversions,
+                               TemplateArgumentListInfo *ExplicitTemplateArgs) {
+  for (UnresolvedSetIterator F = Fns.begin(), E = Fns.end(); F != E; ++F) {
+    NamedDecl *D = F.getDecl()->getUnderlyingDecl();
+    if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
+      if (isa<CXXMethodDecl>(FD) && !cast<CXXMethodDecl>(FD)->isStatic())
+        AddMethodCandidate(cast<CXXMethodDecl>(FD), F.getPair(),
+                           cast<CXXMethodDecl>(FD)->getParent(),
+                           Args[0]->getType(), Args[0]->Classify(Context),
+                           Args.slice(1), CandidateSet,
+                           SuppressUserConversions);
+      else
+        AddOverloadCandidate(FD, F.getPair(), Args, CandidateSet,
+                             SuppressUserConversions);
+    } else {
+      FunctionTemplateDecl *FunTmpl = cast<FunctionTemplateDecl>(D);
+      if (isa<CXXMethodDecl>(FunTmpl->getTemplatedDecl()) &&
+          !cast<CXXMethodDecl>(FunTmpl->getTemplatedDecl())->isStatic())
+        AddMethodTemplateCandidate(FunTmpl, F.getPair(),
+                              cast<CXXRecordDecl>(FunTmpl->getDeclContext()),
+                                   ExplicitTemplateArgs,
+                                   Args[0]->getType(),
+                                   Args[0]->Classify(Context), Args.slice(1),
+                                   CandidateSet, SuppressUserConversions);
+      else
+        AddTemplateOverloadCandidate(FunTmpl, F.getPair(),
+                                     ExplicitTemplateArgs, Args,
+                                     CandidateSet, SuppressUserConversions);
+    }
+  }
+}
+
+/// AddMethodCandidate - Adds a named decl (which is some kind of
+/// method) as a method candidate to the given overload set.
+void Sema::AddMethodCandidate(DeclAccessPair FoundDecl,
+                              QualType ObjectType,
+                              Expr::Classification ObjectClassification,
+                              Expr **Args, unsigned NumArgs,
+                              OverloadCandidateSet& CandidateSet,
+                              bool SuppressUserConversions) {
+  NamedDecl *Decl = FoundDecl.getDecl();
+  CXXRecordDecl *ActingContext = cast<CXXRecordDecl>(Decl->getDeclContext());
+
+  if (isa<UsingShadowDecl>(Decl))
+    Decl = cast<UsingShadowDecl>(Decl)->getTargetDecl();
+
+  if (FunctionTemplateDecl *TD = dyn_cast<FunctionTemplateDecl>(Decl)) {
+    assert(isa<CXXMethodDecl>(TD->getTemplatedDecl()) &&
+           "Expected a member function template");
+    AddMethodTemplateCandidate(TD, FoundDecl, ActingContext,
+                               /*ExplicitArgs*/ 0,
+                               ObjectType, ObjectClassification,
+                               llvm::makeArrayRef(Args, NumArgs), CandidateSet,
+                               SuppressUserConversions);
+  } else {
+    AddMethodCandidate(cast<CXXMethodDecl>(Decl), FoundDecl, ActingContext,
+                       ObjectType, ObjectClassification,
+                       llvm::makeArrayRef(Args, NumArgs),
+                       CandidateSet, SuppressUserConversions);
+  }
+}
+
+/// AddMethodCandidate - Adds the given C++ member function to the set
+/// of candidate functions, using the given function call arguments
+/// and the object argument (@c Object). For example, in a call
+/// @c o.f(a1,a2), @c Object will contain @c o and @c Args will contain
+/// both @c a1 and @c a2. If @p SuppressUserConversions, then don't
+/// allow user-defined conversions via constructors or conversion
+/// operators.
+void
+Sema::AddMethodCandidate(CXXMethodDecl *Method, DeclAccessPair FoundDecl,
+                         CXXRecordDecl *ActingContext, QualType ObjectType,
+                         Expr::Classification ObjectClassification,
+                         llvm::ArrayRef<Expr *> Args,
+                         OverloadCandidateSet& CandidateSet,
+                         bool SuppressUserConversions) {
+  const FunctionProtoType* Proto
+    = dyn_cast<FunctionProtoType>(Method->getType()->getAs<FunctionType>());
+  assert(Proto && "Methods without a prototype cannot be overloaded");
+  assert(!isa<CXXConstructorDecl>(Method) &&
+         "Use AddOverloadCandidate for constructors");
+
+  if (!CandidateSet.isNewCandidate(Method))
+    return;
+
+  // Overload resolution is always an unevaluated context.
+  EnterExpressionEvaluationContext Unevaluated(*this, Sema::Unevaluated);
+
+  // Add this candidate
+  OverloadCandidate &Candidate = CandidateSet.addCandidate(Args.size() + 1);
+  Candidate.FoundDecl = FoundDecl;
+  Candidate.Function = Method;
+  Candidate.IsSurrogate = false;
+  Candidate.IgnoreObjectArgument = false;
+  Candidate.ExplicitCallArguments = Args.size();
+
+  unsigned NumArgsInProto = Proto->getNumArgs();
+
+  // (C++ 13.3.2p2): A candidate function having fewer than m
+  // parameters is viable only if it has an ellipsis in its parameter
+  // list (8.3.5).
+  if (Args.size() > NumArgsInProto && !Proto->isVariadic()) {
+    Candidate.Viable = false;
+    Candidate.FailureKind = ovl_fail_too_many_arguments;
+    return;
+  }
+
+  // (C++ 13.3.2p2): A candidate function having more than m parameters
+  // is viable only if the (m+1)st parameter has a default argument
+  // (8.3.6). For the purposes of overload resolution, the
+  // parameter list is truncated on the right, so that there are
+  // exactly m parameters.
+  unsigned MinRequiredArgs = Method->getMinRequiredArguments();
+  if (Args.size() < MinRequiredArgs) {
+    // Not enough arguments.
+    Candidate.Viable = false;
+    Candidate.FailureKind = ovl_fail_too_few_arguments;
+    return;
+  }
+
+  Candidate.Viable = true;
+
+  if (Method->isStatic() || ObjectType.isNull())
+    // The implicit object argument is ignored.
+    Candidate.IgnoreObjectArgument = true;
+  else {
+    // Determine the implicit conversion sequence for the object
+    // parameter.
+    Candidate.Conversions[0]
+      = TryObjectArgumentInitialization(*this, ObjectType, ObjectClassification,
+                                        Method, ActingContext);
+    if (Candidate.Conversions[0].isBad()) {
+      Candidate.Viable = false;
+      Candidate.FailureKind = ovl_fail_bad_conversion;
+      return;
+    }
+  }
+
+  // Determine the implicit conversion sequences for each of the
+  // arguments.
+  for (unsigned ArgIdx = 0; ArgIdx < Args.size(); ++ArgIdx) {
+    if (ArgIdx < NumArgsInProto) {
+      // (C++ 13.3.2p3): for F to be a viable function, there shall
+      // exist for each argument an implicit conversion sequence
+      // (13.3.3.1) that converts that argument to the corresponding
+      // parameter of F.
+      QualType ParamType = Proto->getArgType(ArgIdx);
+      Candidate.Conversions[ArgIdx + 1]
+        = TryCopyInitialization(*this, Args[ArgIdx], ParamType,
+                                SuppressUserConversions,
+                                /*InOverloadResolution=*/true,
+                                /*AllowObjCWritebackConversion=*/
+                                  getLangOpts().ObjCAutoRefCount);
+      if (Candidate.Conversions[ArgIdx + 1].isBad()) {
+        Candidate.Viable = false;
+        Candidate.FailureKind = ovl_fail_bad_conversion;
+        break;
+      }
+    } else {
+      // (C++ 13.3.2p2): For the purposes of overload resolution, any
+      // argument for which there is no corresponding parameter is
+      // considered to ""match the ellipsis" (C+ 13.3.3.1.3).
+      Candidate.Conversions[ArgIdx + 1].setEllipsis();
+    }
+  }
+}
+
+/// \brief Add a C++ member function template as a candidate to the candidate
+/// set, using template argument deduction to produce an appropriate member
+/// function template specialization.
+void
+Sema::AddMethodTemplateCandidate(FunctionTemplateDecl *MethodTmpl,
+                                 DeclAccessPair FoundDecl,
+                                 CXXRecordDecl *ActingContext,
+                                 TemplateArgumentListInfo *ExplicitTemplateArgs,
+                                 QualType ObjectType,
+                                 Expr::Classification ObjectClassification,
+                                 llvm::ArrayRef<Expr *> Args,
+                                 OverloadCandidateSet& CandidateSet,
+                                 bool SuppressUserConversions) {
+  if (!CandidateSet.isNewCandidate(MethodTmpl))
+    return;
+
+  // C++ [over.match.funcs]p7:
+  //   In each case where a candidate is a function template, candidate
+  //   function template specializations are generated using template argument
+  //   deduction (14.8.3, 14.8.2). Those candidates are then handled as
+  //   candidate functions in the usual way.113) A given name can refer to one
+  //   or more function templates and also to a set of overloaded non-template
+  //   functions. In such a case, the candidate functions generated from each
+  //   function template are combined with the set of non-template candidate
+  //   functions.
+  TemplateDeductionInfo Info(Context, CandidateSet.getLocation());
+  FunctionDecl *Specialization = 0;
+  if (TemplateDeductionResult Result
+      = DeduceTemplateArguments(MethodTmpl, ExplicitTemplateArgs, Args,
+                                Specialization, Info)) {
+    OverloadCandidate &Candidate = CandidateSet.addCandidate();
+    Candidate.FoundDecl = FoundDecl;
+    Candidate.Function = MethodTmpl->getTemplatedDecl();
+    Candidate.Viable = false;
+    Candidate.FailureKind = ovl_fail_bad_deduction;
+    Candidate.IsSurrogate = false;
+    Candidate.IgnoreObjectArgument = false;
+    Candidate.ExplicitCallArguments = Args.size();
+    Candidate.DeductionFailure = MakeDeductionFailureInfo(Context, Result,
+                                                          Info);
+    return;
+  }
+
+  // Add the function template specialization produced by template argument
+  // deduction as a candidate.
+  assert(Specialization && "Missing member function template specialization?");
+  assert(isa<CXXMethodDecl>(Specialization) &&
+         "Specialization is not a member function?");
+  AddMethodCandidate(cast<CXXMethodDecl>(Specialization), FoundDecl,
+                     ActingContext, ObjectType, ObjectClassification, Args,
+                     CandidateSet, SuppressUserConversions);
+}
+
+/// \brief Add a C++ function template specialization as a candidate
+/// in the candidate set, using template argument deduction to produce
+/// an appropriate function template specialization.
+void
+Sema::AddTemplateOverloadCandidate(FunctionTemplateDecl *FunctionTemplate,
+                                   DeclAccessPair FoundDecl,
+                                 TemplateArgumentListInfo *ExplicitTemplateArgs,
+                                   llvm::ArrayRef<Expr *> Args,
+                                   OverloadCandidateSet& CandidateSet,
+                                   bool SuppressUserConversions) {
+  if (!CandidateSet.isNewCandidate(FunctionTemplate))
+    return;
+
+  // C++ [over.match.funcs]p7:
+  //   In each case where a candidate is a function template, candidate
+  //   function template specializations are generated using template argument
+  //   deduction (14.8.3, 14.8.2). Those candidates are then handled as
+  //   candidate functions in the usual way.113) A given name can refer to one
+  //   or more function templates and also to a set of overloaded non-template
+  //   functions. In such a case, the candidate functions generated from each
+  //   function template are combined with the set of non-template candidate
+  //   functions.
+  TemplateDeductionInfo Info(Context, CandidateSet.getLocation());
+  FunctionDecl *Specialization = 0;
+  if (TemplateDeductionResult Result
+        = DeduceTemplateArguments(FunctionTemplate, ExplicitTemplateArgs, Args,
+                                  Specialization, Info)) {
+    OverloadCandidate &Candidate = CandidateSet.addCandidate();
+    Candidate.FoundDecl = FoundDecl;
+    Candidate.Function = FunctionTemplate->getTemplatedDecl();
+    Candidate.Viable = false;
+    Candidate.FailureKind = ovl_fail_bad_deduction;
+    Candidate.IsSurrogate = false;
+    Candidate.IgnoreObjectArgument = false;
+    Candidate.ExplicitCallArguments = Args.size();
+    Candidate.DeductionFailure = MakeDeductionFailureInfo(Context, Result,
+                                                          Info);
+    return;
+  }
+
+  // Add the function template specialization produced by template argument
+  // deduction as a candidate.
+  assert(Specialization && "Missing function template specialization?");
+  AddOverloadCandidate(Specialization, FoundDecl, Args, CandidateSet,
+                       SuppressUserConversions);
+}
+
+/// AddConversionCandidate - Add a C++ conversion function as a
+/// candidate in the candidate set (C++ [over.match.conv],
+/// C++ [over.match.copy]). From is the expression we're converting from,
+/// and ToType is the type that we're eventually trying to convert to
+/// (which may or may not be the same type as the type that the
+/// conversion function produces).
+void
+Sema::AddConversionCandidate(CXXConversionDecl *Conversion,
+                             DeclAccessPair FoundDecl,
+                             CXXRecordDecl *ActingContext,
+                             Expr *From, QualType ToType,
+                             OverloadCandidateSet& CandidateSet) {
+  assert(!Conversion->getDescribedFunctionTemplate() &&
+         "Conversion function templates use AddTemplateConversionCandidate");
+  QualType ConvType = Conversion->getConversionType().getNonReferenceType();
+  if (!CandidateSet.isNewCandidate(Conversion))
+    return;
+
+  // Overload resolution is always an unevaluated context.
+  EnterExpressionEvaluationContext Unevaluated(*this, Sema::Unevaluated);
+
+  // Add this candidate
+  OverloadCandidate &Candidate = CandidateSet.addCandidate(1);
+  Candidate.FoundDecl = FoundDecl;
+  Candidate.Function = Conversion;
+  Candidate.IsSurrogate = false;
+  Candidate.IgnoreObjectArgument = false;
+  Candidate.FinalConversion.setAsIdentityConversion();
+  Candidate.FinalConversion.setFromType(ConvType);
+  Candidate.FinalConversion.setAllToTypes(ToType);
+  Candidate.Viable = true;
+  Candidate.ExplicitCallArguments = 1;
+
+  // C++ [over.match.funcs]p4:
+  //   For conversion functions, the function is considered to be a member of
+  //   the class of the implicit implied object argument for the purpose of
+  //   defining the type of the implicit object parameter.
+  //
+  // Determine the implicit conversion sequence for the implicit
+  // object parameter.
+  QualType ImplicitParamType = From->getType();
+  if (const PointerType *FromPtrType = ImplicitParamType->getAs<PointerType>())
+    ImplicitParamType = FromPtrType->getPointeeType();
+  CXXRecordDecl *ConversionContext
+    = cast<CXXRecordDecl>(ImplicitParamType->getAs<RecordType>()->getDecl());
+
+  Candidate.Conversions[0]
+    = TryObjectArgumentInitialization(*this, From->getType(),
+                                      From->Classify(Context),
+                                      Conversion, ConversionContext);
+
+  if (Candidate.Conversions[0].isBad()) {
+    Candidate.Viable = false;
+    Candidate.FailureKind = ovl_fail_bad_conversion;
+    return;
+  }
+
+  // We won't go through a user-define type conversion function to convert a
+  // derived to base as such conversions are given Conversion Rank. They only
+  // go through a copy constructor. 13.3.3.1.2-p4 [over.ics.user]
+  QualType FromCanon
+    = Context.getCanonicalType(From->getType().getUnqualifiedType());
+  QualType ToCanon = Context.getCanonicalType(ToType).getUnqualifiedType();
+  if (FromCanon == ToCanon || IsDerivedFrom(FromCanon, ToCanon)) {
+    Candidate.Viable = false;
+    Candidate.FailureKind = ovl_fail_trivial_conversion;
+    return;
+  }
+
+  // To determine what the conversion from the result of calling the
+  // conversion function to the type we're eventually trying to
+  // convert to (ToType), we need to synthesize a call to the
+  // conversion function and attempt copy initialization from it. This
+  // makes sure that we get the right semantics with respect to
+  // lvalues/rvalues and the type. Fortunately, we can allocate this
+  // call on the stack and we don't need its arguments to be
+  // well-formed.
+  DeclRefExpr ConversionRef(Conversion, false, Conversion->getType(),
+                            VK_LValue, From->getLocStart());
+  ImplicitCastExpr ConversionFn(ImplicitCastExpr::OnStack,
+                                Context.getPointerType(Conversion->getType()),
+                                CK_FunctionToPointerDecay,
+                                &ConversionRef, VK_RValue);
+
+  QualType ConversionType = Conversion->getConversionType();
+  if (RequireCompleteType(From->getLocStart(), ConversionType, 0)) {
+    Candidate.Viable = false;
+    Candidate.FailureKind = ovl_fail_bad_final_conversion;
+    return;
+  }
+
+  ExprValueKind VK = Expr::getValueKindForType(ConversionType);
+
+  // Note that it is safe to allocate CallExpr on the stack here because
+  // there are 0 arguments (i.e., nothing is allocated using ASTContext's
+  // allocator).
+  QualType CallResultType = ConversionType.getNonLValueExprType(Context);
+  CallExpr Call(Context, &ConversionFn, 0, 0, CallResultType, VK,
+                From->getLocStart());
+  ImplicitConversionSequence ICS =
+    TryCopyInitialization(*this, &Call, ToType,
+                          /*SuppressUserConversions=*/true,
+                          /*InOverloadResolution=*/false,
+                          /*AllowObjCWritebackConversion=*/false);
+
+  switch (ICS.getKind()) {
+  case ImplicitConversionSequence::StandardConversion:
+    Candidate.FinalConversion = ICS.Standard;
+
+    // C++ [over.ics.user]p3:
+    //   If the user-defined conversion is specified by a specialization of a
+    //   conversion function template, the second standard conversion sequence
+    //   shall have exact match rank.
+    if (Conversion->getPrimaryTemplate() &&
+        GetConversionRank(ICS.Standard.Second) != ICR_Exact_Match) {
+      Candidate.Viable = false;
+      Candidate.FailureKind = ovl_fail_final_conversion_not_exact;
+    }
+
+    // C++0x [dcl.init.ref]p5:
+    //    In the second case, if the reference is an rvalue reference and
+    //    the second standard conversion sequence of the user-defined
+    //    conversion sequence includes an lvalue-to-rvalue conversion, the
+    //    program is ill-formed.
+    if (ToType->isRValueReferenceType() &&
+        ICS.Standard.First == ICK_Lvalue_To_Rvalue) {
+      Candidate.Viable = false;
+      Candidate.FailureKind = ovl_fail_bad_final_conversion;
+    }
+    break;
+
+  case ImplicitConversionSequence::BadConversion:
+    Candidate.Viable = false;
+    Candidate.FailureKind = ovl_fail_bad_final_conversion;
+    break;
+
+  default:
+    llvm_unreachable(
+           "Can only end up with a standard conversion sequence or failure");
+  }
+}
+
+/// \brief Adds a conversion function template specialization
+/// candidate to the overload set, using template argument deduction
+/// to deduce the template arguments of the conversion function
+/// template from the type that we are converting to (C++
+/// [temp.deduct.conv]).
+void
+Sema::AddTemplateConversionCandidate(FunctionTemplateDecl *FunctionTemplate,
+                                     DeclAccessPair FoundDecl,
+                                     CXXRecordDecl *ActingDC,
+                                     Expr *From, QualType ToType,
+                                     OverloadCandidateSet &CandidateSet) {
+  assert(isa<CXXConversionDecl>(FunctionTemplate->getTemplatedDecl()) &&
+         "Only conversion function templates permitted here");
+
+  if (!CandidateSet.isNewCandidate(FunctionTemplate))
+    return;
+
+  TemplateDeductionInfo Info(Context, CandidateSet.getLocation());
+  CXXConversionDecl *Specialization = 0;
+  if (TemplateDeductionResult Result
+        = DeduceTemplateArguments(FunctionTemplate, ToType,
+                                  Specialization, Info)) {
+    OverloadCandidate &Candidate = CandidateSet.addCandidate();
+    Candidate.FoundDecl = FoundDecl;
+    Candidate.Function = FunctionTemplate->getTemplatedDecl();
+    Candidate.Viable = false;
+    Candidate.FailureKind = ovl_fail_bad_deduction;
+    Candidate.IsSurrogate = false;
+    Candidate.IgnoreObjectArgument = false;
+    Candidate.ExplicitCallArguments = 1;
+    Candidate.DeductionFailure = MakeDeductionFailureInfo(Context, Result,
+                                                          Info);
+    return;
+  }
+
+  // Add the conversion function template specialization produced by
+  // template argument deduction as a candidate.
+  assert(Specialization && "Missing function template specialization?");
+  AddConversionCandidate(Specialization, FoundDecl, ActingDC, From, ToType,
+                         CandidateSet);
+}
+
+/// AddSurrogateCandidate - Adds a "surrogate" candidate function that
+/// converts the given @c Object to a function pointer via the
+/// conversion function @c Conversion, and then attempts to call it
+/// with the given arguments (C++ [over.call.object]p2-4). Proto is
+/// the type of function that we'll eventually be calling.
+void Sema::AddSurrogateCandidate(CXXConversionDecl *Conversion,
+                                 DeclAccessPair FoundDecl,
+                                 CXXRecordDecl *ActingContext,
+                                 const FunctionProtoType *Proto,
+                                 Expr *Object,
+                                 llvm::ArrayRef<Expr *> Args,
+                                 OverloadCandidateSet& CandidateSet) {
+  if (!CandidateSet.isNewCandidate(Conversion))
+    return;
+
+  // Overload resolution is always an unevaluated context.
+  EnterExpressionEvaluationContext Unevaluated(*this, Sema::Unevaluated);
+
+  OverloadCandidate &Candidate = CandidateSet.addCandidate(Args.size() + 1);
+  Candidate.FoundDecl = FoundDecl;
+  Candidate.Function = 0;
+  Candidate.Surrogate = Conversion;
+  Candidate.Viable = true;
+  Candidate.IsSurrogate = true;
+  Candidate.IgnoreObjectArgument = false;
+  Candidate.ExplicitCallArguments = Args.size();
+
+  // Determine the implicit conversion sequence for the implicit
+  // object parameter.
+  ImplicitConversionSequence ObjectInit
+    = TryObjectArgumentInitialization(*this, Object->getType(),
+                                      Object->Classify(Context),
+                                      Conversion, ActingContext);
+  if (ObjectInit.isBad()) {
+    Candidate.Viable = false;
+    Candidate.FailureKind = ovl_fail_bad_conversion;
+    Candidate.Conversions[0] = ObjectInit;
+    return;
+  }
+
+  // The first conversion is actually a user-defined conversion whose
+  // first conversion is ObjectInit's standard conversion (which is
+  // effectively a reference binding). Record it as such.
+  Candidate.Conversions[0].setUserDefined();
+  Candidate.Conversions[0].UserDefined.Before = ObjectInit.Standard;
+  Candidate.Conversions[0].UserDefined.EllipsisConversion = false;
+  Candidate.Conversions[0].UserDefined.HadMultipleCandidates = false;
+  Candidate.Conversions[0].UserDefined.ConversionFunction = Conversion;
+  Candidate.Conversions[0].UserDefined.FoundConversionFunction = FoundDecl;
+  Candidate.Conversions[0].UserDefined.After
+    = Candidate.Conversions[0].UserDefined.Before;
+  Candidate.Conversions[0].UserDefined.After.setAsIdentityConversion();
+
+  // Find the
+  unsigned NumArgsInProto = Proto->getNumArgs();
+
+  // (C++ 13.3.2p2): A candidate function having fewer than m
+  // parameters is viable only if it has an ellipsis in its parameter
+  // list (8.3.5).
+  if (Args.size() > NumArgsInProto && !Proto->isVariadic()) {
+    Candidate.Viable = false;
+    Candidate.FailureKind = ovl_fail_too_many_arguments;
+    return;
+  }
+
+  // Function types don't have any default arguments, so just check if
+  // we have enough arguments.
+  if (Args.size() < NumArgsInProto) {
+    // Not enough arguments.
+    Candidate.Viable = false;
+    Candidate.FailureKind = ovl_fail_too_few_arguments;
+    return;
+  }
+
+  // Determine the implicit conversion sequences for each of the
+  // arguments.
+  for (unsigned ArgIdx = 0; ArgIdx < Args.size(); ++ArgIdx) {
+    if (ArgIdx < NumArgsInProto) {
+      // (C++ 13.3.2p3): for F to be a viable function, there shall
+      // exist for each argument an implicit conversion sequence
+      // (13.3.3.1) that converts that argument to the corresponding
+      // parameter of F.
+      QualType ParamType = Proto->getArgType(ArgIdx);
+      Candidate.Conversions[ArgIdx + 1]
+        = TryCopyInitialization(*this, Args[ArgIdx], ParamType,
+                                /*SuppressUserConversions=*/false,
+                                /*InOverloadResolution=*/false,
+                                /*AllowObjCWritebackConversion=*/
+                                  getLangOpts().ObjCAutoRefCount);
+      if (Candidate.Conversions[ArgIdx + 1].isBad()) {
+        Candidate.Viable = false;
+        Candidate.FailureKind = ovl_fail_bad_conversion;
+        break;
+      }
+    } else {
+      // (C++ 13.3.2p2): For the purposes of overload resolution, any
+      // argument for which there is no corresponding parameter is
+      // considered to ""match the ellipsis" (C+ 13.3.3.1.3).
+      Candidate.Conversions[ArgIdx + 1].setEllipsis();
+    }
+  }
+}
+
+/// \brief Add overload candidates for overloaded operators that are
+/// member functions.
+///
+/// Add the overloaded operator candidates that are member functions
+/// for the operator Op that was used in an operator expression such
+/// as "x Op y". , Args/NumArgs provides the operator arguments, and
+/// CandidateSet will store the added overload candidates. (C++
+/// [over.match.oper]).
+void Sema::AddMemberOperatorCandidates(OverloadedOperatorKind Op,
+                                       SourceLocation OpLoc,
+                                       Expr **Args, unsigned NumArgs,
+                                       OverloadCandidateSet& CandidateSet,
+                                       SourceRange OpRange) {
+  DeclarationName OpName = Context.DeclarationNames.getCXXOperatorName(Op);
+
+  // C++ [over.match.oper]p3:
+  //   For a unary operator @ with an operand of a type whose
+  //   cv-unqualified version is T1, and for a binary operator @ with
+  //   a left operand of a type whose cv-unqualified version is T1 and
+  //   a right operand of a type whose cv-unqualified version is T2,
+  //   three sets of candidate functions, designated member
+  //   candidates, non-member candidates and built-in candidates, are
+  //   constructed as follows:
+  QualType T1 = Args[0]->getType();
+
+  //     -- If T1 is a class type, the set of member candidates is the
+  //        result of the qualified lookup of T1::operator@
+  //        (13.3.1.1.1); otherwise, the set of member candidates is
+  //        empty.
+  if (const RecordType *T1Rec = T1->getAs<RecordType>()) {
+    // Complete the type if it can be completed. Otherwise, we're done.
+    if (RequireCompleteType(OpLoc, T1, PDiag()))
+      return;
+
+    LookupResult Operators(*this, OpName, OpLoc, LookupOrdinaryName);
+    LookupQualifiedName(Operators, T1Rec->getDecl());
+    Operators.suppressDiagnostics();
+
+    for (LookupResult::iterator Oper = Operators.begin(),
+                             OperEnd = Operators.end();
+         Oper != OperEnd;
+         ++Oper)
+      AddMethodCandidate(Oper.getPair(), Args[0]->getType(),
+                         Args[0]->Classify(Context), Args + 1, NumArgs - 1,
+                         CandidateSet,
+                         /* SuppressUserConversions = */ false);
+  }
+}
+
+/// AddBuiltinCandidate - Add a candidate for a built-in
+/// operator. ResultTy and ParamTys are the result and parameter types
+/// of the built-in candidate, respectively. Args and NumArgs are the
+/// arguments being passed to the candidate. IsAssignmentOperator
+/// should be true when this built-in candidate is an assignment
+/// operator. NumContextualBoolArguments is the number of arguments
+/// (at the beginning of the argument list) that will be contextually
+/// converted to bool.
+void Sema::AddBuiltinCandidate(QualType ResultTy, QualType *ParamTys,
+                               Expr **Args, unsigned NumArgs,
+                               OverloadCandidateSet& CandidateSet,
+                               bool IsAssignmentOperator,
+                               unsigned NumContextualBoolArguments) {
+  // Overload resolution is always an unevaluated context.
+  EnterExpressionEvaluationContext Unevaluated(*this, Sema::Unevaluated);
+
+  // Add this candidate
+  OverloadCandidate &Candidate = CandidateSet.addCandidate(NumArgs);
+  Candidate.FoundDecl = DeclAccessPair::make(0, AS_none);
+  Candidate.Function = 0;
+  Candidate.IsSurrogate = false;
+  Candidate.IgnoreObjectArgument = false;
+  Candidate.BuiltinTypes.ResultTy = ResultTy;
+  for (unsigned ArgIdx = 0; ArgIdx < NumArgs; ++ArgIdx)
+    Candidate.BuiltinTypes.ParamTypes[ArgIdx] = ParamTys[ArgIdx];
+
+  // Determine the implicit conversion sequences for each of the
+  // arguments.
+  Candidate.Viable = true;
+  Candidate.ExplicitCallArguments = NumArgs;
+  for (unsigned ArgIdx = 0; ArgIdx < NumArgs; ++ArgIdx) {
+    // C++ [over.match.oper]p4:
+    //   For the built-in assignment operators, conversions of the
+    //   left operand are restricted as follows:
+    //     -- no temporaries are introduced to hold the left operand, and
+    //     -- no user-defined conversions are applied to the left
+    //        operand to achieve a type match with the left-most
+    //        parameter of a built-in candidate.
+    //
+    // We block these conversions by turning off user-defined
+    // conversions, since that is the only way that initialization of
+    // a reference to a non-class type can occur from something that
+    // is not of the same type.
+    if (ArgIdx < NumContextualBoolArguments) {
+      assert(ParamTys[ArgIdx] == Context.BoolTy &&
+             "Contextual conversion to bool requires bool type");
+      Candidate.Conversions[ArgIdx]
+        = TryContextuallyConvertToBool(*this, Args[ArgIdx]);
+    } else {
+      Candidate.Conversions[ArgIdx]
+        = TryCopyInitialization(*this, Args[ArgIdx], ParamTys[ArgIdx],
+                                ArgIdx == 0 && IsAssignmentOperator,
+                                /*InOverloadResolution=*/false,
+                                /*AllowObjCWritebackConversion=*/
+                                  getLangOpts().ObjCAutoRefCount);
+    }
+    if (Candidate.Conversions[ArgIdx].isBad()) {
+      Candidate.Viable = false;
+      Candidate.FailureKind = ovl_fail_bad_conversion;
+      break;
+    }
+  }
+}
+
+/// BuiltinCandidateTypeSet - A set of types that will be used for the
+/// candidate operator functions for built-in operators (C++
+/// [over.built]). The types are separated into pointer types and
+/// enumeration types.
+class BuiltinCandidateTypeSet  {
+  /// TypeSet - A set of types.
+  typedef llvm::SmallPtrSet<QualType, 8> TypeSet;
+
+  /// PointerTypes - The set of pointer types that will be used in the
+  /// built-in candidates.
+  TypeSet PointerTypes;
+
+  /// MemberPointerTypes - The set of member pointer types that will be
+  /// used in the built-in candidates.
+  TypeSet MemberPointerTypes;
+
+  /// EnumerationTypes - The set of enumeration types that will be
+  /// used in the built-in candidates.
+  TypeSet EnumerationTypes;
+
+  /// \brief The set of vector types that will be used in the built-in
+  /// candidates.
+  TypeSet VectorTypes;
+
+  /// \brief A flag indicating non-record types are viable candidates
+  bool HasNonRecordTypes;
+
+  /// \brief A flag indicating whether either arithmetic or enumeration types
+  /// were present in the candidate set.
+  bool HasArithmeticOrEnumeralTypes;
+
+  /// \brief A flag indicating whether the nullptr type was present in the
+  /// candidate set.
+  bool HasNullPtrType;
+  
+  /// Sema - The semantic analysis instance where we are building the
+  /// candidate type set.
+  Sema &SemaRef;
+
+  /// Context - The AST context in which we will build the type sets.
+  ASTContext &Context;
+
+  bool AddPointerWithMoreQualifiedTypeVariants(QualType Ty,
+                                               const Qualifiers &VisibleQuals);
+  bool AddMemberPointerWithMoreQualifiedTypeVariants(QualType Ty);
+
+public:
+  /// iterator - Iterates through the types that are part of the set.
+  typedef TypeSet::iterator iterator;
+
+  BuiltinCandidateTypeSet(Sema &SemaRef)
+    : HasNonRecordTypes(false),
+      HasArithmeticOrEnumeralTypes(false),
+      HasNullPtrType(false),
+      SemaRef(SemaRef),
+      Context(SemaRef.Context) { }
+
+  void AddTypesConvertedFrom(QualType Ty,
+                             SourceLocation Loc,
+                             bool AllowUserConversions,
+                             bool AllowExplicitConversions,
+                             const Qualifiers &VisibleTypeConversionsQuals);
+
+  /// pointer_begin - First pointer type found;
+  iterator pointer_begin() { return PointerTypes.begin(); }
+
+  /// pointer_end - Past the last pointer type found;
+  iterator pointer_end() { return PointerTypes.end(); }
+
+  /// member_pointer_begin - First member pointer type found;
+  iterator member_pointer_begin() { return MemberPointerTypes.begin(); }
+
+  /// member_pointer_end - Past the last member pointer type found;
+  iterator member_pointer_end() { return MemberPointerTypes.end(); }
+
+  /// enumeration_begin - First enumeration type found;
+  iterator enumeration_begin() { return EnumerationTypes.begin(); }
+
+  /// enumeration_end - Past the last enumeration type found;
+  iterator enumeration_end() { return EnumerationTypes.end(); }
+
+  iterator vector_begin() { return VectorTypes.begin(); }
+  iterator vector_end() { return VectorTypes.end(); }
+
+  bool hasNonRecordTypes() { return HasNonRecordTypes; }
+  bool hasArithmeticOrEnumeralTypes() { return HasArithmeticOrEnumeralTypes; }
+  bool hasNullPtrType() const { return HasNullPtrType; }
+};
+
+/// AddPointerWithMoreQualifiedTypeVariants - Add the pointer type @p Ty to
+/// the set of pointer types along with any more-qualified variants of
+/// that type. For example, if @p Ty is "int const *", this routine
+/// will add "int const *", "int const volatile *", "int const
+/// restrict *", and "int const volatile restrict *" to the set of
+/// pointer types. Returns true if the add of @p Ty itself succeeded,
+/// false otherwise.
+///
+/// FIXME: what to do about extended qualifiers?
+bool
+BuiltinCandidateTypeSet::AddPointerWithMoreQualifiedTypeVariants(QualType Ty,
+                                             const Qualifiers &VisibleQuals) {
+
+  // Insert this type.
+  if (!PointerTypes.insert(Ty))
+    return false;
+
+  QualType PointeeTy;
+  const PointerType *PointerTy = Ty->getAs<PointerType>();
+  bool buildObjCPtr = false;
+  if (!PointerTy) {
+    if (const ObjCObjectPointerType *PTy = Ty->getAs<ObjCObjectPointerType>()) {
+      PointeeTy = PTy->getPointeeType();
+      buildObjCPtr = true;
+    }
+    else
+      llvm_unreachable("type was not a pointer type!");
+  }
+  else
+    PointeeTy = PointerTy->getPointeeType();
+
+  // Don't add qualified variants of arrays. For one, they're not allowed
+  // (the qualifier would sink to the element type), and for another, the
+  // only overload situation where it matters is subscript or pointer +- int,
+  // and those shouldn't have qualifier variants anyway.
+  if (PointeeTy->isArrayType())
+    return true;
+  unsigned BaseCVR = PointeeTy.getCVRQualifiers();
+  if (const ConstantArrayType *Array =Context.getAsConstantArrayType(PointeeTy))
+    BaseCVR = Array->getElementType().getCVRQualifiers();
+  bool hasVolatile = VisibleQuals.hasVolatile();
+  bool hasRestrict = VisibleQuals.hasRestrict();
+
+  // Iterate through all strict supersets of BaseCVR.
+  for (unsigned CVR = BaseCVR+1; CVR <= Qualifiers::CVRMask; ++CVR) {
+    if ((CVR | BaseCVR) != CVR) continue;
+    // Skip over Volatile/Restrict if no Volatile/Restrict found anywhere
+    // in the types.
+    if ((CVR & Qualifiers::Volatile) && !hasVolatile) continue;
+    if ((CVR & Qualifiers::Restrict) && !hasRestrict) continue;
+    QualType QPointeeTy = Context.getCVRQualifiedType(PointeeTy, CVR);
+    if (!buildObjCPtr)
+      PointerTypes.insert(Context.getPointerType(QPointeeTy));
+    else
+      PointerTypes.insert(Context.getObjCObjectPointerType(QPointeeTy));
+  }
+
+  return true;
+}
+
+/// AddMemberPointerWithMoreQualifiedTypeVariants - Add the pointer type @p Ty
+/// to the set of pointer types along with any more-qualified variants of
+/// that type. For example, if @p Ty is "int const *", this routine
+/// will add "int const *", "int const volatile *", "int const
+/// restrict *", and "int const volatile restrict *" to the set of
+/// pointer types. Returns true if the add of @p Ty itself succeeded,
+/// false otherwise.
+///
+/// FIXME: what to do about extended qualifiers?
+bool
+BuiltinCandidateTypeSet::AddMemberPointerWithMoreQualifiedTypeVariants(
+    QualType Ty) {
+  // Insert this type.
+  if (!MemberPointerTypes.insert(Ty))
+    return false;
+
+  const MemberPointerType *PointerTy = Ty->getAs<MemberPointerType>();
+  assert(PointerTy && "type was not a member pointer type!");
+
+  QualType PointeeTy = PointerTy->getPointeeType();
+  // Don't add qualified variants of arrays. For one, they're not allowed
+  // (the qualifier would sink to the element type), and for another, the
+  // only overload situation where it matters is subscript or pointer +- int,
+  // and those shouldn't have qualifier variants anyway.
+  if (PointeeTy->isArrayType())
+    return true;
+  const Type *ClassTy = PointerTy->getClass();
+
+  // Iterate through all strict supersets of the pointee type's CVR
+  // qualifiers.
+  unsigned BaseCVR = PointeeTy.getCVRQualifiers();
+  for (unsigned CVR = BaseCVR+1; CVR <= Qualifiers::CVRMask; ++CVR) {
+    if ((CVR | BaseCVR) != CVR) continue;
+
+    QualType QPointeeTy = Context.getCVRQualifiedType(PointeeTy, CVR);
+    MemberPointerTypes.insert(
+      Context.getMemberPointerType(QPointeeTy, ClassTy));
+  }
+
+  return true;
+}
+
+/// AddTypesConvertedFrom - Add each of the types to which the type @p
+/// Ty can be implicit converted to the given set of @p Types. We're
+/// primarily interested in pointer types and enumeration types. We also
+/// take member pointer types, for the conditional operator.
+/// AllowUserConversions is true if we should look at the conversion
+/// functions of a class type, and AllowExplicitConversions if we
+/// should also include the explicit conversion functions of a class
+/// type.
+void
+BuiltinCandidateTypeSet::AddTypesConvertedFrom(QualType Ty,
+                                               SourceLocation Loc,
+                                               bool AllowUserConversions,
+                                               bool AllowExplicitConversions,
+                                               const Qualifiers &VisibleQuals) {
+  // Only deal with canonical types.
+  Ty = Context.getCanonicalType(Ty);
+
+  // Look through reference types; they aren't part of the type of an
+  // expression for the purposes of conversions.
+  if (const ReferenceType *RefTy = Ty->getAs<ReferenceType>())
+    Ty = RefTy->getPointeeType();
+
+  // If we're dealing with an array type, decay to the pointer.
+  if (Ty->isArrayType())
+    Ty = SemaRef.Context.getArrayDecayedType(Ty);
+
+  // Otherwise, we don't care about qualifiers on the type.
+  Ty = Ty.getLocalUnqualifiedType();
+
+  // Flag if we ever add a non-record type.
+  const RecordType *TyRec = Ty->getAs<RecordType>();
+  HasNonRecordTypes = HasNonRecordTypes || !TyRec;
+
+  // Flag if we encounter an arithmetic type.
+  HasArithmeticOrEnumeralTypes =
+    HasArithmeticOrEnumeralTypes || Ty->isArithmeticType();
+
+  if (Ty->isObjCIdType() || Ty->isObjCClassType())
+    PointerTypes.insert(Ty);
+  else if (Ty->getAs<PointerType>() || Ty->getAs<ObjCObjectPointerType>()) {
+    // Insert our type, and its more-qualified variants, into the set
+    // of types.
+    if (!AddPointerWithMoreQualifiedTypeVariants(Ty, VisibleQuals))
+      return;
+  } else if (Ty->isMemberPointerType()) {
+    // Member pointers are far easier, since the pointee can't be converted.
+    if (!AddMemberPointerWithMoreQualifiedTypeVariants(Ty))
+      return;
+  } else if (Ty->isEnumeralType()) {
+    HasArithmeticOrEnumeralTypes = true;
+    EnumerationTypes.insert(Ty);
+  } else if (Ty->isVectorType()) {
+    // We treat vector types as arithmetic types in many contexts as an
+    // extension.
+    HasArithmeticOrEnumeralTypes = true;
+    VectorTypes.insert(Ty);
+  } else if (Ty->isNullPtrType()) {
+    HasNullPtrType = true;
+  } else if (AllowUserConversions && TyRec) {
+    // No conversion functions in incomplete types.
+    if (SemaRef.RequireCompleteType(Loc, Ty, 0))
+      return;
+
+    CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(TyRec->getDecl());
+    const UnresolvedSetImpl *Conversions
+      = ClassDecl->getVisibleConversionFunctions();
+    for (UnresolvedSetImpl::iterator I = Conversions->begin(),
+           E = Conversions->end(); I != E; ++I) {
+      NamedDecl *D = I.getDecl();
+      if (isa<UsingShadowDecl>(D))
+        D = cast<UsingShadowDecl>(D)->getTargetDecl();
+
+      // Skip conversion function templates; they don't tell us anything
+      // about which builtin types we can convert to.
+      if (isa<FunctionTemplateDecl>(D))
+        continue;
+
+      CXXConversionDecl *Conv = cast<CXXConversionDecl>(D);
+      if (AllowExplicitConversions || !Conv->isExplicit()) {
+        AddTypesConvertedFrom(Conv->getConversionType(), Loc, false, false,
+                              VisibleQuals);
+      }
+    }
+  }
+}
+
+/// \brief Helper function for AddBuiltinOperatorCandidates() that adds
+/// the volatile- and non-volatile-qualified assignment operators for the
+/// given type to the candidate set.
+static void AddBuiltinAssignmentOperatorCandidates(Sema &S,
+                                                   QualType T,
+                                                   Expr **Args,
+                                                   unsigned NumArgs,
+                                    OverloadCandidateSet &CandidateSet) {
+  QualType ParamTypes[2];
+
+  // T& operator=(T&, T)
+  ParamTypes[0] = S.Context.getLValueReferenceType(T);
+  ParamTypes[1] = T;
+  S.AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 2, CandidateSet,
+                        /*IsAssignmentOperator=*/true);
+
+  if (!S.Context.getCanonicalType(T).isVolatileQualified()) {
+    // volatile T& operator=(volatile T&, T)
+    ParamTypes[0]
+      = S.Context.getLValueReferenceType(S.Context.getVolatileType(T));
+    ParamTypes[1] = T;
+    S.AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 2, CandidateSet,
+                          /*IsAssignmentOperator=*/true);
+  }
+}
+
+/// CollectVRQualifiers - This routine returns Volatile/Restrict qualifiers,
+/// if any, found in visible type conversion functions found in ArgExpr's type.
+static  Qualifiers CollectVRQualifiers(ASTContext &Context, Expr* ArgExpr) {
+    Qualifiers VRQuals;
+    const RecordType *TyRec;
+    if (const MemberPointerType *RHSMPType =
+        ArgExpr->getType()->getAs<MemberPointerType>())
+      TyRec = RHSMPType->getClass()->getAs<RecordType>();
+    else
+      TyRec = ArgExpr->getType()->getAs<RecordType>();
+    if (!TyRec) {
+      // Just to be safe, assume the worst case.
+      VRQuals.addVolatile();
+      VRQuals.addRestrict();
+      return VRQuals;
+    }
+
+    CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(TyRec->getDecl());
+    if (!ClassDecl->hasDefinition())
+      return VRQuals;
+
+    const UnresolvedSetImpl *Conversions =
+      ClassDecl->getVisibleConversionFunctions();
+
+    for (UnresolvedSetImpl::iterator I = Conversions->begin(),
+           E = Conversions->end(); I != E; ++I) {
+      NamedDecl *D = I.getDecl();
+      if (isa<UsingShadowDecl>(D))
+        D = cast<UsingShadowDecl>(D)->getTargetDecl();
+      if (CXXConversionDecl *Conv = dyn_cast<CXXConversionDecl>(D)) {
+        QualType CanTy = Context.getCanonicalType(Conv->getConversionType());
+        if (const ReferenceType *ResTypeRef = CanTy->getAs<ReferenceType>())
+          CanTy = ResTypeRef->getPointeeType();
+        // Need to go down the pointer/mempointer chain and add qualifiers
+        // as see them.
+        bool done = false;
+        while (!done) {
+          if (const PointerType *ResTypePtr = CanTy->getAs<PointerType>())
+            CanTy = ResTypePtr->getPointeeType();
+          else if (const MemberPointerType *ResTypeMPtr =
+                CanTy->getAs<MemberPointerType>())
+            CanTy = ResTypeMPtr->getPointeeType();
+          else
+            done = true;
+          if (CanTy.isVolatileQualified())
+            VRQuals.addVolatile();
+          if (CanTy.isRestrictQualified())
+            VRQuals.addRestrict();
+          if (VRQuals.hasRestrict() && VRQuals.hasVolatile())
+            return VRQuals;
+        }
+      }
+    }
+    return VRQuals;
+}
+
+namespace {
+
+/// \brief Helper class to manage the addition of builtin operator overload
+/// candidates. It provides shared state and utility methods used throughout
+/// the process, as well as a helper method to add each group of builtin
+/// operator overloads from the standard to a candidate set.
+class BuiltinOperatorOverloadBuilder {
+  // Common instance state available to all overload candidate addition methods.
+  Sema &S;
+  Expr **Args;
+  unsigned NumArgs;
+  Qualifiers VisibleTypeConversionsQuals;
+  bool HasArithmeticOrEnumeralCandidateType;
+  SmallVectorImpl<BuiltinCandidateTypeSet> &CandidateTypes;
+  OverloadCandidateSet &CandidateSet;
+
+  // Define some constants used to index and iterate over the arithemetic types
+  // provided via the getArithmeticType() method below.
+  // The "promoted arithmetic types" are the arithmetic
+  // types are that preserved by promotion (C++ [over.built]p2).
+  static const unsigned FirstIntegralType = 3;
+  static const unsigned LastIntegralType = 18;
+  static const unsigned FirstPromotedIntegralType = 3,
+                        LastPromotedIntegralType = 9;
+  static const unsigned FirstPromotedArithmeticType = 0,
+                        LastPromotedArithmeticType = 9;
+  static const unsigned NumArithmeticTypes = 18;
+
+  /// \brief Get the canonical type for a given arithmetic type index.
+  CanQualType getArithmeticType(unsigned index) {
+    assert(index < NumArithmeticTypes);
+    static CanQualType ASTContext::* const
+      ArithmeticTypes[NumArithmeticTypes] = {
+      // Start of promoted types.
+      &ASTContext::FloatTy,
+      &ASTContext::DoubleTy,
+      &ASTContext::LongDoubleTy,
+
+      // Start of integral types.
+      &ASTContext::IntTy,
+      &ASTContext::LongTy,
+      &ASTContext::LongLongTy,
+      &ASTContext::UnsignedIntTy,
+      &ASTContext::UnsignedLongTy,
+      &ASTContext::UnsignedLongLongTy,
+      // End of promoted types.
+
+      &ASTContext::BoolTy,
+      &ASTContext::CharTy,
+      &ASTContext::WCharTy,
+      &ASTContext::Char16Ty,
+      &ASTContext::Char32Ty,
+      &ASTContext::SignedCharTy,
+      &ASTContext::ShortTy,
+      &ASTContext::UnsignedCharTy,
+      &ASTContext::UnsignedShortTy,
+      // End of integral types.
+      // FIXME: What about complex?
+    };
+    return S.Context.*ArithmeticTypes[index];
+  }
+
+  /// \brief Gets the canonical type resulting from the usual arithemetic
+  /// converions for the given arithmetic types.
+  CanQualType getUsualArithmeticConversions(unsigned L, unsigned R) {
+    // Accelerator table for performing the usual arithmetic conversions.
+    // The rules are basically:
+    //   - if either is floating-point, use the wider floating-point
+    //   - if same signedness, use the higher rank
+    //   - if same size, use unsigned of the higher rank
+    //   - use the larger type
+    // These rules, together with the axiom that higher ranks are
+    // never smaller, are sufficient to precompute all of these results
+    // *except* when dealing with signed types of higher rank.
+    // (we could precompute SLL x UI for all known platforms, but it's
+    // better not to make any assumptions).
+    enum PromotedType {
+                  Flt,  Dbl, LDbl,   SI,   SL,  SLL,   UI,   UL,  ULL, Dep=-1
+    };
+    static PromotedType ConversionsTable[LastPromotedArithmeticType]
+                                        [LastPromotedArithmeticType] = {
+      /* Flt*/ {  Flt,  Dbl, LDbl,  Flt,  Flt,  Flt,  Flt,  Flt,  Flt },
+      /* Dbl*/ {  Dbl,  Dbl, LDbl,  Dbl,  Dbl,  Dbl,  Dbl,  Dbl,  Dbl },
+      /*LDbl*/ { LDbl, LDbl, LDbl, LDbl, LDbl, LDbl, LDbl, LDbl, LDbl },
+      /*  SI*/ {  Flt,  Dbl, LDbl,   SI,   SL,  SLL,   UI,   UL,  ULL },
+      /*  SL*/ {  Flt,  Dbl, LDbl,   SL,   SL,  SLL,  Dep,   UL,  ULL },
+      /* SLL*/ {  Flt,  Dbl, LDbl,  SLL,  SLL,  SLL,  Dep,  Dep,  ULL },
+      /*  UI*/ {  Flt,  Dbl, LDbl,   UI,  Dep,  Dep,   UI,   UL,  ULL },
+      /*  UL*/ {  Flt,  Dbl, LDbl,   UL,   UL,  Dep,   UL,   UL,  ULL },
+      /* ULL*/ {  Flt,  Dbl, LDbl,  ULL,  ULL,  ULL,  ULL,  ULL,  ULL },
+    };
+
+    assert(L < LastPromotedArithmeticType);
+    assert(R < LastPromotedArithmeticType);
+    int Idx = ConversionsTable[L][R];
+
+    // Fast path: the table gives us a concrete answer.
+    if (Idx != Dep) return getArithmeticType(Idx);
+
+    // Slow path: we need to compare widths.
+    // An invariant is that the signed type has higher rank.
+    CanQualType LT = getArithmeticType(L),
+                RT = getArithmeticType(R);
+    unsigned LW = S.Context.getIntWidth(LT),
+             RW = S.Context.getIntWidth(RT);
+
+    // If they're different widths, use the signed type.
+    if (LW > RW) return LT;
+    else if (LW < RW) return RT;
+
+    // Otherwise, use the unsigned type of the signed type's rank.
+    if (L == SL || R == SL) return S.Context.UnsignedLongTy;
+    assert(L == SLL || R == SLL);
+    return S.Context.UnsignedLongLongTy;
+  }
+
+  /// \brief Helper method to factor out the common pattern of adding overloads
+  /// for '++' and '--' builtin operators.
+  void addPlusPlusMinusMinusStyleOverloads(QualType CandidateTy,
+                                           bool HasVolatile) {
+    QualType ParamTypes[2] = {
+      S.Context.getLValueReferenceType(CandidateTy),
+      S.Context.IntTy
+    };
+
+    // Non-volatile version.
+    if (NumArgs == 1)
+      S.AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 1, CandidateSet);
+    else
+      S.AddBuiltinCandidate(CandidateTy, ParamTypes, Args, 2, CandidateSet);
+
+    // Use a heuristic to reduce number of builtin candidates in the set:
+    // add volatile version only if there are conversions to a volatile type.
+    if (HasVolatile) {
+      ParamTypes[0] =
+        S.Context.getLValueReferenceType(
+          S.Context.getVolatileType(CandidateTy));
+      if (NumArgs == 1)
+        S.AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 1, CandidateSet);
+      else
+        S.AddBuiltinCandidate(CandidateTy, ParamTypes, Args, 2, CandidateSet);
+    }
+  }
+
+public:
+  BuiltinOperatorOverloadBuilder(
+    Sema &S, Expr **Args, unsigned NumArgs,
+    Qualifiers VisibleTypeConversionsQuals,
+    bool HasArithmeticOrEnumeralCandidateType,
+    SmallVectorImpl<BuiltinCandidateTypeSet> &CandidateTypes,
+    OverloadCandidateSet &CandidateSet)
+    : S(S), Args(Args), NumArgs(NumArgs),
+      VisibleTypeConversionsQuals(VisibleTypeConversionsQuals),
+      HasArithmeticOrEnumeralCandidateType(
+        HasArithmeticOrEnumeralCandidateType),
+      CandidateTypes(CandidateTypes),
+      CandidateSet(CandidateSet) {
+    // Validate some of our static helper constants in debug builds.
+    assert(getArithmeticType(FirstPromotedIntegralType) == S.Context.IntTy &&
+           "Invalid first promoted integral type");
+    assert(getArithmeticType(LastPromotedIntegralType - 1)
+             == S.Context.UnsignedLongLongTy &&
+           "Invalid last promoted integral type");
+    assert(getArithmeticType(FirstPromotedArithmeticType)
+             == S.Context.FloatTy &&
+           "Invalid first promoted arithmetic type");
+    assert(getArithmeticType(LastPromotedArithmeticType - 1)
+             == S.Context.UnsignedLongLongTy &&
+           "Invalid last promoted arithmetic type");
+  }
+
+  // C++ [over.built]p3:
+  //
+  //   For every pair (T, VQ), where T is an arithmetic type, and VQ
+  //   is either volatile or empty, there exist candidate operator
+  //   functions of the form
+  //
+  //       VQ T&      operator++(VQ T&);
+  //       T          operator++(VQ T&, int);
+  //
+  // C++ [over.built]p4:
+  //
+  //   For every pair (T, VQ), where T is an arithmetic type other
+  //   than bool, and VQ is either volatile or empty, there exist
+  //   candidate operator functions of the form
+  //
+  //       VQ T&      operator--(VQ T&);
+  //       T          operator--(VQ T&, int);
+  void addPlusPlusMinusMinusArithmeticOverloads(OverloadedOperatorKind Op) {
+    if (!HasArithmeticOrEnumeralCandidateType)
+      return;
+
+    for (unsigned Arith = (Op == OO_PlusPlus? 0 : 1);
+         Arith < NumArithmeticTypes; ++Arith) {
+      addPlusPlusMinusMinusStyleOverloads(
+        getArithmeticType(Arith),
+        VisibleTypeConversionsQuals.hasVolatile());
+    }
+  }
+
+  // C++ [over.built]p5:
+  //
+  //   For every pair (T, VQ), where T is a cv-qualified or
+  //   cv-unqualified object type, and VQ is either volatile or
+  //   empty, there exist candidate operator functions of the form
+  //
+  //       T*VQ&      operator++(T*VQ&);
+  //       T*VQ&      operator--(T*VQ&);
+  //       T*         operator++(T*VQ&, int);
+  //       T*         operator--(T*VQ&, int);
+  void addPlusPlusMinusMinusPointerOverloads() {
+    for (BuiltinCandidateTypeSet::iterator
+              Ptr = CandidateTypes[0].pointer_begin(),
+           PtrEnd = CandidateTypes[0].pointer_end();
+         Ptr != PtrEnd; ++Ptr) {
+      // Skip pointer types that aren't pointers to object types.
+      if (!(*Ptr)->getPointeeType()->isObjectType())
+        continue;
+
+      addPlusPlusMinusMinusStyleOverloads(*Ptr,
+        (!S.Context.getCanonicalType(*Ptr).isVolatileQualified() &&
+         VisibleTypeConversionsQuals.hasVolatile()));
+    }
+  }
+
+  // C++ [over.built]p6:
+  //   For every cv-qualified or cv-unqualified object type T, there
+  //   exist candidate operator functions of the form
+  //
+  //       T&         operator*(T*);
+  //
+  // C++ [over.built]p7:
+  //   For every function type T that does not have cv-qualifiers or a
+  //   ref-qualifier, there exist candidate operator functions of the form
+  //       T&         operator*(T*);
+  void addUnaryStarPointerOverloads() {
+    for (BuiltinCandidateTypeSet::iterator
+              Ptr = CandidateTypes[0].pointer_begin(),
+           PtrEnd = CandidateTypes[0].pointer_end();
+         Ptr != PtrEnd; ++Ptr) {
+      QualType ParamTy = *Ptr;
+      QualType PointeeTy = ParamTy->getPointeeType();
+      if (!PointeeTy->isObjectType() && !PointeeTy->isFunctionType())
+        continue;
+
+      if (const FunctionProtoType *Proto =PointeeTy->getAs<FunctionProtoType>())
+        if (Proto->getTypeQuals() || Proto->getRefQualifier())
+          continue;
+
+      S.AddBuiltinCandidate(S.Context.getLValueReferenceType(PointeeTy),
+                            &ParamTy, Args, 1, CandidateSet);
+    }
+  }
+
+  // C++ [over.built]p9:
+  //  For every promoted arithmetic type T, there exist candidate
+  //  operator functions of the form
+  //
+  //       T         operator+(T);
+  //       T         operator-(T);
+  void addUnaryPlusOrMinusArithmeticOverloads() {
+    if (!HasArithmeticOrEnumeralCandidateType)
+      return;
+
+    for (unsigned Arith = FirstPromotedArithmeticType;
+         Arith < LastPromotedArithmeticType; ++Arith) {
+      QualType ArithTy = getArithmeticType(Arith);
+      S.AddBuiltinCandidate(ArithTy, &ArithTy, Args, 1, CandidateSet);
+    }
+
+    // Extension: We also add these operators for vector types.
+    for (BuiltinCandidateTypeSet::iterator
+              Vec = CandidateTypes[0].vector_begin(),
+           VecEnd = CandidateTypes[0].vector_end();
+         Vec != VecEnd; ++Vec) {
+      QualType VecTy = *Vec;
+      S.AddBuiltinCandidate(VecTy, &VecTy, Args, 1, CandidateSet);
+    }
+  }
+
+  // C++ [over.built]p8:
+  //   For every type T, there exist candidate operator functions of
+  //   the form
+  //
+  //       T*         operator+(T*);
+  void addUnaryPlusPointerOverloads() {
+    for (BuiltinCandidateTypeSet::iterator
+              Ptr = CandidateTypes[0].pointer_begin(),
+           PtrEnd = CandidateTypes[0].pointer_end();
+         Ptr != PtrEnd; ++Ptr) {
+      QualType ParamTy = *Ptr;
+      S.AddBuiltinCandidate(ParamTy, &ParamTy, Args, 1, CandidateSet);
+    }
+  }
+
+  // C++ [over.built]p10:
+  //   For every promoted integral type T, there exist candidate
+  //   operator functions of the form
+  //
+  //        T         operator~(T);
+  void addUnaryTildePromotedIntegralOverloads() {
+    if (!HasArithmeticOrEnumeralCandidateType)
+      return;
+
+    for (unsigned Int = FirstPromotedIntegralType;
+         Int < LastPromotedIntegralType; ++Int) {
+      QualType IntTy = getArithmeticType(Int);
+      S.AddBuiltinCandidate(IntTy, &IntTy, Args, 1, CandidateSet);
+    }
+
+    // Extension: We also add this operator for vector types.
+    for (BuiltinCandidateTypeSet::iterator
+              Vec = CandidateTypes[0].vector_begin(),
+           VecEnd = CandidateTypes[0].vector_end();
+         Vec != VecEnd; ++Vec) {
+      QualType VecTy = *Vec;
+      S.AddBuiltinCandidate(VecTy, &VecTy, Args, 1, CandidateSet);
+    }
+  }
+
+  // C++ [over.match.oper]p16:
+  //   For every pointer to member type T, there exist candidate operator
+  //   functions of the form
+  //
+  //        bool operator==(T,T);
+  //        bool operator!=(T,T);
+  void addEqualEqualOrNotEqualMemberPointerOverloads() {
+    /// Set of (canonical) types that we've already handled.
+    llvm::SmallPtrSet<QualType, 8> AddedTypes;
+
+    for (unsigned ArgIdx = 0; ArgIdx < NumArgs; ++ArgIdx) {
+      for (BuiltinCandidateTypeSet::iterator
+                MemPtr = CandidateTypes[ArgIdx].member_pointer_begin(),
+             MemPtrEnd = CandidateTypes[ArgIdx].member_pointer_end();
+           MemPtr != MemPtrEnd;
+           ++MemPtr) {
+        // Don't add the same builtin candidate twice.
+        if (!AddedTypes.insert(S.Context.getCanonicalType(*MemPtr)))
+          continue;
+
+        QualType ParamTypes[2] = { *MemPtr, *MemPtr };
+        S.AddBuiltinCandidate(S.Context.BoolTy, ParamTypes, Args, 2,
+                              CandidateSet);
+      }
+    }
+  }
+
+  // C++ [over.built]p15:
+  //
+  //   For every T, where T is an enumeration type, a pointer type, or 
+  //   std::nullptr_t, there exist candidate operator functions of the form
+  //
+  //        bool       operator<(T, T);
+  //        bool       operator>(T, T);
+  //        bool       operator<=(T, T);
+  //        bool       operator>=(T, T);
+  //        bool       operator==(T, T);
+  //        bool       operator!=(T, T);
+  void addRelationalPointerOrEnumeralOverloads() {
+    // C++ [over.built]p1:
+    //   If there is a user-written candidate with the same name and parameter
+    //   types as a built-in candidate operator function, the built-in operator
+    //   function is hidden and is not included in the set of candidate
+    //   functions.
+    //
+    // The text is actually in a note, but if we don't implement it then we end
+    // up with ambiguities when the user provides an overloaded operator for
+    // an enumeration type. Note that only enumeration types have this problem,
+    // so we track which enumeration types we've seen operators for. Also, the
+    // only other overloaded operator with enumeration argumenst, operator=,
+    // cannot be overloaded for enumeration types, so this is the only place
+    // where we must suppress candidates like this.
+    llvm::DenseSet<std::pair<CanQualType, CanQualType> >
+      UserDefinedBinaryOperators;
+
+    for (unsigned ArgIdx = 0; ArgIdx < NumArgs; ++ArgIdx) {
+      if (CandidateTypes[ArgIdx].enumeration_begin() !=
+          CandidateTypes[ArgIdx].enumeration_end()) {
+        for (OverloadCandidateSet::iterator C = CandidateSet.begin(),
+                                         CEnd = CandidateSet.end();
+             C != CEnd; ++C) {
+          if (!C->Viable || !C->Function || C->Function->getNumParams() != 2)
+            continue;
+
+          QualType FirstParamType =
+            C->Function->getParamDecl(0)->getType().getUnqualifiedType();
+          QualType SecondParamType =
+            C->Function->getParamDecl(1)->getType().getUnqualifiedType();
+
+          // Skip if either parameter isn't of enumeral type.
+          if (!FirstParamType->isEnumeralType() ||
+              !SecondParamType->isEnumeralType())
+            continue;
+
+          // Add this operator to the set of known user-defined operators.
+          UserDefinedBinaryOperators.insert(
+            std::make_pair(S.Context.getCanonicalType(FirstParamType),
+                           S.Context.getCanonicalType(SecondParamType)));
+        }
+      }
+    }
+
+    /// Set of (canonical) types that we've already handled.
+    llvm::SmallPtrSet<QualType, 8> AddedTypes;
+
+    for (unsigned ArgIdx = 0; ArgIdx < NumArgs; ++ArgIdx) {
+      for (BuiltinCandidateTypeSet::iterator
+                Ptr = CandidateTypes[ArgIdx].pointer_begin(),
+             PtrEnd = CandidateTypes[ArgIdx].pointer_end();
+           Ptr != PtrEnd; ++Ptr) {
+        // Don't add the same builtin candidate twice.
+        if (!AddedTypes.insert(S.Context.getCanonicalType(*Ptr)))
+          continue;
+
+        QualType ParamTypes[2] = { *Ptr, *Ptr };
+        S.AddBuiltinCandidate(S.Context.BoolTy, ParamTypes, Args, 2,
+                              CandidateSet);
+      }
+      for (BuiltinCandidateTypeSet::iterator
+                Enum = CandidateTypes[ArgIdx].enumeration_begin(),
+             EnumEnd = CandidateTypes[ArgIdx].enumeration_end();
+           Enum != EnumEnd; ++Enum) {
+        CanQualType CanonType = S.Context.getCanonicalType(*Enum);
+
+        // Don't add the same builtin candidate twice, or if a user defined
+        // candidate exists.
+        if (!AddedTypes.insert(CanonType) ||
+            UserDefinedBinaryOperators.count(std::make_pair(CanonType,
+                                                            CanonType)))
+          continue;
+
+        QualType ParamTypes[2] = { *Enum, *Enum };
+        S.AddBuiltinCandidate(S.Context.BoolTy, ParamTypes, Args, 2,
+                              CandidateSet);
+      }
+      
+      if (CandidateTypes[ArgIdx].hasNullPtrType()) {
+        CanQualType NullPtrTy = S.Context.getCanonicalType(S.Context.NullPtrTy);
+        if (AddedTypes.insert(NullPtrTy) &&
+            !UserDefinedBinaryOperators.count(std::make_pair(NullPtrTy, 
+                                                             NullPtrTy))) {
+          QualType ParamTypes[2] = { NullPtrTy, NullPtrTy };
+          S.AddBuiltinCandidate(S.Context.BoolTy, ParamTypes, Args, 2, 
+                                CandidateSet);
+        }
+      }
+    }
+  }
+
+  // C++ [over.built]p13:
+  //
+  //   For every cv-qualified or cv-unqualified object type T
+  //   there exist candidate operator functions of the form
+  //
+  //      T*         operator+(T*, ptrdiff_t);
+  //      T&         operator[](T*, ptrdiff_t);    [BELOW]
+  //      T*         operator-(T*, ptrdiff_t);
+  //      T*         operator+(ptrdiff_t, T*);
+  //      T&         operator[](ptrdiff_t, T*);    [BELOW]
+  //
+  // C++ [over.built]p14:
+  //
+  //   For every T, where T is a pointer to object type, there
+  //   exist candidate operator functions of the form
+  //
+  //      ptrdiff_t  operator-(T, T);
+  void addBinaryPlusOrMinusPointerOverloads(OverloadedOperatorKind Op) {
+    /// Set of (canonical) types that we've already handled.
+    llvm::SmallPtrSet<QualType, 8> AddedTypes;
+
+    for (int Arg = 0; Arg < 2; ++Arg) {
+      QualType AsymetricParamTypes[2] = {
+        S.Context.getPointerDiffType(),
+        S.Context.getPointerDiffType(),
+      };
+      for (BuiltinCandidateTypeSet::iterator
+                Ptr = CandidateTypes[Arg].pointer_begin(),
+             PtrEnd = CandidateTypes[Arg].pointer_end();
+           Ptr != PtrEnd; ++Ptr) {
+        QualType PointeeTy = (*Ptr)->getPointeeType();
+        if (!PointeeTy->isObjectType())
+          continue;
+
+        AsymetricParamTypes[Arg] = *Ptr;
+        if (Arg == 0 || Op == OO_Plus) {
+          // operator+(T*, ptrdiff_t) or operator-(T*, ptrdiff_t)
+          // T* operator+(ptrdiff_t, T*);
+          S.AddBuiltinCandidate(*Ptr, AsymetricParamTypes, Args, 2,
+                                CandidateSet);
+        }
+        if (Op == OO_Minus) {
+          // ptrdiff_t operator-(T, T);
+          if (!AddedTypes.insert(S.Context.getCanonicalType(*Ptr)))
+            continue;
+
+          QualType ParamTypes[2] = { *Ptr, *Ptr };
+          S.AddBuiltinCandidate(S.Context.getPointerDiffType(), ParamTypes,
+                                Args, 2, CandidateSet);
+        }
+      }
+    }
+  }
+
+  // C++ [over.built]p12:
+  //
+  //   For every pair of promoted arithmetic types L and R, there
+  //   exist candidate operator functions of the form
+  //
+  //        LR         operator*(L, R);
+  //        LR         operator/(L, R);
+  //        LR         operator+(L, R);
+  //        LR         operator-(L, R);
+  //        bool       operator<(L, R);
+  //        bool       operator>(L, R);
+  //        bool       operator<=(L, R);
+  //        bool       operator>=(L, R);
+  //        bool       operator==(L, R);
+  //        bool       operator!=(L, R);
+  //
+  //   where LR is the result of the usual arithmetic conversions
+  //   between types L and R.
+  //
+  // C++ [over.built]p24:
+  //
+  //   For every pair of promoted arithmetic types L and R, there exist
+  //   candidate operator functions of the form
+  //
+  //        LR       operator?(bool, L, R);
+  //
+  //   where LR is the result of the usual arithmetic conversions
+  //   between types L and R.
+  // Our candidates ignore the first parameter.
+  void addGenericBinaryArithmeticOverloads(bool isComparison) {
+    if (!HasArithmeticOrEnumeralCandidateType)
+      return;
+
+    for (unsigned Left = FirstPromotedArithmeticType;
+         Left < LastPromotedArithmeticType; ++Left) {
+      for (unsigned Right = FirstPromotedArithmeticType;
+           Right < LastPromotedArithmeticType; ++Right) {
+        QualType LandR[2] = { getArithmeticType(Left),
+                              getArithmeticType(Right) };
+        QualType Result =
+          isComparison ? S.Context.BoolTy
+                       : getUsualArithmeticConversions(Left, Right);
+        S.AddBuiltinCandidate(Result, LandR, Args, 2, CandidateSet);
+      }
+    }
+
+    // Extension: Add the binary operators ==, !=, <, <=, >=, >, *, /, and the
+    // conditional operator for vector types.
+    for (BuiltinCandidateTypeSet::iterator
+              Vec1 = CandidateTypes[0].vector_begin(),
+           Vec1End = CandidateTypes[0].vector_end();
+         Vec1 != Vec1End; ++Vec1) {
+      for (BuiltinCandidateTypeSet::iterator
+                Vec2 = CandidateTypes[1].vector_begin(),
+             Vec2End = CandidateTypes[1].vector_end();
+           Vec2 != Vec2End; ++Vec2) {
+        QualType LandR[2] = { *Vec1, *Vec2 };
+        QualType Result = S.Context.BoolTy;
+        if (!isComparison) {
+          if ((*Vec1)->isExtVectorType() || !(*Vec2)->isExtVectorType())
+            Result = *Vec1;
+          else
+            Result = *Vec2;
+        }
+
+        S.AddBuiltinCandidate(Result, LandR, Args, 2, CandidateSet);
+      }
+    }
+  }
+
+  // C++ [over.built]p17:
+  //
+  //   For every pair of promoted integral types L and R, there
+  //   exist candidate operator functions of the form
+  //
+  //      LR         operator%(L, R);
+  //      LR         operator&(L, R);
+  //      LR         operator^(L, R);
+  //      LR         operator|(L, R);
+  //      L          operator<<(L, R);
+  //      L          operator>>(L, R);
+  //
+  //   where LR is the result of the usual arithmetic conversions
+  //   between types L and R.
+  void addBinaryBitwiseArithmeticOverloads(OverloadedOperatorKind Op) {
+    if (!HasArithmeticOrEnumeralCandidateType)
+      return;
+
+    for (unsigned Left = FirstPromotedIntegralType;
+         Left < LastPromotedIntegralType; ++Left) {
+      for (unsigned Right = FirstPromotedIntegralType;
+           Right < LastPromotedIntegralType; ++Right) {
+        QualType LandR[2] = { getArithmeticType(Left),
+                              getArithmeticType(Right) };
+        QualType Result = (Op == OO_LessLess || Op == OO_GreaterGreater)
+            ? LandR[0]
+            : getUsualArithmeticConversions(Left, Right);
+        S.AddBuiltinCandidate(Result, LandR, Args, 2, CandidateSet);
+      }
+    }
+  }
+
+  // C++ [over.built]p20:
+  //
+  //   For every pair (T, VQ), where T is an enumeration or
+  //   pointer to member type and VQ is either volatile or
+  //   empty, there exist candidate operator functions of the form
+  //
+  //        VQ T&      operator=(VQ T&, T);
+  void addAssignmentMemberPointerOrEnumeralOverloads() {
+    /// Set of (canonical) types that we've already handled.
+    llvm::SmallPtrSet<QualType, 8> AddedTypes;
+
+    for (unsigned ArgIdx = 0; ArgIdx < 2; ++ArgIdx) {
+      for (BuiltinCandidateTypeSet::iterator
+                Enum = CandidateTypes[ArgIdx].enumeration_begin(),
+             EnumEnd = CandidateTypes[ArgIdx].enumeration_end();
+           Enum != EnumEnd; ++Enum) {
+        if (!AddedTypes.insert(S.Context.getCanonicalType(*Enum)))
+          continue;
+
+        AddBuiltinAssignmentOperatorCandidates(S, *Enum, Args, 2,
+                                               CandidateSet);
+      }
+
+      for (BuiltinCandidateTypeSet::iterator
+                MemPtr = CandidateTypes[ArgIdx].member_pointer_begin(),
+             MemPtrEnd = CandidateTypes[ArgIdx].member_pointer_end();
+           MemPtr != MemPtrEnd; ++MemPtr) {
+        if (!AddedTypes.insert(S.Context.getCanonicalType(*MemPtr)))
+          continue;
+
+        AddBuiltinAssignmentOperatorCandidates(S, *MemPtr, Args, 2,
+                                               CandidateSet);
+      }
+    }
+  }
+
+  // C++ [over.built]p19:
+  //
+  //   For every pair (T, VQ), where T is any type and VQ is either
+  //   volatile or empty, there exist candidate operator functions
+  //   of the form
+  //
+  //        T*VQ&      operator=(T*VQ&, T*);
+  //
+  // C++ [over.built]p21:
+  //
+  //   For every pair (T, VQ), where T is a cv-qualified or
+  //   cv-unqualified object type and VQ is either volatile or
+  //   empty, there exist candidate operator functions of the form
+  //
+  //        T*VQ&      operator+=(T*VQ&, ptrdiff_t);
+  //        T*VQ&      operator-=(T*VQ&, ptrdiff_t);
+  void addAssignmentPointerOverloads(bool isEqualOp) {
+    /// Set of (canonical) types that we've already handled.
+    llvm::SmallPtrSet<QualType, 8> AddedTypes;
+
+    for (BuiltinCandidateTypeSet::iterator
+              Ptr = CandidateTypes[0].pointer_begin(),
+           PtrEnd = CandidateTypes[0].pointer_end();
+         Ptr != PtrEnd; ++Ptr) {
+      // If this is operator=, keep track of the builtin candidates we added.
+      if (isEqualOp)
+        AddedTypes.insert(S.Context.getCanonicalType(*Ptr));
+      else if (!(*Ptr)->getPointeeType()->isObjectType())
+        continue;
+
+      // non-volatile version
+      QualType ParamTypes[2] = {
+        S.Context.getLValueReferenceType(*Ptr),
+        isEqualOp ? *Ptr : S.Context.getPointerDiffType(),
+      };
+      S.AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 2, CandidateSet,
+                            /*IsAssigmentOperator=*/ isEqualOp);
+
+      if (!S.Context.getCanonicalType(*Ptr).isVolatileQualified() &&
+          VisibleTypeConversionsQuals.hasVolatile()) {
+        // volatile version
+        ParamTypes[0] =
+          S.Context.getLValueReferenceType(S.Context.getVolatileType(*Ptr));
+        S.AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 2, CandidateSet,
+                              /*IsAssigmentOperator=*/isEqualOp);
+      }
+    }
+
+    if (isEqualOp) {
+      for (BuiltinCandidateTypeSet::iterator
+                Ptr = CandidateTypes[1].pointer_begin(),
+             PtrEnd = CandidateTypes[1].pointer_end();
+           Ptr != PtrEnd; ++Ptr) {
+        // Make sure we don't add the same candidate twice.
+        if (!AddedTypes.insert(S.Context.getCanonicalType(*Ptr)))
+          continue;
+
+        QualType ParamTypes[2] = {
+          S.Context.getLValueReferenceType(*Ptr),
+          *Ptr,
+        };
+
+        // non-volatile version
+        S.AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 2, CandidateSet,
+                              /*IsAssigmentOperator=*/true);
+
+        if (!S.Context.getCanonicalType(*Ptr).isVolatileQualified() &&
+            VisibleTypeConversionsQuals.hasVolatile()) {
+          // volatile version
+          ParamTypes[0] =
+            S.Context.getLValueReferenceType(S.Context.getVolatileType(*Ptr));
+          S.AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 2,
+                                CandidateSet, /*IsAssigmentOperator=*/true);
+        }
+      }
+    }
+  }
+
+  // C++ [over.built]p18:
+  //
+  //   For every triple (L, VQ, R), where L is an arithmetic type,
+  //   VQ is either volatile or empty, and R is a promoted
+  //   arithmetic type, there exist candidate operator functions of
+  //   the form
+  //
+  //        VQ L&      operator=(VQ L&, R);
+  //        VQ L&      operator*=(VQ L&, R);
+  //        VQ L&      operator/=(VQ L&, R);
+  //        VQ L&      operator+=(VQ L&, R);
+  //        VQ L&      operator-=(VQ L&, R);
+  void addAssignmentArithmeticOverloads(bool isEqualOp) {
+    if (!HasArithmeticOrEnumeralCandidateType)
+      return;
+
+    for (unsigned Left = 0; Left < NumArithmeticTypes; ++Left) {
+      for (unsigned Right = FirstPromotedArithmeticType;
+           Right < LastPromotedArithmeticType; ++Right) {
+        QualType ParamTypes[2];
+        ParamTypes[1] = getArithmeticType(Right);
+
+        // Add this built-in operator as a candidate (VQ is empty).
+        ParamTypes[0] =
+          S.Context.getLValueReferenceType(getArithmeticType(Left));
+        S.AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 2, CandidateSet,
+                              /*IsAssigmentOperator=*/isEqualOp);
+
+        // Add this built-in operator as a candidate (VQ is 'volatile').
+        if (VisibleTypeConversionsQuals.hasVolatile()) {
+          ParamTypes[0] =
+            S.Context.getVolatileType(getArithmeticType(Left));
+          ParamTypes[0] = S.Context.getLValueReferenceType(ParamTypes[0]);
+          S.AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 2,
+                                CandidateSet,
+                                /*IsAssigmentOperator=*/isEqualOp);
+        }
+      }
+    }
+
+    // Extension: Add the binary operators =, +=, -=, *=, /= for vector types.
+    for (BuiltinCandidateTypeSet::iterator
+              Vec1 = CandidateTypes[0].vector_begin(),
+           Vec1End = CandidateTypes[0].vector_end();
+         Vec1 != Vec1End; ++Vec1) {
+      for (BuiltinCandidateTypeSet::iterator
+                Vec2 = CandidateTypes[1].vector_begin(),
+             Vec2End = CandidateTypes[1].vector_end();
+           Vec2 != Vec2End; ++Vec2) {
+        QualType ParamTypes[2];
+        ParamTypes[1] = *Vec2;
+        // Add this built-in operator as a candidate (VQ is empty).
+        ParamTypes[0] = S.Context.getLValueReferenceType(*Vec1);
+        S.AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 2, CandidateSet,
+                              /*IsAssigmentOperator=*/isEqualOp);
+
+        // Add this built-in operator as a candidate (VQ is 'volatile').
+        if (VisibleTypeConversionsQuals.hasVolatile()) {
+          ParamTypes[0] = S.Context.getVolatileType(*Vec1);
+          ParamTypes[0] = S.Context.getLValueReferenceType(ParamTypes[0]);
+          S.AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 2,
+                                CandidateSet,
+                                /*IsAssigmentOperator=*/isEqualOp);
+        }
+      }
+    }
+  }
+
+  // C++ [over.built]p22:
+  //
+  //   For every triple (L, VQ, R), where L is an integral type, VQ
+  //   is either volatile or empty, and R is a promoted integral
+  //   type, there exist candidate operator functions of the form
+  //
+  //        VQ L&       operator%=(VQ L&, R);
+  //        VQ L&       operator<<=(VQ L&, R);
+  //        VQ L&       operator>>=(VQ L&, R);
+  //        VQ L&       operator&=(VQ L&, R);
+  //        VQ L&       operator^=(VQ L&, R);
+  //        VQ L&       operator|=(VQ L&, R);
+  void addAssignmentIntegralOverloads() {
+    if (!HasArithmeticOrEnumeralCandidateType)
+      return;
+
+    for (unsigned Left = FirstIntegralType; Left < LastIntegralType; ++Left) {
+      for (unsigned Right = FirstPromotedIntegralType;
+           Right < LastPromotedIntegralType; ++Right) {
+        QualType ParamTypes[2];
+        ParamTypes[1] = getArithmeticType(Right);
+
+        // Add this built-in operator as a candidate (VQ is empty).
+        ParamTypes[0] =
+          S.Context.getLValueReferenceType(getArithmeticType(Left));
+        S.AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 2, CandidateSet);
+        if (VisibleTypeConversionsQuals.hasVolatile()) {
+          // Add this built-in operator as a candidate (VQ is 'volatile').
+          ParamTypes[0] = getArithmeticType(Left);
+          ParamTypes[0] = S.Context.getVolatileType(ParamTypes[0]);
+          ParamTypes[0] = S.Context.getLValueReferenceType(ParamTypes[0]);
+          S.AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 2,
+                                CandidateSet);
+        }
+      }
+    }
+  }
+
+  // C++ [over.operator]p23:
+  //
+  //   There also exist candidate operator functions of the form
+  //
+  //        bool        operator!(bool);
+  //        bool        operator&&(bool, bool);
+  //        bool        operator||(bool, bool);
+  void addExclaimOverload() {
+    QualType ParamTy = S.Context.BoolTy;
+    S.AddBuiltinCandidate(ParamTy, &ParamTy, Args, 1, CandidateSet,
+                          /*IsAssignmentOperator=*/false,
+                          /*NumContextualBoolArguments=*/1);
+  }
+  void addAmpAmpOrPipePipeOverload() {
+    QualType ParamTypes[2] = { S.Context.BoolTy, S.Context.BoolTy };
+    S.AddBuiltinCandidate(S.Context.BoolTy, ParamTypes, Args, 2, CandidateSet,
+                          /*IsAssignmentOperator=*/false,
+                          /*NumContextualBoolArguments=*/2);
+  }
+
+  // C++ [over.built]p13:
+  //
+  //   For every cv-qualified or cv-unqualified object type T there
+  //   exist candidate operator functions of the form
+  //
+  //        T*         operator+(T*, ptrdiff_t);     [ABOVE]
+  //        T&         operator[](T*, ptrdiff_t);
+  //        T*         operator-(T*, ptrdiff_t);     [ABOVE]
+  //        T*         operator+(ptrdiff_t, T*);     [ABOVE]
+  //        T&         operator[](ptrdiff_t, T*);
+  void addSubscriptOverloads() {
+    for (BuiltinCandidateTypeSet::iterator
+              Ptr = CandidateTypes[0].pointer_begin(),
+           PtrEnd = CandidateTypes[0].pointer_end();
+         Ptr != PtrEnd; ++Ptr) {
+      QualType ParamTypes[2] = { *Ptr, S.Context.getPointerDiffType() };
+      QualType PointeeType = (*Ptr)->getPointeeType();
+      if (!PointeeType->isObjectType())
+        continue;
+
+      QualType ResultTy = S.Context.getLValueReferenceType(PointeeType);
+
+      // T& operator[](T*, ptrdiff_t)
+      S.AddBuiltinCandidate(ResultTy, ParamTypes, Args, 2, CandidateSet);
+    }
+
+    for (BuiltinCandidateTypeSet::iterator
+              Ptr = CandidateTypes[1].pointer_begin(),
+           PtrEnd = CandidateTypes[1].pointer_end();
+         Ptr != PtrEnd; ++Ptr) {
+      QualType ParamTypes[2] = { S.Context.getPointerDiffType(), *Ptr };
+      QualType PointeeType = (*Ptr)->getPointeeType();
+      if (!PointeeType->isObjectType())
+        continue;
+
+      QualType ResultTy = S.Context.getLValueReferenceType(PointeeType);
+
+      // T& operator[](ptrdiff_t, T*)
+      S.AddBuiltinCandidate(ResultTy, ParamTypes, Args, 2, CandidateSet);
+    }
+  }
+
+  // C++ [over.built]p11:
+  //    For every quintuple (C1, C2, T, CV1, CV2), where C2 is a class type,
+  //    C1 is the same type as C2 or is a derived class of C2, T is an object
+  //    type or a function type, and CV1 and CV2 are cv-qualifier-seqs,
+  //    there exist candidate operator functions of the form
+  //
+  //      CV12 T& operator->*(CV1 C1*, CV2 T C2::*);
+  //
+  //    where CV12 is the union of CV1 and CV2.
+  void addArrowStarOverloads() {
+    for (BuiltinCandidateTypeSet::iterator
+             Ptr = CandidateTypes[0].pointer_begin(),
+           PtrEnd = CandidateTypes[0].pointer_end();
+         Ptr != PtrEnd; ++Ptr) {
+      QualType C1Ty = (*Ptr);
+      QualType C1;
+      QualifierCollector Q1;
+      C1 = QualType(Q1.strip(C1Ty->getPointeeType()), 0);
+      if (!isa<RecordType>(C1))
+        continue;
+      // heuristic to reduce number of builtin candidates in the set.
+      // Add volatile/restrict version only if there are conversions to a
+      // volatile/restrict type.
+      if (!VisibleTypeConversionsQuals.hasVolatile() && Q1.hasVolatile())
+        continue;
+      if (!VisibleTypeConversionsQuals.hasRestrict() && Q1.hasRestrict())
+        continue;
+      for (BuiltinCandidateTypeSet::iterator
+                MemPtr = CandidateTypes[1].member_pointer_begin(),
+             MemPtrEnd = CandidateTypes[1].member_pointer_end();
+           MemPtr != MemPtrEnd; ++MemPtr) {
+        const MemberPointerType *mptr = cast<MemberPointerType>(*MemPtr);
+        QualType C2 = QualType(mptr->getClass(), 0);
+        C2 = C2.getUnqualifiedType();
+        if (C1 != C2 && !S.IsDerivedFrom(C1, C2))
+          break;
+        QualType ParamTypes[2] = { *Ptr, *MemPtr };
+        // build CV12 T&
+        QualType T = mptr->getPointeeType();
+        if (!VisibleTypeConversionsQuals.hasVolatile() &&
+            T.isVolatileQualified())
+          continue;
+        if (!VisibleTypeConversionsQuals.hasRestrict() &&
+            T.isRestrictQualified())
+          continue;
+        T = Q1.apply(S.Context, T);
+        QualType ResultTy = S.Context.getLValueReferenceType(T);
+        S.AddBuiltinCandidate(ResultTy, ParamTypes, Args, 2, CandidateSet);
+      }
+    }
+  }
+
+  // Note that we don't consider the first argument, since it has been
+  // contextually converted to bool long ago. The candidates below are
+  // therefore added as binary.
+  //
+  // C++ [over.built]p25:
+  //   For every type T, where T is a pointer, pointer-to-member, or scoped
+  //   enumeration type, there exist candidate operator functions of the form
+  //
+  //        T        operator?(bool, T, T);
+  //
+  void addConditionalOperatorOverloads() {
+    /// Set of (canonical) types that we've already handled.
+    llvm::SmallPtrSet<QualType, 8> AddedTypes;
+
+    for (unsigned ArgIdx = 0; ArgIdx < 2; ++ArgIdx) {
+      for (BuiltinCandidateTypeSet::iterator
+                Ptr = CandidateTypes[ArgIdx].pointer_begin(),
+             PtrEnd = CandidateTypes[ArgIdx].pointer_end();
+           Ptr != PtrEnd; ++Ptr) {
+        if (!AddedTypes.insert(S.Context.getCanonicalType(*Ptr)))
+          continue;
+
+        QualType ParamTypes[2] = { *Ptr, *Ptr };
+        S.AddBuiltinCandidate(*Ptr, ParamTypes, Args, 2, CandidateSet);
+      }
+
+      for (BuiltinCandidateTypeSet::iterator
+                MemPtr = CandidateTypes[ArgIdx].member_pointer_begin(),
+             MemPtrEnd = CandidateTypes[ArgIdx].member_pointer_end();
+           MemPtr != MemPtrEnd; ++MemPtr) {
+        if (!AddedTypes.insert(S.Context.getCanonicalType(*MemPtr)))
+          continue;
+
+        QualType ParamTypes[2] = { *MemPtr, *MemPtr };
+        S.AddBuiltinCandidate(*MemPtr, ParamTypes, Args, 2, CandidateSet);
+      }
+
+      if (S.getLangOpts().CPlusPlus0x) {
+        for (BuiltinCandidateTypeSet::iterator
+                  Enum = CandidateTypes[ArgIdx].enumeration_begin(),
+               EnumEnd = CandidateTypes[ArgIdx].enumeration_end();
+             Enum != EnumEnd; ++Enum) {
+          if (!(*Enum)->getAs<EnumType>()->getDecl()->isScoped())
+            continue;
+
+          if (!AddedTypes.insert(S.Context.getCanonicalType(*Enum)))
+            continue;
+
+          QualType ParamTypes[2] = { *Enum, *Enum };
+          S.AddBuiltinCandidate(*Enum, ParamTypes, Args, 2, CandidateSet);
+        }
+      }
+    }
+  }
+};
+
+} // end anonymous namespace
+
+/// AddBuiltinOperatorCandidates - Add the appropriate built-in
+/// operator overloads to the candidate set (C++ [over.built]), based
+/// on the operator @p Op and the arguments given. For example, if the
+/// operator is a binary '+', this routine might add "int
+/// operator+(int, int)" to cover integer addition.
+void
+Sema::AddBuiltinOperatorCandidates(OverloadedOperatorKind Op,
+                                   SourceLocation OpLoc,
+                                   Expr **Args, unsigned NumArgs,
+                                   OverloadCandidateSet& CandidateSet) {
+  // Find all of the types that the arguments can convert to, but only
+  // if the operator we're looking at has built-in operator candidates
+  // that make use of these types. Also record whether we encounter non-record
+  // candidate types or either arithmetic or enumeral candidate types.
+  Qualifiers VisibleTypeConversionsQuals;
+  VisibleTypeConversionsQuals.addConst();
+  for (unsigned ArgIdx = 0; ArgIdx < NumArgs; ++ArgIdx)
+    VisibleTypeConversionsQuals += CollectVRQualifiers(Context, Args[ArgIdx]);
+
+  bool HasNonRecordCandidateType = false;
+  bool HasArithmeticOrEnumeralCandidateType = false;
+  SmallVector<BuiltinCandidateTypeSet, 2> CandidateTypes;
+  for (unsigned ArgIdx = 0; ArgIdx < NumArgs; ++ArgIdx) {
+    CandidateTypes.push_back(BuiltinCandidateTypeSet(*this));
+    CandidateTypes[ArgIdx].AddTypesConvertedFrom(Args[ArgIdx]->getType(),
+                                                 OpLoc,
+                                                 true,
+                                                 (Op == OO_Exclaim ||
+                                                  Op == OO_AmpAmp ||
+                                                  Op == OO_PipePipe),
+                                                 VisibleTypeConversionsQuals);
+    HasNonRecordCandidateType = HasNonRecordCandidateType ||
+        CandidateTypes[ArgIdx].hasNonRecordTypes();
+    HasArithmeticOrEnumeralCandidateType =
+        HasArithmeticOrEnumeralCandidateType ||
+        CandidateTypes[ArgIdx].hasArithmeticOrEnumeralTypes();
+  }
+
+  // Exit early when no non-record types have been added to the candidate set
+  // for any of the arguments to the operator.
+  //
+  // We can't exit early for !, ||, or &&, since there we have always have
+  // 'bool' overloads.
+  if (!HasNonRecordCandidateType && 
+      !(Op == OO_Exclaim || Op == OO_AmpAmp || Op == OO_PipePipe))
+    return;
+
+  // Setup an object to manage the common state for building overloads.
+  BuiltinOperatorOverloadBuilder OpBuilder(*this, Args, NumArgs,
+                                           VisibleTypeConversionsQuals,
+                                           HasArithmeticOrEnumeralCandidateType,
+                                           CandidateTypes, CandidateSet);
+
+  // Dispatch over the operation to add in only those overloads which apply.
+  switch (Op) {
+  case OO_None:
+  case NUM_OVERLOADED_OPERATORS:
+    llvm_unreachable("Expected an overloaded operator");
+
+  case OO_New:
+  case OO_Delete:
+  case OO_Array_New:
+  case OO_Array_Delete:
+  case OO_Call:
+    llvm_unreachable(
+                    "Special operators don't use AddBuiltinOperatorCandidates");
+
+  case OO_Comma:
+  case OO_Arrow:
+    // C++ [over.match.oper]p3:
+    //   -- For the operator ',', the unary operator '&', or the
+    //      operator '->', the built-in candidates set is empty.
+    break;
+
+  case OO_Plus: // '+' is either unary or binary
+    if (NumArgs == 1)
+      OpBuilder.addUnaryPlusPointerOverloads();
+    // Fall through.
+
+  case OO_Minus: // '-' is either unary or binary
+    if (NumArgs == 1) {
+      OpBuilder.addUnaryPlusOrMinusArithmeticOverloads();
+    } else {
+      OpBuilder.addBinaryPlusOrMinusPointerOverloads(Op);
+      OpBuilder.addGenericBinaryArithmeticOverloads(/*isComparison=*/false);
+    }
+    break;
+
+  case OO_Star: // '*' is either unary or binary
+    if (NumArgs == 1)
+      OpBuilder.addUnaryStarPointerOverloads();
+    else
+      OpBuilder.addGenericBinaryArithmeticOverloads(/*isComparison=*/false);
+    break;
+
+  case OO_Slash:
+    OpBuilder.addGenericBinaryArithmeticOverloads(/*isComparison=*/false);
+    break;
+
+  case OO_PlusPlus:
+  case OO_MinusMinus:
+    OpBuilder.addPlusPlusMinusMinusArithmeticOverloads(Op);
+    OpBuilder.addPlusPlusMinusMinusPointerOverloads();
+    break;
+
+  case OO_EqualEqual:
+  case OO_ExclaimEqual:
+    OpBuilder.addEqualEqualOrNotEqualMemberPointerOverloads();
+    // Fall through.
+
+  case OO_Less:
+  case OO_Greater:
+  case OO_LessEqual:
+  case OO_GreaterEqual:
+    OpBuilder.addRelationalPointerOrEnumeralOverloads();
+    OpBuilder.addGenericBinaryArithmeticOverloads(/*isComparison=*/true);
+    break;
+
+  case OO_Percent:
+  case OO_Caret:
+  case OO_Pipe:
+  case OO_LessLess:
+  case OO_GreaterGreater:
+    OpBuilder.addBinaryBitwiseArithmeticOverloads(Op);
+    break;
+
+  case OO_Amp: // '&' is either unary or binary
+    if (NumArgs == 1)
+      // C++ [over.match.oper]p3:
+      //   -- For the operator ',', the unary operator '&', or the
+      //      operator '->', the built-in candidates set is empty.
+      break;
+
+    OpBuilder.addBinaryBitwiseArithmeticOverloads(Op);
+    break;
+
+  case OO_Tilde:
+    OpBuilder.addUnaryTildePromotedIntegralOverloads();
+    break;
+
+  case OO_Equal:
+    OpBuilder.addAssignmentMemberPointerOrEnumeralOverloads();
+    // Fall through.
+
+  case OO_PlusEqual:
+  case OO_MinusEqual:
+    OpBuilder.addAssignmentPointerOverloads(Op == OO_Equal);
+    // Fall through.
+
+  case OO_StarEqual:
+  case OO_SlashEqual:
+    OpBuilder.addAssignmentArithmeticOverloads(Op == OO_Equal);
+    break;
+
+  case OO_PercentEqual:
+  case OO_LessLessEqual:
+  case OO_GreaterGreaterEqual:
+  case OO_AmpEqual:
+  case OO_CaretEqual:
+  case OO_PipeEqual:
+    OpBuilder.addAssignmentIntegralOverloads();
+    break;
+
+  case OO_Exclaim:
+    OpBuilder.addExclaimOverload();
+    break;
+
+  case OO_AmpAmp:
+  case OO_PipePipe:
+    OpBuilder.addAmpAmpOrPipePipeOverload();
+    break;
+
+  case OO_Subscript:
+    OpBuilder.addSubscriptOverloads();
+    break;
+
+  case OO_ArrowStar:
+    OpBuilder.addArrowStarOverloads();
+    break;
+
+  case OO_Conditional:
+    OpBuilder.addConditionalOperatorOverloads();
+    OpBuilder.addGenericBinaryArithmeticOverloads(/*isComparison=*/false);
+    break;
+  }
+}
+
+/// \brief Add function candidates found via argument-dependent lookup
+/// to the set of overloading candidates.
+///
+/// This routine performs argument-dependent name lookup based on the
+/// given function name (which may also be an operator name) and adds
+/// all of the overload candidates found by ADL to the overload
+/// candidate set (C++ [basic.lookup.argdep]).
+void
+Sema::AddArgumentDependentLookupCandidates(DeclarationName Name,
+                                           bool Operator, SourceLocation Loc,
+                                           llvm::ArrayRef<Expr *> Args,
+                                 TemplateArgumentListInfo *ExplicitTemplateArgs,
+                                           OverloadCandidateSet& CandidateSet,
+                                           bool PartialOverloading,
+                                           bool StdNamespaceIsAssociated) {
+  ADLResult Fns;
+
+  // FIXME: This approach for uniquing ADL results (and removing
+  // redundant candidates from the set) relies on pointer-equality,
+  // which means we need to key off the canonical decl.  However,
+  // always going back to the canonical decl might not get us the
+  // right set of default arguments.  What default arguments are
+  // we supposed to consider on ADL candidates, anyway?
+
+  // FIXME: Pass in the explicit template arguments?
+  ArgumentDependentLookup(Name, Operator, Loc, Args, Fns,
+                          StdNamespaceIsAssociated);
+
+  // Erase all of the candidates we already knew about.
+  for (OverloadCandidateSet::iterator Cand = CandidateSet.begin(),
+                                   CandEnd = CandidateSet.end();
+       Cand != CandEnd; ++Cand)
+    if (Cand->Function) {
+      Fns.erase(Cand->Function);
+      if (FunctionTemplateDecl *FunTmpl = Cand->Function->getPrimaryTemplate())
+        Fns.erase(FunTmpl);
+    }
+
+  // For each of the ADL candidates we found, add it to the overload
+  // set.
+  for (ADLResult::iterator I = Fns.begin(), E = Fns.end(); I != E; ++I) {
+    DeclAccessPair FoundDecl = DeclAccessPair::make(*I, AS_none);
+    if (FunctionDecl *FD = dyn_cast<FunctionDecl>(*I)) {
+      if (ExplicitTemplateArgs)
+        continue;
+
+      AddOverloadCandidate(FD, FoundDecl, Args, CandidateSet, false,
+                           PartialOverloading);
+    } else
+      AddTemplateOverloadCandidate(cast<FunctionTemplateDecl>(*I),
+                                   FoundDecl, ExplicitTemplateArgs,
+                                   Args, CandidateSet);
+  }
+}
+
+/// isBetterOverloadCandidate - Determines whether the first overload
+/// candidate is a better candidate than the second (C++ 13.3.3p1).
+bool
+isBetterOverloadCandidate(Sema &S,
+                          const OverloadCandidate &Cand1,
+                          const OverloadCandidate &Cand2,
+                          SourceLocation Loc,
+                          bool UserDefinedConversion) {
+  // Define viable functions to be better candidates than non-viable
+  // functions.
+  if (!Cand2.Viable)
+    return Cand1.Viable;
+  else if (!Cand1.Viable)
+    return false;
+
+  // C++ [over.match.best]p1:
+  //
+  //   -- if F is a static member function, ICS1(F) is defined such
+  //      that ICS1(F) is neither better nor worse than ICS1(G) for
+  //      any function G, and, symmetrically, ICS1(G) is neither
+  //      better nor worse than ICS1(F).
+  unsigned StartArg = 0;
+  if (Cand1.IgnoreObjectArgument || Cand2.IgnoreObjectArgument)
+    StartArg = 1;
+
+  // C++ [over.match.best]p1:
+  //   A viable function F1 is defined to be a better function than another
+  //   viable function F2 if for all arguments i, ICSi(F1) is not a worse
+  //   conversion sequence than ICSi(F2), and then...
+  unsigned NumArgs = Cand1.NumConversions;
+  assert(Cand2.NumConversions == NumArgs && "Overload candidate mismatch");
+  bool HasBetterConversion = false;
+  for (unsigned ArgIdx = StartArg; ArgIdx < NumArgs; ++ArgIdx) {
+    switch (CompareImplicitConversionSequences(S,
+                                               Cand1.Conversions[ArgIdx],
+                                               Cand2.Conversions[ArgIdx])) {
+    case ImplicitConversionSequence::Better:
+      // Cand1 has a better conversion sequence.
+      HasBetterConversion = true;
+      break;
+
+    case ImplicitConversionSequence::Worse:
+      // Cand1 can't be better than Cand2.
+      return false;
+
+    case ImplicitConversionSequence::Indistinguishable:
+      // Do nothing.
+      break;
+    }
+  }
+
+  //    -- for some argument j, ICSj(F1) is a better conversion sequence than
+  //       ICSj(F2), or, if not that,
+  if (HasBetterConversion)
+    return true;
+
+  //     - F1 is a non-template function and F2 is a function template
+  //       specialization, or, if not that,
+  if ((!Cand1.Function || !Cand1.Function->getPrimaryTemplate()) &&
+      Cand2.Function && Cand2.Function->getPrimaryTemplate())
+    return true;
+
+  //   -- F1 and F2 are function template specializations, and the function
+  //      template for F1 is more specialized than the template for F2
+  //      according to the partial ordering rules described in 14.5.5.2, or,
+  //      if not that,
+  if (Cand1.Function && Cand1.Function->getPrimaryTemplate() &&
+      Cand2.Function && Cand2.Function->getPrimaryTemplate()) {
+    if (FunctionTemplateDecl *BetterTemplate
+          = S.getMoreSpecializedTemplate(Cand1.Function->getPrimaryTemplate(),
+                                         Cand2.Function->getPrimaryTemplate(),
+                                         Loc,
+                       isa<CXXConversionDecl>(Cand1.Function)? TPOC_Conversion
+                                                             : TPOC_Call,
+                                         Cand1.ExplicitCallArguments))
+      return BetterTemplate == Cand1.Function->getPrimaryTemplate();
+  }
+
+  //   -- the context is an initialization by user-defined conversion
+  //      (see 8.5, 13.3.1.5) and the standard conversion sequence
+  //      from the return type of F1 to the destination type (i.e.,
+  //      the type of the entity being initialized) is a better
+  //      conversion sequence than the standard conversion sequence
+  //      from the return type of F2 to the destination type.
+  if (UserDefinedConversion && Cand1.Function && Cand2.Function &&
+      isa<CXXConversionDecl>(Cand1.Function) &&
+      isa<CXXConversionDecl>(Cand2.Function)) {
+    // First check whether we prefer one of the conversion functions over the
+    // other. This only distinguishes the results in non-standard, extension
+    // cases such as the conversion from a lambda closure type to a function
+    // pointer or block.
+    ImplicitConversionSequence::CompareKind FuncResult
+      = compareConversionFunctions(S, Cand1.Function, Cand2.Function);
+    if (FuncResult != ImplicitConversionSequence::Indistinguishable)
+      return FuncResult;
+          
+    switch (CompareStandardConversionSequences(S,
+                                               Cand1.FinalConversion,
+                                               Cand2.FinalConversion)) {
+    case ImplicitConversionSequence::Better:
+      // Cand1 has a better conversion sequence.
+      return true;
+
+    case ImplicitConversionSequence::Worse:
+      // Cand1 can't be better than Cand2.
+      return false;
+
+    case ImplicitConversionSequence::Indistinguishable:
+      // Do nothing
+      break;
+    }
+  }
+
+  return false;
+}
+
+/// \brief Computes the best viable function (C++ 13.3.3)
+/// within an overload candidate set.
+///
+/// \param CandidateSet the set of candidate functions.
+///
+/// \param Loc the location of the function name (or operator symbol) for
+/// which overload resolution occurs.
+///
+/// \param Best f overload resolution was successful or found a deleted
+/// function, Best points to the candidate function found.
+///
+/// \returns The result of overload resolution.
+OverloadingResult
+OverloadCandidateSet::BestViableFunction(Sema &S, SourceLocation Loc,
+                                         iterator &Best,
+                                         bool UserDefinedConversion) {
+  // Find the best viable function.
+  Best = end();
+  for (iterator Cand = begin(); Cand != end(); ++Cand) {
+    if (Cand->Viable)
+      if (Best == end() || isBetterOverloadCandidate(S, *Cand, *Best, Loc,
+                                                     UserDefinedConversion))
+        Best = Cand;
+  }
+
+  // If we didn't find any viable functions, abort.
+  if (Best == end())
+    return OR_No_Viable_Function;
+
+  // Make sure that this function is better than every other viable
+  // function. If not, we have an ambiguity.
+  for (iterator Cand = begin(); Cand != end(); ++Cand) {
+    if (Cand->Viable &&
+        Cand != Best &&
+        !isBetterOverloadCandidate(S, *Best, *Cand, Loc,
+                                   UserDefinedConversion)) {
+      Best = end();
+      return OR_Ambiguous;
+    }
+  }
+
+  // Best is the best viable function.
+  if (Best->Function &&
+      (Best->Function->isDeleted() ||
+       S.isFunctionConsideredUnavailable(Best->Function)))
+    return OR_Deleted;
+
+  return OR_Success;
+}
+
+namespace {
+
+enum OverloadCandidateKind {
+  oc_function,
+  oc_method,
+  oc_constructor,
+  oc_function_template,
+  oc_method_template,
+  oc_constructor_template,
+  oc_implicit_default_constructor,
+  oc_implicit_copy_constructor,
+  oc_implicit_move_constructor,
+  oc_implicit_copy_assignment,
+  oc_implicit_move_assignment,
+  oc_implicit_inherited_constructor
+};
+
+OverloadCandidateKind ClassifyOverloadCandidate(Sema &S,
+                                                FunctionDecl *Fn,
+                                                std::string &Description) {
+  bool isTemplate = false;
+
+  if (FunctionTemplateDecl *FunTmpl = Fn->getPrimaryTemplate()) {
+    isTemplate = true;
+    Description = S.getTemplateArgumentBindingsText(
+      FunTmpl->getTemplateParameters(), *Fn->getTemplateSpecializationArgs());
+  }
+
+  if (CXXConstructorDecl *Ctor = dyn_cast<CXXConstructorDecl>(Fn)) {
+    if (!Ctor->isImplicit())
+      return isTemplate ? oc_constructor_template : oc_constructor;
+
+    if (Ctor->getInheritedConstructor())
+      return oc_implicit_inherited_constructor;
+
+    if (Ctor->isDefaultConstructor())
+      return oc_implicit_default_constructor;
+
+    if (Ctor->isMoveConstructor())
+      return oc_implicit_move_constructor;
+
+    assert(Ctor->isCopyConstructor() &&
+           "unexpected sort of implicit constructor");
+    return oc_implicit_copy_constructor;
+  }
+
+  if (CXXMethodDecl *Meth = dyn_cast<CXXMethodDecl>(Fn)) {
+    // This actually gets spelled 'candidate function' for now, but
+    // it doesn't hurt to split it out.
+    if (!Meth->isImplicit())
+      return isTemplate ? oc_method_template : oc_method;
+
+    if (Meth->isMoveAssignmentOperator())
+      return oc_implicit_move_assignment;
+
+    if (Meth->isCopyAssignmentOperator())
+      return oc_implicit_copy_assignment;
+
+    assert(isa<CXXConversionDecl>(Meth) && "expected conversion");
+    return oc_method;
+  }
+
+  return isTemplate ? oc_function_template : oc_function;
+}
+
+void MaybeEmitInheritedConstructorNote(Sema &S, FunctionDecl *Fn) {
+  const CXXConstructorDecl *Ctor = dyn_cast<CXXConstructorDecl>(Fn);
+  if (!Ctor) return;
+
+  Ctor = Ctor->getInheritedConstructor();
+  if (!Ctor) return;
+
+  S.Diag(Ctor->getLocation(), diag::note_ovl_candidate_inherited_constructor);
+}
+
+} // end anonymous namespace
+
+// Notes the location of an overload candidate.
+void Sema::NoteOverloadCandidate(FunctionDecl *Fn, QualType DestType) {
+  std::string FnDesc;
+  OverloadCandidateKind K = ClassifyOverloadCandidate(*this, Fn, FnDesc);
+  PartialDiagnostic PD = PDiag(diag::note_ovl_candidate)
+                             << (unsigned) K << FnDesc;
+  HandleFunctionTypeMismatch(PD, Fn->getType(), DestType);
+  Diag(Fn->getLocation(), PD);
+  MaybeEmitInheritedConstructorNote(*this, Fn);
+}
+
+//Notes the location of all overload candidates designated through 
+// OverloadedExpr
+void Sema::NoteAllOverloadCandidates(Expr* OverloadedExpr, QualType DestType) {
+  assert(OverloadedExpr->getType() == Context.OverloadTy);
+
+  OverloadExpr::FindResult Ovl = OverloadExpr::find(OverloadedExpr);
+  OverloadExpr *OvlExpr = Ovl.Expression;
+
+  for (UnresolvedSetIterator I = OvlExpr->decls_begin(),
+                            IEnd = OvlExpr->decls_end(); 
+       I != IEnd; ++I) {
+    if (FunctionTemplateDecl *FunTmpl = 
+                dyn_cast<FunctionTemplateDecl>((*I)->getUnderlyingDecl()) ) {
+      NoteOverloadCandidate(FunTmpl->getTemplatedDecl(), DestType);
+    } else if (FunctionDecl *Fun 
+                      = dyn_cast<FunctionDecl>((*I)->getUnderlyingDecl()) ) {
+      NoteOverloadCandidate(Fun, DestType);
+    }
+  }
+}
+
+/// Diagnoses an ambiguous conversion.  The partial diagnostic is the
+/// "lead" diagnostic; it will be given two arguments, the source and
+/// target types of the conversion.
+void ImplicitConversionSequence::DiagnoseAmbiguousConversion(
+                                 Sema &S,
+                                 SourceLocation CaretLoc,
+                                 const PartialDiagnostic &PDiag) const {
+  S.Diag(CaretLoc, PDiag)
+    << Ambiguous.getFromType() << Ambiguous.getToType();
+  for (AmbiguousConversionSequence::const_iterator
+         I = Ambiguous.begin(), E = Ambiguous.end(); I != E; ++I) {
+    S.NoteOverloadCandidate(*I);
+  }
+}
+
+namespace {
+
+void DiagnoseBadConversion(Sema &S, OverloadCandidate *Cand, unsigned I) {
+  const ImplicitConversionSequence &Conv = Cand->Conversions[I];
+  assert(Conv.isBad());
+  assert(Cand->Function && "for now, candidate must be a function");
+  FunctionDecl *Fn = Cand->Function;
+
+  // There's a conversion slot for the object argument if this is a
+  // non-constructor method.  Note that 'I' corresponds the
+  // conversion-slot index.
+  bool isObjectArgument = false;
+  if (isa<CXXMethodDecl>(Fn) && !isa<CXXConstructorDecl>(Fn)) {
+    if (I == 0)
+      isObjectArgument = true;
+    else
+      I--;
+  }
+
+  std::string FnDesc;
+  OverloadCandidateKind FnKind = ClassifyOverloadCandidate(S, Fn, FnDesc);
+
+  Expr *FromExpr = Conv.Bad.FromExpr;
+  QualType FromTy = Conv.Bad.getFromType();
+  QualType ToTy = Conv.Bad.getToType();
+
+  if (FromTy == S.Context.OverloadTy) {
+    assert(FromExpr && "overload set argument came from implicit argument?");
+    Expr *E = FromExpr->IgnoreParens();
+    if (isa<UnaryOperator>(E))
+      E = cast<UnaryOperator>(E)->getSubExpr()->IgnoreParens();
+    DeclarationName Name = cast<OverloadExpr>(E)->getName();
+
+    S.Diag(Fn->getLocation(), diag::note_ovl_candidate_bad_overload)
+      << (unsigned) FnKind << FnDesc
+      << (FromExpr ? FromExpr->getSourceRange() : SourceRange())
+      << ToTy << Name << I+1;
+    MaybeEmitInheritedConstructorNote(S, Fn);
+    return;
+  }
+
+  // Do some hand-waving analysis to see if the non-viability is due
+  // to a qualifier mismatch.
+  CanQualType CFromTy = S.Context.getCanonicalType(FromTy);
+  CanQualType CToTy = S.Context.getCanonicalType(ToTy);
+  if (CanQual<ReferenceType> RT = CToTy->getAs<ReferenceType>())
+    CToTy = RT->getPointeeType();
+  else {
+    // TODO: detect and diagnose the full richness of const mismatches.
+    if (CanQual<PointerType> FromPT = CFromTy->getAs<PointerType>())
+      if (CanQual<PointerType> ToPT = CToTy->getAs<PointerType>())
+        CFromTy = FromPT->getPointeeType(), CToTy = ToPT->getPointeeType();
+  }
+
+  if (CToTy.getUnqualifiedType() == CFromTy.getUnqualifiedType() &&
+      !CToTy.isAtLeastAsQualifiedAs(CFromTy)) {
+    Qualifiers FromQs = CFromTy.getQualifiers();
+    Qualifiers ToQs = CToTy.getQualifiers();
+
+    if (FromQs.getAddressSpace() != ToQs.getAddressSpace()) {
+      S.Diag(Fn->getLocation(), diag::note_ovl_candidate_bad_addrspace)
+        << (unsigned) FnKind << FnDesc
+        << (FromExpr ? FromExpr->getSourceRange() : SourceRange())
+        << FromTy
+        << FromQs.getAddressSpace() << ToQs.getAddressSpace()
+        << (unsigned) isObjectArgument << I+1;
+      MaybeEmitInheritedConstructorNote(S, Fn);
+      return;
+    }
+
+    if (FromQs.getObjCLifetime() != ToQs.getObjCLifetime()) {
+      S.Diag(Fn->getLocation(), diag::note_ovl_candidate_bad_ownership)
+        << (unsigned) FnKind << FnDesc
+        << (FromExpr ? FromExpr->getSourceRange() : SourceRange())
+        << FromTy
+        << FromQs.getObjCLifetime() << ToQs.getObjCLifetime()
+        << (unsigned) isObjectArgument << I+1;
+      MaybeEmitInheritedConstructorNote(S, Fn);
+      return;
+    }
+
+    if (FromQs.getObjCGCAttr() != ToQs.getObjCGCAttr()) {
+      S.Diag(Fn->getLocation(), diag::note_ovl_candidate_bad_gc)
+      << (unsigned) FnKind << FnDesc
+      << (FromExpr ? FromExpr->getSourceRange() : SourceRange())
+      << FromTy
+      << FromQs.getObjCGCAttr() << ToQs.getObjCGCAttr()
+      << (unsigned) isObjectArgument << I+1;
+      MaybeEmitInheritedConstructorNote(S, Fn);
+      return;
+    }
+
+    unsigned CVR = FromQs.getCVRQualifiers() & ~ToQs.getCVRQualifiers();
+    assert(CVR && "unexpected qualifiers mismatch");
+
+    if (isObjectArgument) {
+      S.Diag(Fn->getLocation(), diag::note_ovl_candidate_bad_cvr_this)
+        << (unsigned) FnKind << FnDesc
+        << (FromExpr ? FromExpr->getSourceRange() : SourceRange())
+        << FromTy << (CVR - 1);
+    } else {
+      S.Diag(Fn->getLocation(), diag::note_ovl_candidate_bad_cvr)
+        << (unsigned) FnKind << FnDesc
+        << (FromExpr ? FromExpr->getSourceRange() : SourceRange())
+        << FromTy << (CVR - 1) << I+1;
+    }
+    MaybeEmitInheritedConstructorNote(S, Fn);
+    return;
+  }
+
+  // Special diagnostic for failure to convert an initializer list, since
+  // telling the user that it has type void is not useful.
+  if (FromExpr && isa<InitListExpr>(FromExpr)) {
+    S.Diag(Fn->getLocation(), diag::note_ovl_candidate_bad_list_argument)
+      << (unsigned) FnKind << FnDesc
+      << (FromExpr ? FromExpr->getSourceRange() : SourceRange())
+      << FromTy << ToTy << (unsigned) isObjectArgument << I+1;
+    MaybeEmitInheritedConstructorNote(S, Fn);
+    return;
+  }
+
+  // Diagnose references or pointers to incomplete types differently,
+  // since it's far from impossible that the incompleteness triggered
+  // the failure.
+  QualType TempFromTy = FromTy.getNonReferenceType();
+  if (const PointerType *PTy = TempFromTy->getAs<PointerType>())
+    TempFromTy = PTy->getPointeeType();
+  if (TempFromTy->isIncompleteType()) {
+    S.Diag(Fn->getLocation(), diag::note_ovl_candidate_bad_conv_incomplete)
+      << (unsigned) FnKind << FnDesc
+      << (FromExpr ? FromExpr->getSourceRange() : SourceRange())
+      << FromTy << ToTy << (unsigned) isObjectArgument << I+1;
+    MaybeEmitInheritedConstructorNote(S, Fn);
+    return;
+  }
+
+  // Diagnose base -> derived pointer conversions.
+  unsigned BaseToDerivedConversion = 0;
+  if (const PointerType *FromPtrTy = FromTy->getAs<PointerType>()) {
+    if (const PointerType *ToPtrTy = ToTy->getAs<PointerType>()) {
+      if (ToPtrTy->getPointeeType().isAtLeastAsQualifiedAs(
+                                               FromPtrTy->getPointeeType()) &&
+          !FromPtrTy->getPointeeType()->isIncompleteType() &&
+          !ToPtrTy->getPointeeType()->isIncompleteType() &&
+          S.IsDerivedFrom(ToPtrTy->getPointeeType(),
+                          FromPtrTy->getPointeeType()))
+        BaseToDerivedConversion = 1;
+    }
+  } else if (const ObjCObjectPointerType *FromPtrTy
+                                    = FromTy->getAs<ObjCObjectPointerType>()) {
+    if (const ObjCObjectPointerType *ToPtrTy
+                                        = ToTy->getAs<ObjCObjectPointerType>())
+      if (const ObjCInterfaceDecl *FromIface = FromPtrTy->getInterfaceDecl())
+        if (const ObjCInterfaceDecl *ToIface = ToPtrTy->getInterfaceDecl())
+          if (ToPtrTy->getPointeeType().isAtLeastAsQualifiedAs(
+                                                FromPtrTy->getPointeeType()) &&
+              FromIface->isSuperClassOf(ToIface))
+            BaseToDerivedConversion = 2;
+  } else if (const ReferenceType *ToRefTy = ToTy->getAs<ReferenceType>()) {
+      if (ToRefTy->getPointeeType().isAtLeastAsQualifiedAs(FromTy) &&
+          !FromTy->isIncompleteType() &&
+          !ToRefTy->getPointeeType()->isIncompleteType() &&
+          S.IsDerivedFrom(ToRefTy->getPointeeType(), FromTy))
+        BaseToDerivedConversion = 3;
+    }
+
+  if (BaseToDerivedConversion) {
+    S.Diag(Fn->getLocation(),
+           diag::note_ovl_candidate_bad_base_to_derived_conv)
+      << (unsigned) FnKind << FnDesc
+      << (FromExpr ? FromExpr->getSourceRange() : SourceRange())
+      << (BaseToDerivedConversion - 1)
+      << FromTy << ToTy << I+1;
+    MaybeEmitInheritedConstructorNote(S, Fn);
+    return;
+  }
+
+  if (isa<ObjCObjectPointerType>(CFromTy) &&
+      isa<PointerType>(CToTy)) {
+      Qualifiers FromQs = CFromTy.getQualifiers();
+      Qualifiers ToQs = CToTy.getQualifiers();
+      if (FromQs.getObjCLifetime() != ToQs.getObjCLifetime()) {
+        S.Diag(Fn->getLocation(), diag::note_ovl_candidate_bad_arc_conv)
+        << (unsigned) FnKind << FnDesc
+        << (FromExpr ? FromExpr->getSourceRange() : SourceRange())
+        << FromTy << ToTy << (unsigned) isObjectArgument << I+1;
+        MaybeEmitInheritedConstructorNote(S, Fn);
+        return;
+      }
+  }
+  
+  // Emit the generic diagnostic and, optionally, add the hints to it.
+  PartialDiagnostic FDiag = S.PDiag(diag::note_ovl_candidate_bad_conv);
+  FDiag << (unsigned) FnKind << FnDesc
+    << (FromExpr ? FromExpr->getSourceRange() : SourceRange())
+    << FromTy << ToTy << (unsigned) isObjectArgument << I + 1
+    << (unsigned) (Cand->Fix.Kind);
+
+  // If we can fix the conversion, suggest the FixIts.
+  for (std::vector<FixItHint>::iterator HI = Cand->Fix.Hints.begin(),
+       HE = Cand->Fix.Hints.end(); HI != HE; ++HI)
+    FDiag << *HI;
+  S.Diag(Fn->getLocation(), FDiag);
+
+  MaybeEmitInheritedConstructorNote(S, Fn);
+}
+
+void DiagnoseArityMismatch(Sema &S, OverloadCandidate *Cand,
+                           unsigned NumFormalArgs) {
+  // TODO: treat calls to a missing default constructor as a special case
+
+  FunctionDecl *Fn = Cand->Function;
+  const FunctionProtoType *FnTy = Fn->getType()->getAs<FunctionProtoType>();
+
+  unsigned MinParams = Fn->getMinRequiredArguments();
+
+  // With invalid overloaded operators, it's possible that we think we
+  // have an arity mismatch when it fact it looks like we have the
+  // right number of arguments, because only overloaded operators have
+  // the weird behavior of overloading member and non-member functions.
+  // Just don't report anything.
+  if (Fn->isInvalidDecl() && 
+      Fn->getDeclName().getNameKind() == DeclarationName::CXXOperatorName)
+    return;
+
+  // at least / at most / exactly
+  unsigned mode, modeCount;
+  if (NumFormalArgs < MinParams) {
+    assert((Cand->FailureKind == ovl_fail_too_few_arguments) ||
+           (Cand->FailureKind == ovl_fail_bad_deduction &&
+            Cand->DeductionFailure.Result == Sema::TDK_TooFewArguments));
+    if (MinParams != FnTy->getNumArgs() ||
+        FnTy->isVariadic() || FnTy->isTemplateVariadic())
+      mode = 0; // "at least"
+    else
+      mode = 2; // "exactly"
+    modeCount = MinParams;
+  } else {
+    assert((Cand->FailureKind == ovl_fail_too_many_arguments) ||
+           (Cand->FailureKind == ovl_fail_bad_deduction &&
+            Cand->DeductionFailure.Result == Sema::TDK_TooManyArguments));
+    if (MinParams != FnTy->getNumArgs())
+      mode = 1; // "at most"
+    else
+      mode = 2; // "exactly"
+    modeCount = FnTy->getNumArgs();
+  }
+
+  std::string Description;
+  OverloadCandidateKind FnKind = ClassifyOverloadCandidate(S, Fn, Description);
+
+  S.Diag(Fn->getLocation(), diag::note_ovl_candidate_arity)
+    << (unsigned) FnKind << (Fn->getDescribedFunctionTemplate() != 0) << mode
+    << modeCount << NumFormalArgs;
+  MaybeEmitInheritedConstructorNote(S, Fn);
+}
+
+/// Diagnose a failed template-argument deduction.
+void DiagnoseBadDeduction(Sema &S, OverloadCandidate *Cand,
+                          unsigned NumArgs) {
+  FunctionDecl *Fn = Cand->Function; // pattern
+
+  TemplateParameter Param = Cand->DeductionFailure.getTemplateParameter();
+  NamedDecl *ParamD;
+  (ParamD = Param.dyn_cast<TemplateTypeParmDecl*>()) ||
+  (ParamD = Param.dyn_cast<NonTypeTemplateParmDecl*>()) ||
+  (ParamD = Param.dyn_cast<TemplateTemplateParmDecl*>());
+  switch (Cand->DeductionFailure.Result) {
+  case Sema::TDK_Success:
+    llvm_unreachable("TDK_success while diagnosing bad deduction");
+
+  case Sema::TDK_Incomplete: {
+    assert(ParamD && "no parameter found for incomplete deduction result");
+    S.Diag(Fn->getLocation(), diag::note_ovl_candidate_incomplete_deduction)
+      << ParamD->getDeclName();
+    MaybeEmitInheritedConstructorNote(S, Fn);
+    return;
+  }
+
+  case Sema::TDK_Underqualified: {
+    assert(ParamD && "no parameter found for bad qualifiers deduction result");
+    TemplateTypeParmDecl *TParam = cast<TemplateTypeParmDecl>(ParamD);
+
+    QualType Param = Cand->DeductionFailure.getFirstArg()->getAsType();
+
+    // Param will have been canonicalized, but it should just be a
+    // qualified version of ParamD, so move the qualifiers to that.
+    QualifierCollector Qs;
+    Qs.strip(Param);
+    QualType NonCanonParam = Qs.apply(S.Context, TParam->getTypeForDecl());
+    assert(S.Context.hasSameType(Param, NonCanonParam));
+
+    // Arg has also been canonicalized, but there's nothing we can do
+    // about that.  It also doesn't matter as much, because it won't
+    // have any template parameters in it (because deduction isn't
+    // done on dependent types).
+    QualType Arg = Cand->DeductionFailure.getSecondArg()->getAsType();
+
+    S.Diag(Fn->getLocation(), diag::note_ovl_candidate_underqualified)
+      << ParamD->getDeclName() << Arg << NonCanonParam;
+    MaybeEmitInheritedConstructorNote(S, Fn);
+    return;
+  }
+
+  case Sema::TDK_Inconsistent: {
+    assert(ParamD && "no parameter found for inconsistent deduction result");
+    int which = 0;
+    if (isa<TemplateTypeParmDecl>(ParamD))
+      which = 0;
+    else if (isa<NonTypeTemplateParmDecl>(ParamD))
+      which = 1;
+    else {
+      which = 2;
+    }
+
+    S.Diag(Fn->getLocation(), diag::note_ovl_candidate_inconsistent_deduction)
+      << which << ParamD->getDeclName()
+      << *Cand->DeductionFailure.getFirstArg()
+      << *Cand->DeductionFailure.getSecondArg();
+    MaybeEmitInheritedConstructorNote(S, Fn);
+    return;
+  }
+
+  case Sema::TDK_InvalidExplicitArguments:
+    assert(ParamD && "no parameter found for invalid explicit arguments");
+    if (ParamD->getDeclName())
+      S.Diag(Fn->getLocation(),
+             diag::note_ovl_candidate_explicit_arg_mismatch_named)
+        << ParamD->getDeclName();
+    else {
+      int index = 0;
+      if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(ParamD))
+        index = TTP->getIndex();
+      else if (NonTypeTemplateParmDecl *NTTP
+                                  = dyn_cast<NonTypeTemplateParmDecl>(ParamD))
+        index = NTTP->getIndex();
+      else
+        index = cast<TemplateTemplateParmDecl>(ParamD)->getIndex();
+      S.Diag(Fn->getLocation(),
+             diag::note_ovl_candidate_explicit_arg_mismatch_unnamed)
+        << (index + 1);
+    }
+    MaybeEmitInheritedConstructorNote(S, Fn);
+    return;
+
+  case Sema::TDK_TooManyArguments:
+  case Sema::TDK_TooFewArguments:
+    DiagnoseArityMismatch(S, Cand, NumArgs);
+    return;
+
+  case Sema::TDK_InstantiationDepth:
+    S.Diag(Fn->getLocation(), diag::note_ovl_candidate_instantiation_depth);
+    MaybeEmitInheritedConstructorNote(S, Fn);
+    return;
+
+  case Sema::TDK_SubstitutionFailure: {
+    std::string ArgString;
+    if (TemplateArgumentList *Args
+                            = Cand->DeductionFailure.getTemplateArgumentList())
+      ArgString = S.getTemplateArgumentBindingsText(
+                    Fn->getDescribedFunctionTemplate()->getTemplateParameters(),
+                                                    *Args);
+    S.Diag(Fn->getLocation(), diag::note_ovl_candidate_substitution_failure)
+      << ArgString;
+    MaybeEmitInheritedConstructorNote(S, Fn);
+    return;
+  }
+
+  // TODO: diagnose these individually, then kill off
+  // note_ovl_candidate_bad_deduction, which is uselessly vague.
+  case Sema::TDK_NonDeducedMismatch:
+  case Sema::TDK_FailedOverloadResolution:
+    S.Diag(Fn->getLocation(), diag::note_ovl_candidate_bad_deduction);
+    MaybeEmitInheritedConstructorNote(S, Fn);
+    return;
+  }
+}
+
+/// CUDA: diagnose an invalid call across targets.
+void DiagnoseBadTarget(Sema &S, OverloadCandidate *Cand) {
+  FunctionDecl *Caller = cast<FunctionDecl>(S.CurContext);
+  FunctionDecl *Callee = Cand->Function;
+
+  Sema::CUDAFunctionTarget CallerTarget = S.IdentifyCUDATarget(Caller),
+                           CalleeTarget = S.IdentifyCUDATarget(Callee);
+
+  std::string FnDesc;
+  OverloadCandidateKind FnKind = ClassifyOverloadCandidate(S, Callee, FnDesc);
+
+  S.Diag(Callee->getLocation(), diag::note_ovl_candidate_bad_target)
+      << (unsigned) FnKind << CalleeTarget << CallerTarget;
+}
+
+/// Generates a 'note' diagnostic for an overload candidate.  We've
+/// already generated a primary error at the call site.
+///
+/// It really does need to be a single diagnostic with its caret
+/// pointed at the candidate declaration.  Yes, this creates some
+/// major challenges of technical writing.  Yes, this makes pointing
+/// out problems with specific arguments quite awkward.  It's still
+/// better than generating twenty screens of text for every failed
+/// overload.
+///
+/// It would be great to be able to express per-candidate problems
+/// more richly for those diagnostic clients that cared, but we'd
+/// still have to be just as careful with the default diagnostics.
+void NoteFunctionCandidate(Sema &S, OverloadCandidate *Cand,
+                           unsigned NumArgs) {
+  FunctionDecl *Fn = Cand->Function;
+
+  // Note deleted candidates, but only if they're viable.
+  if (Cand->Viable && (Fn->isDeleted() ||
+      S.isFunctionConsideredUnavailable(Fn))) {
+    std::string FnDesc;
+    OverloadCandidateKind FnKind = ClassifyOverloadCandidate(S, Fn, FnDesc);
+
+    S.Diag(Fn->getLocation(), diag::note_ovl_candidate_deleted)
+      << FnKind << FnDesc
+      << (Fn->isDeleted() ? (Fn->isDeletedAsWritten() ? 1 : 2) : 0);
+    MaybeEmitInheritedConstructorNote(S, Fn);
+    return;
+  }
+
+  // We don't really have anything else to say about viable candidates.
+  if (Cand->Viable) {
+    S.NoteOverloadCandidate(Fn);
+    return;
+  }
+
+  switch (Cand->FailureKind) {
+  case ovl_fail_too_many_arguments:
+  case ovl_fail_too_few_arguments:
+    return DiagnoseArityMismatch(S, Cand, NumArgs);
+
+  case ovl_fail_bad_deduction:
+    return DiagnoseBadDeduction(S, Cand, NumArgs);
+
+  case ovl_fail_trivial_conversion:
+  case ovl_fail_bad_final_conversion:
+  case ovl_fail_final_conversion_not_exact:
+    return S.NoteOverloadCandidate(Fn);
+
+  case ovl_fail_bad_conversion: {
+    unsigned I = (Cand->IgnoreObjectArgument ? 1 : 0);
+    for (unsigned N = Cand->NumConversions; I != N; ++I)
+      if (Cand->Conversions[I].isBad())
+        return DiagnoseBadConversion(S, Cand, I);
+
+    // FIXME: this currently happens when we're called from SemaInit
+    // when user-conversion overload fails.  Figure out how to handle
+    // those conditions and diagnose them well.
+    return S.NoteOverloadCandidate(Fn);
+  }
+
+  case ovl_fail_bad_target:
+    return DiagnoseBadTarget(S, Cand);
+  }
+}
+
+void NoteSurrogateCandidate(Sema &S, OverloadCandidate *Cand) {
+  // Desugar the type of the surrogate down to a function type,
+  // retaining as many typedefs as possible while still showing
+  // the function type (and, therefore, its parameter types).
+  QualType FnType = Cand->Surrogate->getConversionType();
+  bool isLValueReference = false;
+  bool isRValueReference = false;
+  bool isPointer = false;
+  if (const LValueReferenceType *FnTypeRef =
+        FnType->getAs<LValueReferenceType>()) {
+    FnType = FnTypeRef->getPointeeType();
+    isLValueReference = true;
+  } else if (const RValueReferenceType *FnTypeRef =
+               FnType->getAs<RValueReferenceType>()) {
+    FnType = FnTypeRef->getPointeeType();
+    isRValueReference = true;
+  }
+  if (const PointerType *FnTypePtr = FnType->getAs<PointerType>()) {
+    FnType = FnTypePtr->getPointeeType();
+    isPointer = true;
+  }
+  // Desugar down to a function type.
+  FnType = QualType(FnType->getAs<FunctionType>(), 0);
+  // Reconstruct the pointer/reference as appropriate.
+  if (isPointer) FnType = S.Context.getPointerType(FnType);
+  if (isRValueReference) FnType = S.Context.getRValueReferenceType(FnType);
+  if (isLValueReference) FnType = S.Context.getLValueReferenceType(FnType);
+
+  S.Diag(Cand->Surrogate->getLocation(), diag::note_ovl_surrogate_cand)
+    << FnType;
+  MaybeEmitInheritedConstructorNote(S, Cand->Surrogate);
+}
+
+void NoteBuiltinOperatorCandidate(Sema &S,
+                                  const char *Opc,
+                                  SourceLocation OpLoc,
+                                  OverloadCandidate *Cand) {
+  assert(Cand->NumConversions <= 2 && "builtin operator is not binary");
+  std::string TypeStr("operator");
+  TypeStr += Opc;
+  TypeStr += "(";
+  TypeStr += Cand->BuiltinTypes.ParamTypes[0].getAsString();
+  if (Cand->NumConversions == 1) {
+    TypeStr += ")";
+    S.Diag(OpLoc, diag::note_ovl_builtin_unary_candidate) << TypeStr;
+  } else {
+    TypeStr += ", ";
+    TypeStr += Cand->BuiltinTypes.ParamTypes[1].getAsString();
+    TypeStr += ")";
+    S.Diag(OpLoc, diag::note_ovl_builtin_binary_candidate) << TypeStr;
+  }
+}
+
+void NoteAmbiguousUserConversions(Sema &S, SourceLocation OpLoc,
+                                  OverloadCandidate *Cand) {
+  unsigned NoOperands = Cand->NumConversions;
+  for (unsigned ArgIdx = 0; ArgIdx < NoOperands; ++ArgIdx) {
+    const ImplicitConversionSequence &ICS = Cand->Conversions[ArgIdx];
+    if (ICS.isBad()) break; // all meaningless after first invalid
+    if (!ICS.isAmbiguous()) continue;
+
+    ICS.DiagnoseAmbiguousConversion(S, OpLoc,
+                              S.PDiag(diag::note_ambiguous_type_conversion));
+  }
+}
+
+SourceLocation GetLocationForCandidate(const OverloadCandidate *Cand) {
+  if (Cand->Function)
+    return Cand->Function->getLocation();
+  if (Cand->IsSurrogate)
+    return Cand->Surrogate->getLocation();
+  return SourceLocation();
+}
+
+static unsigned
+RankDeductionFailure(const OverloadCandidate::DeductionFailureInfo &DFI) {
+  switch ((Sema::TemplateDeductionResult)DFI.Result) {
+  case Sema::TDK_Success:
+    llvm_unreachable("TDK_success while diagnosing bad deduction");
+
+  case Sema::TDK_Incomplete:
+    return 1;
+
+  case Sema::TDK_Underqualified:
+  case Sema::TDK_Inconsistent:
+    return 2;
+
+  case Sema::TDK_SubstitutionFailure:
+  case Sema::TDK_NonDeducedMismatch:
+    return 3;
+
+  case Sema::TDK_InstantiationDepth:
+  case Sema::TDK_FailedOverloadResolution:
+    return 4;
+
+  case Sema::TDK_InvalidExplicitArguments:
+    return 5;
+
+  case Sema::TDK_TooManyArguments:
+  case Sema::TDK_TooFewArguments:
+    return 6;
+  }
+  llvm_unreachable("Unhandled deduction result");
+}
+
+struct CompareOverloadCandidatesForDisplay {
+  Sema &S;
+  CompareOverloadCandidatesForDisplay(Sema &S) : S(S) {}
+
+  bool operator()(const OverloadCandidate *L,
+                  const OverloadCandidate *R) {
+    // Fast-path this check.
+    if (L == R) return false;
+
+    // Order first by viability.
+    if (L->Viable) {
+      if (!R->Viable) return true;
+
+      // TODO: introduce a tri-valued comparison for overload
+      // candidates.  Would be more worthwhile if we had a sort
+      // that could exploit it.
+      if (isBetterOverloadCandidate(S, *L, *R, SourceLocation())) return true;
+      if (isBetterOverloadCandidate(S, *R, *L, SourceLocation())) return false;
+    } else if (R->Viable)
+      return false;
+
+    assert(L->Viable == R->Viable);
+
+    // Criteria by which we can sort non-viable candidates:
+    if (!L->Viable) {
+      // 1. Arity mismatches come after other candidates.
+      if (L->FailureKind == ovl_fail_too_many_arguments ||
+          L->FailureKind == ovl_fail_too_few_arguments)
+        return false;
+      if (R->FailureKind == ovl_fail_too_many_arguments ||
+          R->FailureKind == ovl_fail_too_few_arguments)
+        return true;
+
+      // 2. Bad conversions come first and are ordered by the number
+      // of bad conversions and quality of good conversions.
+      if (L->FailureKind == ovl_fail_bad_conversion) {
+        if (R->FailureKind != ovl_fail_bad_conversion)
+          return true;
+
+        // The conversion that can be fixed with a smaller number of changes,
+        // comes first.
+        unsigned numLFixes = L->Fix.NumConversionsFixed;
+        unsigned numRFixes = R->Fix.NumConversionsFixed;
+        numLFixes = (numLFixes == 0) ? UINT_MAX : numLFixes;
+        numRFixes = (numRFixes == 0) ? UINT_MAX : numRFixes;
+        if (numLFixes != numRFixes) {
+          if (numLFixes < numRFixes)
+            return true;
+          else
+            return false;
+        }
+
+        // If there's any ordering between the defined conversions...
+        // FIXME: this might not be transitive.
+        assert(L->NumConversions == R->NumConversions);
+
+        int leftBetter = 0;
+        unsigned I = (L->IgnoreObjectArgument || R->IgnoreObjectArgument);
+        for (unsigned E = L->NumConversions; I != E; ++I) {
+          switch (CompareImplicitConversionSequences(S,
+                                                     L->Conversions[I],
+                                                     R->Conversions[I])) {
+          case ImplicitConversionSequence::Better:
+            leftBetter++;
+            break;
+
+          case ImplicitConversionSequence::Worse:
+            leftBetter--;
+            break;
+
+          case ImplicitConversionSequence::Indistinguishable:
+            break;
+          }
+        }
+        if (leftBetter > 0) return true;
+        if (leftBetter < 0) return false;
+
+      } else if (R->FailureKind == ovl_fail_bad_conversion)
+        return false;
+
+      if (L->FailureKind == ovl_fail_bad_deduction) {
+        if (R->FailureKind != ovl_fail_bad_deduction)
+          return true;
+
+        if (L->DeductionFailure.Result != R->DeductionFailure.Result)
+          return RankDeductionFailure(L->DeductionFailure)
+               < RankDeductionFailure(R->DeductionFailure);
+      } else if (R->FailureKind == ovl_fail_bad_deduction)
+        return false;
+
+      // TODO: others?
+    }
+
+    // Sort everything else by location.
+    SourceLocation LLoc = GetLocationForCandidate(L);
+    SourceLocation RLoc = GetLocationForCandidate(R);
+
+    // Put candidates without locations (e.g. builtins) at the end.
+    if (LLoc.isInvalid()) return false;
+    if (RLoc.isInvalid()) return true;
+
+    return S.SourceMgr.isBeforeInTranslationUnit(LLoc, RLoc);
+  }
+};
+
+/// CompleteNonViableCandidate - Normally, overload resolution only
+/// computes up to the first. Produces the FixIt set if possible.
+void CompleteNonViableCandidate(Sema &S, OverloadCandidate *Cand,
+                                llvm::ArrayRef<Expr *> Args) {
+  assert(!Cand->Viable);
+
+  // Don't do anything on failures other than bad conversion.
+  if (Cand->FailureKind != ovl_fail_bad_conversion) return;
+
+  // We only want the FixIts if all the arguments can be corrected.
+  bool Unfixable = false;
+  // Use a implicit copy initialization to check conversion fixes.
+  Cand->Fix.setConversionChecker(TryCopyInitialization);
+
+  // Skip forward to the first bad conversion.
+  unsigned ConvIdx = (Cand->IgnoreObjectArgument ? 1 : 0);
+  unsigned ConvCount = Cand->NumConversions;
+  while (true) {
+    assert(ConvIdx != ConvCount && "no bad conversion in candidate");
+    ConvIdx++;
+    if (Cand->Conversions[ConvIdx - 1].isBad()) {
+      Unfixable = !Cand->TryToFixBadConversion(ConvIdx - 1, S);
+      break;
+    }
+  }
+
+  if (ConvIdx == ConvCount)
+    return;
+
+  assert(!Cand->Conversions[ConvIdx].isInitialized() &&
+         "remaining conversion is initialized?");
+
+  // FIXME: this should probably be preserved from the overload
+  // operation somehow.
+  bool SuppressUserConversions = false;
+
+  const FunctionProtoType* Proto;
+  unsigned ArgIdx = ConvIdx;
+
+  if (Cand->IsSurrogate) {
+    QualType ConvType
+      = Cand->Surrogate->getConversionType().getNonReferenceType();
+    if (const PointerType *ConvPtrType = ConvType->getAs<PointerType>())
+      ConvType = ConvPtrType->getPointeeType();
+    Proto = ConvType->getAs<FunctionProtoType>();
+    ArgIdx--;
+  } else if (Cand->Function) {
+    Proto = Cand->Function->getType()->getAs<FunctionProtoType>();
+    if (isa<CXXMethodDecl>(Cand->Function) &&
+        !isa<CXXConstructorDecl>(Cand->Function))
+      ArgIdx--;
+  } else {
+    // Builtin binary operator with a bad first conversion.
+    assert(ConvCount <= 3);
+    for (; ConvIdx != ConvCount; ++ConvIdx)
+      Cand->Conversions[ConvIdx]
+        = TryCopyInitialization(S, Args[ConvIdx],
+                                Cand->BuiltinTypes.ParamTypes[ConvIdx],
+                                SuppressUserConversions,
+                                /*InOverloadResolution*/ true,
+                                /*AllowObjCWritebackConversion=*/
+                                  S.getLangOpts().ObjCAutoRefCount);
+    return;
+  }
+
+  // Fill in the rest of the conversions.
+  unsigned NumArgsInProto = Proto->getNumArgs();
+  for (; ConvIdx != ConvCount; ++ConvIdx, ++ArgIdx) {
+    if (ArgIdx < NumArgsInProto) {
+      Cand->Conversions[ConvIdx]
+        = TryCopyInitialization(S, Args[ArgIdx], Proto->getArgType(ArgIdx),
+                                SuppressUserConversions,
+                                /*InOverloadResolution=*/true,
+                                /*AllowObjCWritebackConversion=*/
+                                  S.getLangOpts().ObjCAutoRefCount);
+      // Store the FixIt in the candidate if it exists.
+      if (!Unfixable && Cand->Conversions[ConvIdx].isBad())
+        Unfixable = !Cand->TryToFixBadConversion(ConvIdx, S);
+    }
+    else
+      Cand->Conversions[ConvIdx].setEllipsis();
+  }
+}
+
+} // end anonymous namespace
+
+/// PrintOverloadCandidates - When overload resolution fails, prints
+/// diagnostic messages containing the candidates in the candidate
+/// set.
+void OverloadCandidateSet::NoteCandidates(Sema &S,
+                                          OverloadCandidateDisplayKind OCD,
+                                          llvm::ArrayRef<Expr *> Args,
+                                          const char *Opc,
+                                          SourceLocation OpLoc) {
+  // Sort the candidates by viability and position.  Sorting directly would
+  // be prohibitive, so we make a set of pointers and sort those.
+  SmallVector<OverloadCandidate*, 32> Cands;
+  if (OCD == OCD_AllCandidates) Cands.reserve(size());
+  for (iterator Cand = begin(), LastCand = end(); Cand != LastCand; ++Cand) {
+    if (Cand->Viable)
+      Cands.push_back(Cand);
+    else if (OCD == OCD_AllCandidates) {
+      CompleteNonViableCandidate(S, Cand, Args);
+      if (Cand->Function || Cand->IsSurrogate)
+        Cands.push_back(Cand);
+      // Otherwise, this a non-viable builtin candidate.  We do not, in general,
+      // want to list every possible builtin candidate.
+    }
+  }
+
+  std::sort(Cands.begin(), Cands.end(),
+            CompareOverloadCandidatesForDisplay(S));
+
+  bool ReportedAmbiguousConversions = false;
+
+  SmallVectorImpl<OverloadCandidate*>::iterator I, E;
+  const DiagnosticsEngine::OverloadsShown ShowOverloads = 
+      S.Diags.getShowOverloads();
+  unsigned CandsShown = 0;
+  for (I = Cands.begin(), E = Cands.end(); I != E; ++I) {
+    OverloadCandidate *Cand = *I;
+
+    // Set an arbitrary limit on the number of candidate functions we'll spam
+    // the user with.  FIXME: This limit should depend on details of the
+    // candidate list.
+    if (CandsShown >= 4 && ShowOverloads == DiagnosticsEngine::Ovl_Best) {
+      break;
+    }
+    ++CandsShown;
+
+    if (Cand->Function)
+      NoteFunctionCandidate(S, Cand, Args.size());
+    else if (Cand->IsSurrogate)
+      NoteSurrogateCandidate(S, Cand);
+    else {
+      assert(Cand->Viable &&
+             "Non-viable built-in candidates are not added to Cands.");
+      // Generally we only see ambiguities including viable builtin
+      // operators if overload resolution got screwed up by an
+      // ambiguous user-defined conversion.
+      //
+      // FIXME: It's quite possible for different conversions to see
+      // different ambiguities, though.
+      if (!ReportedAmbiguousConversions) {
+        NoteAmbiguousUserConversions(S, OpLoc, Cand);
+        ReportedAmbiguousConversions = true;
+      }
+
+      // If this is a viable builtin, print it.
+      NoteBuiltinOperatorCandidate(S, Opc, OpLoc, Cand);
+    }
+  }
+
+  if (I != E)
+    S.Diag(OpLoc, diag::note_ovl_too_many_candidates) << int(E - I);
+}
+
+// [PossiblyAFunctionType]  -->   [Return]
+// NonFunctionType --> NonFunctionType
+// R (A) --> R(A)
+// R (*)(A) --> R (A)
+// R (&)(A) --> R (A)
+// R (S::*)(A) --> R (A)
+QualType Sema::ExtractUnqualifiedFunctionType(QualType PossiblyAFunctionType) {
+  QualType Ret = PossiblyAFunctionType;
+  if (const PointerType *ToTypePtr = 
+    PossiblyAFunctionType->getAs<PointerType>())
+    Ret = ToTypePtr->getPointeeType();
+  else if (const ReferenceType *ToTypeRef = 
+    PossiblyAFunctionType->getAs<ReferenceType>())
+    Ret = ToTypeRef->getPointeeType();
+  else if (const MemberPointerType *MemTypePtr =
+    PossiblyAFunctionType->getAs<MemberPointerType>()) 
+    Ret = MemTypePtr->getPointeeType();   
+  Ret = 
+    Context.getCanonicalType(Ret).getUnqualifiedType();
+  return Ret;
+}
+
+// A helper class to help with address of function resolution
+// - allows us to avoid passing around all those ugly parameters
+class AddressOfFunctionResolver 
+{
+  Sema& S;
+  Expr* SourceExpr;
+  const QualType& TargetType; 
+  QualType TargetFunctionType; // Extracted function type from target type 
+   
+  bool Complain;
+  //DeclAccessPair& ResultFunctionAccessPair;
+  ASTContext& Context;
+
+  bool TargetTypeIsNonStaticMemberFunction;
+  bool FoundNonTemplateFunction;
+
+  OverloadExpr::FindResult OvlExprInfo; 
+  OverloadExpr *OvlExpr;
+  TemplateArgumentListInfo OvlExplicitTemplateArgs;
+  SmallVector<std::pair<DeclAccessPair, FunctionDecl*>, 4> Matches;
+
+public:
+  AddressOfFunctionResolver(Sema &S, Expr* SourceExpr, 
+                            const QualType& TargetType, bool Complain)
+    : S(S), SourceExpr(SourceExpr), TargetType(TargetType), 
+      Complain(Complain), Context(S.getASTContext()), 
+      TargetTypeIsNonStaticMemberFunction(
+                                    !!TargetType->getAs<MemberPointerType>()),
+      FoundNonTemplateFunction(false),
+      OvlExprInfo(OverloadExpr::find(SourceExpr)),
+      OvlExpr(OvlExprInfo.Expression)
+  {
+    ExtractUnqualifiedFunctionTypeFromTargetType();
+    
+    if (!TargetFunctionType->isFunctionType()) {        
+      if (OvlExpr->hasExplicitTemplateArgs()) {
+        DeclAccessPair dap;
+        if (FunctionDecl* Fn = S.ResolveSingleFunctionTemplateSpecialization(
+                                            OvlExpr, false, &dap) ) {
+
+          if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(Fn)) {
+            if (!Method->isStatic()) {
+              // If the target type is a non-function type and the function
+              // found is a non-static member function, pretend as if that was
+              // the target, it's the only possible type to end up with.
+              TargetTypeIsNonStaticMemberFunction = true;
+
+              // And skip adding the function if its not in the proper form.
+              // We'll diagnose this due to an empty set of functions.
+              if (!OvlExprInfo.HasFormOfMemberPointer)
+                return;
+            }
+          }
+
+          Matches.push_back(std::make_pair(dap,Fn));
+        }
+      }
+      return;
+    }
+    
+    if (OvlExpr->hasExplicitTemplateArgs())
+      OvlExpr->getExplicitTemplateArgs().copyInto(OvlExplicitTemplateArgs);
+
+    if (FindAllFunctionsThatMatchTargetTypeExactly()) {
+      // C++ [over.over]p4:
+      //   If more than one function is selected, [...]
+      if (Matches.size() > 1) {
+        if (FoundNonTemplateFunction)
+          EliminateAllTemplateMatches();
+        else
+          EliminateAllExceptMostSpecializedTemplate();
+      }
+    }
+  }
+  
+private:
+  bool isTargetTypeAFunction() const {
+    return TargetFunctionType->isFunctionType();
+  }
+
+  // [ToType]     [Return]
+
+  // R (*)(A) --> R (A), IsNonStaticMemberFunction = false
+  // R (&)(A) --> R (A), IsNonStaticMemberFunction = false
+  // R (S::*)(A) --> R (A), IsNonStaticMemberFunction = true
+  void inline ExtractUnqualifiedFunctionTypeFromTargetType() {
+    TargetFunctionType = S.ExtractUnqualifiedFunctionType(TargetType);
+  }
+
+  // return true if any matching specializations were found
+  bool AddMatchingTemplateFunction(FunctionTemplateDecl* FunctionTemplate, 
+                                   const DeclAccessPair& CurAccessFunPair) {
+    if (CXXMethodDecl *Method
+              = dyn_cast<CXXMethodDecl>(FunctionTemplate->getTemplatedDecl())) {
+      // Skip non-static function templates when converting to pointer, and
+      // static when converting to member pointer.
+      if (Method->isStatic() == TargetTypeIsNonStaticMemberFunction)
+        return false;
+    } 
+    else if (TargetTypeIsNonStaticMemberFunction)
+      return false;
+
+    // C++ [over.over]p2:
+    //   If the name is a function template, template argument deduction is
+    //   done (14.8.2.2), and if the argument deduction succeeds, the
+    //   resulting template argument list is used to generate a single
+    //   function template specialization, which is added to the set of
+    //   overloaded functions considered.
+    FunctionDecl *Specialization = 0;
+    TemplateDeductionInfo Info(Context, OvlExpr->getNameLoc());
+    if (Sema::TemplateDeductionResult Result
+          = S.DeduceTemplateArguments(FunctionTemplate, 
+                                      &OvlExplicitTemplateArgs,
+                                      TargetFunctionType, Specialization, 
+                                      Info)) {
+      // FIXME: make a note of the failed deduction for diagnostics.
+      (void)Result;
+      return false;
+    } 
+    
+    // Template argument deduction ensures that we have an exact match.
+    // This function template specicalization works.
+    Specialization = cast<FunctionDecl>(Specialization->getCanonicalDecl());
+    assert(TargetFunctionType
+                      == Context.getCanonicalType(Specialization->getType()));
+    Matches.push_back(std::make_pair(CurAccessFunPair, Specialization));
+    return true;
+  }
+  
+  bool AddMatchingNonTemplateFunction(NamedDecl* Fn, 
+                                      const DeclAccessPair& CurAccessFunPair) {
+    if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(Fn)) {
+      // Skip non-static functions when converting to pointer, and static
+      // when converting to member pointer.
+      if (Method->isStatic() == TargetTypeIsNonStaticMemberFunction)
+        return false;
+    } 
+    else if (TargetTypeIsNonStaticMemberFunction)
+      return false;
+
+    if (FunctionDecl *FunDecl = dyn_cast<FunctionDecl>(Fn)) {
+      if (S.getLangOpts().CUDA)
+        if (FunctionDecl *Caller = dyn_cast<FunctionDecl>(S.CurContext))
+          if (S.CheckCUDATarget(Caller, FunDecl))
+            return false;
+
+      QualType ResultTy;
+      if (Context.hasSameUnqualifiedType(TargetFunctionType, 
+                                         FunDecl->getType()) ||
+          S.IsNoReturnConversion(FunDecl->getType(), TargetFunctionType,
+                                 ResultTy)) {
+        Matches.push_back(std::make_pair(CurAccessFunPair,
+          cast<FunctionDecl>(FunDecl->getCanonicalDecl())));
+        FoundNonTemplateFunction = true;
+        return true;
+      }
+    }
+    
+    return false;
+  }
+  
+  bool FindAllFunctionsThatMatchTargetTypeExactly() {
+    bool Ret = false;
+    
+    // If the overload expression doesn't have the form of a pointer to
+    // member, don't try to convert it to a pointer-to-member type.
+    if (IsInvalidFormOfPointerToMemberFunction())
+      return false;
+
+    for (UnresolvedSetIterator I = OvlExpr->decls_begin(),
+                               E = OvlExpr->decls_end(); 
+         I != E; ++I) {
+      // Look through any using declarations to find the underlying function.
+      NamedDecl *Fn = (*I)->getUnderlyingDecl();
+
+      // C++ [over.over]p3:
+      //   Non-member functions and static member functions match
+      //   targets of type "pointer-to-function" or "reference-to-function."
+      //   Nonstatic member functions match targets of
+      //   type "pointer-to-member-function."
+      // Note that according to DR 247, the containing class does not matter.
+      if (FunctionTemplateDecl *FunctionTemplate
+                                        = dyn_cast<FunctionTemplateDecl>(Fn)) {
+        if (AddMatchingTemplateFunction(FunctionTemplate, I.getPair()))
+          Ret = true;
+      }
+      // If we have explicit template arguments supplied, skip non-templates.
+      else if (!OvlExpr->hasExplicitTemplateArgs() &&
+               AddMatchingNonTemplateFunction(Fn, I.getPair()))
+        Ret = true;
+    }
+    assert(Ret || Matches.empty());
+    return Ret;
+  }
+
+  void EliminateAllExceptMostSpecializedTemplate() {
+    //   [...] and any given function template specialization F1 is
+    //   eliminated if the set contains a second function template
+    //   specialization whose function template is more specialized
+    //   than the function template of F1 according to the partial
+    //   ordering rules of 14.5.5.2.
+
+    // The algorithm specified above is quadratic. We instead use a
+    // two-pass algorithm (similar to the one used to identify the
+    // best viable function in an overload set) that identifies the
+    // best function template (if it exists).
+
+    UnresolvedSet<4> MatchesCopy; // TODO: avoid!
+    for (unsigned I = 0, E = Matches.size(); I != E; ++I)
+      MatchesCopy.addDecl(Matches[I].second, Matches[I].first.getAccess());
+
+    UnresolvedSetIterator Result =
+      S.getMostSpecialized(MatchesCopy.begin(), MatchesCopy.end(),
+                           TPOC_Other, 0, SourceExpr->getLocStart(),
+                           S.PDiag(),
+                           S.PDiag(diag::err_addr_ovl_ambiguous)
+                             << Matches[0].second->getDeclName(),
+                           S.PDiag(diag::note_ovl_candidate)
+                             << (unsigned) oc_function_template,
+                           Complain, TargetFunctionType);
+
+    if (Result != MatchesCopy.end()) {
+      // Make it the first and only element
+      Matches[0].first = Matches[Result - MatchesCopy.begin()].first;
+      Matches[0].second = cast<FunctionDecl>(*Result);
+      Matches.resize(1);
+    }
+  }
+
+  void EliminateAllTemplateMatches() {
+    //   [...] any function template specializations in the set are
+    //   eliminated if the set also contains a non-template function, [...]
+    for (unsigned I = 0, N = Matches.size(); I != N; ) {
+      if (Matches[I].second->getPrimaryTemplate() == 0)
+        ++I;
+      else {
+        Matches[I] = Matches[--N];
+        Matches.set_size(N);
+      }
+    }
+  }
+
+public:
+  void ComplainNoMatchesFound() const {
+    assert(Matches.empty());
+    S.Diag(OvlExpr->getLocStart(), diag::err_addr_ovl_no_viable)
+        << OvlExpr->getName() << TargetFunctionType
+        << OvlExpr->getSourceRange();
+    S.NoteAllOverloadCandidates(OvlExpr, TargetFunctionType);
+  } 
+  
+  bool IsInvalidFormOfPointerToMemberFunction() const {
+    return TargetTypeIsNonStaticMemberFunction &&
+      !OvlExprInfo.HasFormOfMemberPointer;
+  }
+  
+  void ComplainIsInvalidFormOfPointerToMemberFunction() const {
+      // TODO: Should we condition this on whether any functions might
+      // have matched, or is it more appropriate to do that in callers?
+      // TODO: a fixit wouldn't hurt.
+      S.Diag(OvlExpr->getNameLoc(), diag::err_addr_ovl_no_qualifier)
+        << TargetType << OvlExpr->getSourceRange();
+  }
+  
+  void ComplainOfInvalidConversion() const {
+    S.Diag(OvlExpr->getLocStart(), diag::err_addr_ovl_not_func_ptrref)
+      << OvlExpr->getName() << TargetType;
+  }
+
+  void ComplainMultipleMatchesFound() const {
+    assert(Matches.size() > 1);
+    S.Diag(OvlExpr->getLocStart(), diag::err_addr_ovl_ambiguous)
+      << OvlExpr->getName()
+      << OvlExpr->getSourceRange();
+    S.NoteAllOverloadCandidates(OvlExpr, TargetFunctionType);
+  }
+
+  bool hadMultipleCandidates() const { return (OvlExpr->getNumDecls() > 1); }
+
+  int getNumMatches() const { return Matches.size(); }
+  
+  FunctionDecl* getMatchingFunctionDecl() const {
+    if (Matches.size() != 1) return 0;
+    return Matches[0].second;
+  }
+  
+  const DeclAccessPair* getMatchingFunctionAccessPair() const {
+    if (Matches.size() != 1) return 0;
+    return &Matches[0].first;
+  }
+};
+  
+/// ResolveAddressOfOverloadedFunction - Try to resolve the address of
+/// an overloaded function (C++ [over.over]), where @p From is an
+/// expression with overloaded function type and @p ToType is the type
+/// we're trying to resolve to. For example:
+///
+/// @code
+/// int f(double);
+/// int f(int);
+///
+/// int (*pfd)(double) = f; // selects f(double)
+/// @endcode
+///
+/// This routine returns the resulting FunctionDecl if it could be
+/// resolved, and NULL otherwise. When @p Complain is true, this
+/// routine will emit diagnostics if there is an error.
+FunctionDecl *
+Sema::ResolveAddressOfOverloadedFunction(Expr *AddressOfExpr,
+                                         QualType TargetType,
+                                         bool Complain,
+                                         DeclAccessPair &FoundResult,
+                                         bool *pHadMultipleCandidates) {
+  assert(AddressOfExpr->getType() == Context.OverloadTy);
+
+  AddressOfFunctionResolver Resolver(*this, AddressOfExpr, TargetType,
+                                     Complain);
+  int NumMatches = Resolver.getNumMatches();
+  FunctionDecl* Fn = 0;
+  if (NumMatches == 0 && Complain) {
+    if (Resolver.IsInvalidFormOfPointerToMemberFunction())
+      Resolver.ComplainIsInvalidFormOfPointerToMemberFunction();
+    else
+      Resolver.ComplainNoMatchesFound();
+  }
+  else if (NumMatches > 1 && Complain)
+    Resolver.ComplainMultipleMatchesFound();
+  else if (NumMatches == 1) {
+    Fn = Resolver.getMatchingFunctionDecl();
+    assert(Fn);
+    FoundResult = *Resolver.getMatchingFunctionAccessPair();
+    MarkFunctionReferenced(AddressOfExpr->getLocStart(), Fn);
+    if (Complain)
+      CheckAddressOfMemberAccess(AddressOfExpr, FoundResult);
+  }
+
+  if (pHadMultipleCandidates)
+    *pHadMultipleCandidates = Resolver.hadMultipleCandidates();
+  return Fn;
+}
+
+/// \brief Given an expression that refers to an overloaded function, try to
+/// resolve that overloaded function expression down to a single function.
+///
+/// This routine can only resolve template-ids that refer to a single function
+/// template, where that template-id refers to a single template whose template
+/// arguments are either provided by the template-id or have defaults,
+/// as described in C++0x [temp.arg.explicit]p3.
+FunctionDecl *
+Sema::ResolveSingleFunctionTemplateSpecialization(OverloadExpr *ovl, 
+                                                  bool Complain,
+                                                  DeclAccessPair *FoundResult) {
+  // C++ [over.over]p1:
+  //   [...] [Note: any redundant set of parentheses surrounding the
+  //   overloaded function name is ignored (5.1). ]
+  // C++ [over.over]p1:
+  //   [...] The overloaded function name can be preceded by the &
+  //   operator.
+
+  // If we didn't actually find any template-ids, we're done.
+  if (!ovl->hasExplicitTemplateArgs())
+    return 0;
+
+  TemplateArgumentListInfo ExplicitTemplateArgs;
+  ovl->getExplicitTemplateArgs().copyInto(ExplicitTemplateArgs);
+
+  // Look through all of the overloaded functions, searching for one
+  // whose type matches exactly.
+  FunctionDecl *Matched = 0;
+  for (UnresolvedSetIterator I = ovl->decls_begin(),
+         E = ovl->decls_end(); I != E; ++I) {
+    // C++0x [temp.arg.explicit]p3:
+    //   [...] In contexts where deduction is done and fails, or in contexts
+    //   where deduction is not done, if a template argument list is
+    //   specified and it, along with any default template arguments,
+    //   identifies a single function template specialization, then the
+    //   template-id is an lvalue for the function template specialization.
+    FunctionTemplateDecl *FunctionTemplate
+      = cast<FunctionTemplateDecl>((*I)->getUnderlyingDecl());
+
+    // C++ [over.over]p2:
+    //   If the name is a function template, template argument deduction is
+    //   done (14.8.2.2), and if the argument deduction succeeds, the
+    //   resulting template argument list is used to generate a single
+    //   function template specialization, which is added to the set of
+    //   overloaded functions considered.
+    FunctionDecl *Specialization = 0;
+    TemplateDeductionInfo Info(Context, ovl->getNameLoc());
+    if (TemplateDeductionResult Result
+          = DeduceTemplateArguments(FunctionTemplate, &ExplicitTemplateArgs,
+                                    Specialization, Info)) {
+      // FIXME: make a note of the failed deduction for diagnostics.
+      (void)Result;
+      continue;
+    }
+
+    assert(Specialization && "no specialization and no error?");
+
+    // Multiple matches; we can't resolve to a single declaration.
+    if (Matched) {
+      if (Complain) {
+        Diag(ovl->getExprLoc(), diag::err_addr_ovl_ambiguous)
+          << ovl->getName();
+        NoteAllOverloadCandidates(ovl);
+      }
+      return 0;
+    }
+    
+    Matched = Specialization;
+    if (FoundResult) *FoundResult = I.getPair();    
+  }
+
+  return Matched;
+}
+
+
+
+
+// Resolve and fix an overloaded expression that can be resolved
+// because it identifies a single function template specialization.
+//
+// Last three arguments should only be supplied if Complain = true
+//
+// Return true if it was logically possible to so resolve the
+// expression, regardless of whether or not it succeeded.  Always
+// returns true if 'complain' is set.
+bool Sema::ResolveAndFixSingleFunctionTemplateSpecialization(
+                      ExprResult &SrcExpr, bool doFunctionPointerConverion,
+                   bool complain, const SourceRange& OpRangeForComplaining, 
+                                           QualType DestTypeForComplaining, 
+                                            unsigned DiagIDForComplaining) {
+  assert(SrcExpr.get()->getType() == Context.OverloadTy);
+
+  OverloadExpr::FindResult ovl = OverloadExpr::find(SrcExpr.get());
+
+  DeclAccessPair found;
+  ExprResult SingleFunctionExpression;
+  if (FunctionDecl *fn = ResolveSingleFunctionTemplateSpecialization(
+                           ovl.Expression, /*complain*/ false, &found)) {
+    if (DiagnoseUseOfDecl(fn, SrcExpr.get()->getLocStart())) {
+      SrcExpr = ExprError();
+      return true;
+    }
+
+    // It is only correct to resolve to an instance method if we're
+    // resolving a form that's permitted to be a pointer to member.
+    // Otherwise we'll end up making a bound member expression, which
+    // is illegal in all the contexts we resolve like this.
+    if (!ovl.HasFormOfMemberPointer &&
+        isa<CXXMethodDecl>(fn) &&
+        cast<CXXMethodDecl>(fn)->isInstance()) {
+      if (!complain) return false;
+
+      Diag(ovl.Expression->getExprLoc(),
+           diag::err_bound_member_function)
+        << 0 << ovl.Expression->getSourceRange();
+
+      // TODO: I believe we only end up here if there's a mix of
+      // static and non-static candidates (otherwise the expression
+      // would have 'bound member' type, not 'overload' type).
+      // Ideally we would note which candidate was chosen and why
+      // the static candidates were rejected.
+      SrcExpr = ExprError();
+      return true;
+    }
+
+    // Fix the expresion to refer to 'fn'.
+    SingleFunctionExpression =
+      Owned(FixOverloadedFunctionReference(SrcExpr.take(), found, fn));
+
+    // If desired, do function-to-pointer decay.
+    if (doFunctionPointerConverion) {
+      SingleFunctionExpression =
+        DefaultFunctionArrayLvalueConversion(SingleFunctionExpression.take());
+      if (SingleFunctionExpression.isInvalid()) {
+        SrcExpr = ExprError();
+        return true;
+      }
+    }
+  }
+
+  if (!SingleFunctionExpression.isUsable()) {
+    if (complain) {
+      Diag(OpRangeForComplaining.getBegin(), DiagIDForComplaining)
+        << ovl.Expression->getName()
+        << DestTypeForComplaining
+        << OpRangeForComplaining 
+        << ovl.Expression->getQualifierLoc().getSourceRange();
+      NoteAllOverloadCandidates(SrcExpr.get());
+
+      SrcExpr = ExprError();
+      return true;
+    }
+
+    return false;
+  }
+
+  SrcExpr = SingleFunctionExpression;
+  return true;
+}
+
+/// \brief Add a single candidate to the overload set.
+static void AddOverloadedCallCandidate(Sema &S,
+                                       DeclAccessPair FoundDecl,
+                                 TemplateArgumentListInfo *ExplicitTemplateArgs,
+                                       llvm::ArrayRef<Expr *> Args,
+                                       OverloadCandidateSet &CandidateSet,
+                                       bool PartialOverloading,
+                                       bool KnownValid) {
+  NamedDecl *Callee = FoundDecl.getDecl();
+  if (isa<UsingShadowDecl>(Callee))
+    Callee = cast<UsingShadowDecl>(Callee)->getTargetDecl();
+
+  if (FunctionDecl *Func = dyn_cast<FunctionDecl>(Callee)) {
+    if (ExplicitTemplateArgs) {
+      assert(!KnownValid && "Explicit template arguments?");
+      return;
+    }
+    S.AddOverloadCandidate(Func, FoundDecl, Args, CandidateSet, false,
+                           PartialOverloading);
+    return;
+  }
+
+  if (FunctionTemplateDecl *FuncTemplate
+      = dyn_cast<FunctionTemplateDecl>(Callee)) {
+    S.AddTemplateOverloadCandidate(FuncTemplate, FoundDecl,
+                                   ExplicitTemplateArgs, Args, CandidateSet);
+    return;
+  }
+
+  assert(!KnownValid && "unhandled case in overloaded call candidate");
+}
+
+/// \brief Add the overload candidates named by callee and/or found by argument
+/// dependent lookup to the given overload set.
+void Sema::AddOverloadedCallCandidates(UnresolvedLookupExpr *ULE,
+                                       llvm::ArrayRef<Expr *> Args,
+                                       OverloadCandidateSet &CandidateSet,
+                                       bool PartialOverloading) {
+
+#ifndef NDEBUG
+  // Verify that ArgumentDependentLookup is consistent with the rules
+  // in C++0x [basic.lookup.argdep]p3:
+  //
+  //   Let X be the lookup set produced by unqualified lookup (3.4.1)
+  //   and let Y be the lookup set produced by argument dependent
+  //   lookup (defined as follows). If X contains
+  //
+  //     -- a declaration of a class member, or
+  //
+  //     -- a block-scope function declaration that is not a
+  //        using-declaration, or
+  //
+  //     -- a declaration that is neither a function or a function
+  //        template
+  //
+  //   then Y is empty.
+
+  if (ULE->requiresADL()) {
+    for (UnresolvedLookupExpr::decls_iterator I = ULE->decls_begin(),
+           E = ULE->decls_end(); I != E; ++I) {
+      assert(!(*I)->getDeclContext()->isRecord());
+      assert(isa<UsingShadowDecl>(*I) ||
+             !(*I)->getDeclContext()->isFunctionOrMethod());
+      assert((*I)->getUnderlyingDecl()->isFunctionOrFunctionTemplate());
+    }
+  }
+#endif
+
+  // It would be nice to avoid this copy.
+  TemplateArgumentListInfo TABuffer;
+  TemplateArgumentListInfo *ExplicitTemplateArgs = 0;
+  if (ULE->hasExplicitTemplateArgs()) {
+    ULE->copyTemplateArgumentsInto(TABuffer);
+    ExplicitTemplateArgs = &TABuffer;
+  }
+
+  for (UnresolvedLookupExpr::decls_iterator I = ULE->decls_begin(),
+         E = ULE->decls_end(); I != E; ++I)
+    AddOverloadedCallCandidate(*this, I.getPair(), ExplicitTemplateArgs, Args,
+                               CandidateSet, PartialOverloading,
+                               /*KnownValid*/ true);
+
+  if (ULE->requiresADL())
+    AddArgumentDependentLookupCandidates(ULE->getName(), /*Operator*/ false,
+                                         ULE->getExprLoc(),
+                                         Args, ExplicitTemplateArgs,
+                                         CandidateSet, PartialOverloading,
+                                         ULE->isStdAssociatedNamespace());
+}
+
+/// Attempt to recover from an ill-formed use of a non-dependent name in a
+/// template, where the non-dependent name was declared after the template
+/// was defined. This is common in code written for a compilers which do not
+/// correctly implement two-stage name lookup.
+///
+/// Returns true if a viable candidate was found and a diagnostic was issued.
+static bool
+DiagnoseTwoPhaseLookup(Sema &SemaRef, SourceLocation FnLoc,
+                       const CXXScopeSpec &SS, LookupResult &R,
+                       TemplateArgumentListInfo *ExplicitTemplateArgs,
+                       llvm::ArrayRef<Expr *> Args) {
+  if (SemaRef.ActiveTemplateInstantiations.empty() || !SS.isEmpty())
+    return false;
+
+  for (DeclContext *DC = SemaRef.CurContext; DC; DC = DC->getParent()) {
+    if (DC->isTransparentContext())
+      continue;
+
+    SemaRef.LookupQualifiedName(R, DC);
+
+    if (!R.empty()) {
+      R.suppressDiagnostics();
+
+      if (isa<CXXRecordDecl>(DC)) {
+        // Don't diagnose names we find in classes; we get much better
+        // diagnostics for these from DiagnoseEmptyLookup.
+        R.clear();
+        return false;
+      }
+
+      OverloadCandidateSet Candidates(FnLoc);
+      for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I)
+        AddOverloadedCallCandidate(SemaRef, I.getPair(),
+                                   ExplicitTemplateArgs, Args,
+                                   Candidates, false, /*KnownValid*/ false);
+
+      OverloadCandidateSet::iterator Best;
+      if (Candidates.BestViableFunction(SemaRef, FnLoc, Best) != OR_Success) {
+        // No viable functions. Don't bother the user with notes for functions
+        // which don't work and shouldn't be found anyway.
+        R.clear();
+        return false;
+      }
+
+      // Find the namespaces where ADL would have looked, and suggest
+      // declaring the function there instead.
+      Sema::AssociatedNamespaceSet AssociatedNamespaces;
+      Sema::AssociatedClassSet AssociatedClasses;
+      SemaRef.FindAssociatedClassesAndNamespaces(Args,
+                                                 AssociatedNamespaces,
+                                                 AssociatedClasses);
+      // Never suggest declaring a function within namespace 'std'. 
+      Sema::AssociatedNamespaceSet SuggestedNamespaces;
+      if (DeclContext *Std = SemaRef.getStdNamespace()) {
+        for (Sema::AssociatedNamespaceSet::iterator
+               it = AssociatedNamespaces.begin(),
+               end = AssociatedNamespaces.end(); it != end; ++it) {
+          if (!Std->Encloses(*it))
+            SuggestedNamespaces.insert(*it);
+        }
+      } else {
+        // Lacking the 'std::' namespace, use all of the associated namespaces.
+        SuggestedNamespaces = AssociatedNamespaces;
+      }
+
+      SemaRef.Diag(R.getNameLoc(), diag::err_not_found_by_two_phase_lookup)
+        << R.getLookupName();
+      if (SuggestedNamespaces.empty()) {
+        SemaRef.Diag(Best->Function->getLocation(),
+                     diag::note_not_found_by_two_phase_lookup)
+          << R.getLookupName() << 0;
+      } else if (SuggestedNamespaces.size() == 1) {
+        SemaRef.Diag(Best->Function->getLocation(),
+                     diag::note_not_found_by_two_phase_lookup)
+          << R.getLookupName() << 1 << *SuggestedNamespaces.begin();
+      } else {
+        // FIXME: It would be useful to list the associated namespaces here,
+        // but the diagnostics infrastructure doesn't provide a way to produce
+        // a localized representation of a list of items.
+        SemaRef.Diag(Best->Function->getLocation(),
+                     diag::note_not_found_by_two_phase_lookup)
+          << R.getLookupName() << 2;
+      }
+
+      // Try to recover by calling this function.
+      return true;
+    }
+
+    R.clear();
+  }
+
+  return false;
+}
+
+/// Attempt to recover from ill-formed use of a non-dependent operator in a
+/// template, where the non-dependent operator was declared after the template
+/// was defined.
+///
+/// Returns true if a viable candidate was found and a diagnostic was issued.
+static bool
+DiagnoseTwoPhaseOperatorLookup(Sema &SemaRef, OverloadedOperatorKind Op,
+                               SourceLocation OpLoc,
+                               llvm::ArrayRef<Expr *> Args) {
+  DeclarationName OpName =
+    SemaRef.Context.DeclarationNames.getCXXOperatorName(Op);
+  LookupResult R(SemaRef, OpName, OpLoc, Sema::LookupOperatorName);
+  return DiagnoseTwoPhaseLookup(SemaRef, OpLoc, CXXScopeSpec(), R,
+                                /*ExplicitTemplateArgs=*/0, Args);
+}
+
+namespace {
+// Callback to limit the allowed keywords and to only accept typo corrections
+// that are keywords or whose decls refer to functions (or template functions)
+// that accept the given number of arguments.
+class RecoveryCallCCC : public CorrectionCandidateCallback {
+ public:
+  RecoveryCallCCC(Sema &SemaRef, unsigned NumArgs, bool HasExplicitTemplateArgs)
+      : NumArgs(NumArgs), HasExplicitTemplateArgs(HasExplicitTemplateArgs) {
+    WantTypeSpecifiers = SemaRef.getLangOpts().CPlusPlus;
+    WantRemainingKeywords = false;
+  }
+
+  virtual bool ValidateCandidate(const TypoCorrection &candidate) {
+    if (!candidate.getCorrectionDecl())
+      return candidate.isKeyword();
+
+    for (TypoCorrection::const_decl_iterator DI = candidate.begin(),
+           DIEnd = candidate.end(); DI != DIEnd; ++DI) {
+      FunctionDecl *FD = 0;
+      NamedDecl *ND = (*DI)->getUnderlyingDecl();
+      if (FunctionTemplateDecl *FTD = dyn_cast<FunctionTemplateDecl>(ND))
+        FD = FTD->getTemplatedDecl();
+      if (!HasExplicitTemplateArgs && !FD) {
+        if (!(FD = dyn_cast<FunctionDecl>(ND)) && isa<ValueDecl>(ND)) {
+          // If the Decl is neither a function nor a template function,
+          // determine if it is a pointer or reference to a function. If so,
+          // check against the number of arguments expected for the pointee.
+          QualType ValType = cast<ValueDecl>(ND)->getType();
+          if (ValType->isAnyPointerType() || ValType->isReferenceType())
+            ValType = ValType->getPointeeType();
+          if (const FunctionProtoType *FPT = ValType->getAs<FunctionProtoType>())
+            if (FPT->getNumArgs() == NumArgs)
+              return true;
+        }
+      }
+      if (FD && FD->getNumParams() >= NumArgs &&
+          FD->getMinRequiredArguments() <= NumArgs)
+        return true;
+    }
+    return false;
+  }
+
+ private:
+  unsigned NumArgs;
+  bool HasExplicitTemplateArgs;
+};
+
+// Callback that effectively disabled typo correction
+class NoTypoCorrectionCCC : public CorrectionCandidateCallback {
+ public:
+  NoTypoCorrectionCCC() {
+    WantTypeSpecifiers = false;
+    WantExpressionKeywords = false;
+    WantCXXNamedCasts = false;
+    WantRemainingKeywords = false;
+  }
+
+  virtual bool ValidateCandidate(const TypoCorrection &candidate) {
+    return false;
+  }
+};
+}
+
+/// Attempts to recover from a call where no functions were found.
+///
+/// Returns true if new candidates were found.
+static ExprResult
+BuildRecoveryCallExpr(Sema &SemaRef, Scope *S, Expr *Fn,
+                      UnresolvedLookupExpr *ULE,
+                      SourceLocation LParenLoc,
+                      llvm::MutableArrayRef<Expr *> Args,
+                      SourceLocation RParenLoc,
+                      bool EmptyLookup, bool AllowTypoCorrection) {
+
+  CXXScopeSpec SS;
+  SS.Adopt(ULE->getQualifierLoc());
+  SourceLocation TemplateKWLoc = ULE->getTemplateKeywordLoc();
+
+  TemplateArgumentListInfo TABuffer;
+  TemplateArgumentListInfo *ExplicitTemplateArgs = 0;
+  if (ULE->hasExplicitTemplateArgs()) {
+    ULE->copyTemplateArgumentsInto(TABuffer);
+    ExplicitTemplateArgs = &TABuffer;
+  }
+
+  LookupResult R(SemaRef, ULE->getName(), ULE->getNameLoc(),
+                 Sema::LookupOrdinaryName);
+  RecoveryCallCCC Validator(SemaRef, Args.size(), ExplicitTemplateArgs != 0);
+  NoTypoCorrectionCCC RejectAll;
+  CorrectionCandidateCallback *CCC = AllowTypoCorrection ?
+      (CorrectionCandidateCallback*)&Validator :
+      (CorrectionCandidateCallback*)&RejectAll;
+  if (!DiagnoseTwoPhaseLookup(SemaRef, Fn->getExprLoc(), SS, R,
+                              ExplicitTemplateArgs, Args) &&
+      (!EmptyLookup ||
+       SemaRef.DiagnoseEmptyLookup(S, SS, R, *CCC,
+                                   ExplicitTemplateArgs, Args)))
+    return ExprError();
+
+  assert(!R.empty() && "lookup results empty despite recovery");
+
+  // Build an implicit member call if appropriate.  Just drop the
+  // casts and such from the call, we don't really care.
+  ExprResult NewFn = ExprError();
+  if ((*R.begin())->isCXXClassMember())
+    NewFn = SemaRef.BuildPossibleImplicitMemberExpr(SS, TemplateKWLoc,
+                                                    R, ExplicitTemplateArgs);
+  else if (ExplicitTemplateArgs || TemplateKWLoc.isValid())
+    NewFn = SemaRef.BuildTemplateIdExpr(SS, TemplateKWLoc, R, false,
+                                        ExplicitTemplateArgs);
+  else
+    NewFn = SemaRef.BuildDeclarationNameExpr(SS, R, false);
+
+  if (NewFn.isInvalid())
+    return ExprError();
+
+  // This shouldn't cause an infinite loop because we're giving it
+  // an expression with viable lookup results, which should never
+  // end up here.
+  return SemaRef.ActOnCallExpr(/*Scope*/ 0, NewFn.take(), LParenLoc,
+                               MultiExprArg(Args.data(), Args.size()),
+                               RParenLoc);
+}
+
+/// ResolveOverloadedCallFn - Given the call expression that calls Fn
+/// (which eventually refers to the declaration Func) and the call
+/// arguments Args/NumArgs, attempt to resolve the function call down
+/// to a specific function. If overload resolution succeeds, returns
+/// the function declaration produced by overload
+/// resolution. Otherwise, emits diagnostics, deletes all of the
+/// arguments and Fn, and returns NULL.
+ExprResult
+Sema::BuildOverloadedCallExpr(Scope *S, Expr *Fn, UnresolvedLookupExpr *ULE,
+                              SourceLocation LParenLoc,
+                              Expr **Args, unsigned NumArgs,
+                              SourceLocation RParenLoc,
+                              Expr *ExecConfig,
+                              bool AllowTypoCorrection) {
+#ifndef NDEBUG
+  if (ULE->requiresADL()) {
+    // To do ADL, we must have found an unqualified name.
+    assert(!ULE->getQualifier() && "qualified name with ADL");
+
+    // We don't perform ADL for implicit declarations of builtins.
+    // Verify that this was correctly set up.
+    FunctionDecl *F;
+    if (ULE->decls_begin() + 1 == ULE->decls_end() &&
+        (F = dyn_cast<FunctionDecl>(*ULE->decls_begin())) &&
+        F->getBuiltinID() && F->isImplicit())
+      llvm_unreachable("performing ADL for builtin");
+
+    // We don't perform ADL in C.
+    assert(getLangOpts().CPlusPlus && "ADL enabled in C");
+  } else
+    assert(!ULE->isStdAssociatedNamespace() &&
+           "std is associated namespace but not doing ADL");
+#endif
+
+  UnbridgedCastsSet UnbridgedCasts;
+  if (checkArgPlaceholdersForOverload(*this, Args, NumArgs, UnbridgedCasts))
+    return ExprError();
+
+  OverloadCandidateSet CandidateSet(Fn->getExprLoc());
+
+  // Add the functions denoted by the callee to the set of candidate
+  // functions, including those from argument-dependent lookup.
+  AddOverloadedCallCandidates(ULE, llvm::makeArrayRef(Args, NumArgs),
+                              CandidateSet);
+
+  // If we found nothing, try to recover.
+  // BuildRecoveryCallExpr diagnoses the error itself, so we just bail
+  // out if it fails.
+  if (CandidateSet.empty()) {
+    // In Microsoft mode, if we are inside a template class member function then
+    // create a type dependent CallExpr. The goal is to postpone name lookup
+    // to instantiation time to be able to search into type dependent base
+    // classes.
+    if (getLangOpts().MicrosoftMode && CurContext->isDependentContext() && 
+        (isa<FunctionDecl>(CurContext) || isa<CXXRecordDecl>(CurContext))) {
+      CallExpr *CE = new (Context) CallExpr(Context, Fn, Args, NumArgs,
+                                          Context.DependentTy, VK_RValue,
+                                          RParenLoc);
+      CE->setTypeDependent(true);
+      return Owned(CE);
+    }
+    return BuildRecoveryCallExpr(*this, S, Fn, ULE, LParenLoc,
+                                 llvm::MutableArrayRef<Expr *>(Args, NumArgs),
+                                 RParenLoc, /*EmptyLookup=*/true,
+                                 AllowTypoCorrection);
+  }
+
+  UnbridgedCasts.restore();
+
+  OverloadCandidateSet::iterator Best;
+  switch (CandidateSet.BestViableFunction(*this, Fn->getLocStart(), Best)) {
+  case OR_Success: {
+    FunctionDecl *FDecl = Best->Function;
+    MarkFunctionReferenced(Fn->getExprLoc(), FDecl);
+    CheckUnresolvedLookupAccess(ULE, Best->FoundDecl);
+    DiagnoseUseOfDecl(FDecl, ULE->getNameLoc());
+    Fn = FixOverloadedFunctionReference(Fn, Best->FoundDecl, FDecl);
+    return BuildResolvedCallExpr(Fn, FDecl, LParenLoc, Args, NumArgs, RParenLoc,
+                                 ExecConfig);
+  }
+
+  case OR_No_Viable_Function: {
+    // Try to recover by looking for viable functions which the user might
+    // have meant to call.
+    ExprResult Recovery = BuildRecoveryCallExpr(*this, S, Fn, ULE, LParenLoc,
+                                  llvm::MutableArrayRef<Expr *>(Args, NumArgs),
+                                                RParenLoc,
+                                                /*EmptyLookup=*/false,
+                                                AllowTypoCorrection);
+    if (!Recovery.isInvalid())
+      return Recovery;
+
+    Diag(Fn->getLocStart(),
+         diag::err_ovl_no_viable_function_in_call)
+      << ULE->getName() << Fn->getSourceRange();
+    CandidateSet.NoteCandidates(*this, OCD_AllCandidates,
+                                llvm::makeArrayRef(Args, NumArgs));
+    break;
+  }
+
+  case OR_Ambiguous:
+    Diag(Fn->getLocStart(), diag::err_ovl_ambiguous_call)
+      << ULE->getName() << Fn->getSourceRange();
+    CandidateSet.NoteCandidates(*this, OCD_ViableCandidates,
+                                llvm::makeArrayRef(Args, NumArgs));
+    break;
+
+  case OR_Deleted:
+    {
+      Diag(Fn->getLocStart(), diag::err_ovl_deleted_call)
+        << Best->Function->isDeleted()
+        << ULE->getName()
+        << getDeletedOrUnavailableSuffix(Best->Function)
+        << Fn->getSourceRange();
+      CandidateSet.NoteCandidates(*this, OCD_AllCandidates,
+                                  llvm::makeArrayRef(Args, NumArgs));
+
+      // We emitted an error for the unvailable/deleted function call but keep
+      // the call in the AST.
+      FunctionDecl *FDecl = Best->Function;
+      Fn = FixOverloadedFunctionReference(Fn, Best->FoundDecl, FDecl);
+      return BuildResolvedCallExpr(Fn, FDecl, LParenLoc, Args, NumArgs,
+                                   RParenLoc, ExecConfig);
+    }
+  }
+
+  // Overload resolution failed.
+  return ExprError();
+}
+
+static bool IsOverloaded(const UnresolvedSetImpl &Functions) {
+  return Functions.size() > 1 ||
+    (Functions.size() == 1 && isa<FunctionTemplateDecl>(*Functions.begin()));
+}
+
+/// \brief Create a unary operation that may resolve to an overloaded
+/// operator.
+///
+/// \param OpLoc The location of the operator itself (e.g., '*').
+///
+/// \param OpcIn The UnaryOperator::Opcode that describes this
+/// operator.
+///
+/// \param Functions The set of non-member functions that will be
+/// considered by overload resolution. The caller needs to build this
+/// set based on the context using, e.g.,
+/// LookupOverloadedOperatorName() and ArgumentDependentLookup(). This
+/// set should not contain any member functions; those will be added
+/// by CreateOverloadedUnaryOp().
+///
+/// \param input The input argument.
+ExprResult
+Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, unsigned OpcIn,
+                              const UnresolvedSetImpl &Fns,
+                              Expr *Input) {
+  UnaryOperator::Opcode Opc = static_cast<UnaryOperator::Opcode>(OpcIn);
+
+  OverloadedOperatorKind Op = UnaryOperator::getOverloadedOperator(Opc);
+  assert(Op != OO_None && "Invalid opcode for overloaded unary operator");
+  DeclarationName OpName = Context.DeclarationNames.getCXXOperatorName(Op);
+  // TODO: provide better source location info.
+  DeclarationNameInfo OpNameInfo(OpName, OpLoc);
+
+  if (checkPlaceholderForOverload(*this, Input))
+    return ExprError();
+
+  Expr *Args[2] = { Input, 0 };
+  unsigned NumArgs = 1;
+
+  // For post-increment and post-decrement, add the implicit '0' as
+  // the second argument, so that we know this is a post-increment or
+  // post-decrement.
+  if (Opc == UO_PostInc || Opc == UO_PostDec) {
+    llvm::APSInt Zero(Context.getTypeSize(Context.IntTy), false);
+    Args[1] = IntegerLiteral::Create(Context, Zero, Context.IntTy,
+                                     SourceLocation());
+    NumArgs = 2;
+  }
+
+  if (Input->isTypeDependent()) {
+    if (Fns.empty())
+      return Owned(new (Context) UnaryOperator(Input,
+                                               Opc,
+                                               Context.DependentTy,
+                                               VK_RValue, OK_Ordinary,
+                                               OpLoc));
+
+    CXXRecordDecl *NamingClass = 0; // because lookup ignores member operators
+    UnresolvedLookupExpr *Fn
+      = UnresolvedLookupExpr::Create(Context, NamingClass,
+                                     NestedNameSpecifierLoc(), OpNameInfo,
+                                     /*ADL*/ true, IsOverloaded(Fns),
+                                     Fns.begin(), Fns.end());
+    return Owned(new (Context) CXXOperatorCallExpr(Context, Op, Fn,
+                                                  &Args[0], NumArgs,
+                                                   Context.DependentTy,
+                                                   VK_RValue,
+                                                   OpLoc));
+  }
+
+  // Build an empty overload set.
+  OverloadCandidateSet CandidateSet(OpLoc);
+
+  // Add the candidates from the given function set.
+  AddFunctionCandidates(Fns, llvm::makeArrayRef(Args, NumArgs), CandidateSet,
+                        false);
+
+  // Add operator candidates that are member functions.
+  AddMemberOperatorCandidates(Op, OpLoc, &Args[0], NumArgs, CandidateSet);
+
+  // Add candidates from ADL.
+  AddArgumentDependentLookupCandidates(OpName, /*Operator*/ true,
+                                       OpLoc, llvm::makeArrayRef(Args, NumArgs),
+                                       /*ExplicitTemplateArgs*/ 0,
+                                       CandidateSet);
+
+  // Add builtin operator candidates.
+  AddBuiltinOperatorCandidates(Op, OpLoc, &Args[0], NumArgs, CandidateSet);
+
+  bool HadMultipleCandidates = (CandidateSet.size() > 1);
+
+  // Perform overload resolution.
+  OverloadCandidateSet::iterator Best;
+  switch (CandidateSet.BestViableFunction(*this, OpLoc, Best)) {
+  case OR_Success: {
+    // We found a built-in operator or an overloaded operator.
+    FunctionDecl *FnDecl = Best->Function;
+
+    if (FnDecl) {
+      // We matched an overloaded operator. Build a call to that
+      // operator.
+
+      MarkFunctionReferenced(OpLoc, FnDecl);
+
+      // Convert the arguments.
+      if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(FnDecl)) {
+        CheckMemberOperatorAccess(OpLoc, Args[0], 0, Best->FoundDecl);
+
+        ExprResult InputRes =
+          PerformObjectArgumentInitialization(Input, /*Qualifier=*/0,
+                                              Best->FoundDecl, Method);
+        if (InputRes.isInvalid())
+          return ExprError();
+        Input = InputRes.take();
+      } else {
+        // Convert the arguments.
+        ExprResult InputInit
+          = PerformCopyInitialization(InitializedEntity::InitializeParameter(
+                                                      Context,
+                                                      FnDecl->getParamDecl(0)),
+                                      SourceLocation(),
+                                      Input);
+        if (InputInit.isInvalid())
+          return ExprError();
+        Input = InputInit.take();
+      }
+
+      DiagnoseUseOfDecl(Best->FoundDecl, OpLoc);
+
+      // Determine the result type.
+      QualType ResultTy = FnDecl->getResultType();
+      ExprValueKind VK = Expr::getValueKindForType(ResultTy);
+      ResultTy = ResultTy.getNonLValueExprType(Context);
+
+      // Build the actual expression node.
+      ExprResult FnExpr = CreateFunctionRefExpr(*this, FnDecl,
+                                                HadMultipleCandidates, OpLoc);
+      if (FnExpr.isInvalid())
+        return ExprError();
+
+      Args[0] = Input;
+      CallExpr *TheCall =
+        new (Context) CXXOperatorCallExpr(Context, Op, FnExpr.take(),
+                                          Args, NumArgs, ResultTy, VK, OpLoc);
+
+      if (CheckCallReturnType(FnDecl->getResultType(), OpLoc, TheCall,
+                              FnDecl))
+        return ExprError();
+
+      return MaybeBindToTemporary(TheCall);
+    } else {
+      // We matched a built-in operator. Convert the arguments, then
+      // break out so that we will build the appropriate built-in
+      // operator node.
+      ExprResult InputRes =
+        PerformImplicitConversion(Input, Best->BuiltinTypes.ParamTypes[0],
+                                  Best->Conversions[0], AA_Passing);
+      if (InputRes.isInvalid())
+        return ExprError();
+      Input = InputRes.take();
+      break;
+    }
+  }
+
+  case OR_No_Viable_Function:
+    // This is an erroneous use of an operator which can be overloaded by
+    // a non-member function. Check for non-member operators which were
+    // defined too late to be candidates.
+    if (DiagnoseTwoPhaseOperatorLookup(*this, Op, OpLoc,
+                                       llvm::makeArrayRef(Args, NumArgs)))
+      // FIXME: Recover by calling the found function.
+      return ExprError();
+
+    // No viable function; fall through to handling this as a
+    // built-in operator, which will produce an error message for us.
+    break;
+
+  case OR_Ambiguous:
+    Diag(OpLoc,  diag::err_ovl_ambiguous_oper_unary)
+        << UnaryOperator::getOpcodeStr(Opc)
+        << Input->getType()
+        << Input->getSourceRange();
+    CandidateSet.NoteCandidates(*this, OCD_ViableCandidates,
+                                llvm::makeArrayRef(Args, NumArgs),
+                                UnaryOperator::getOpcodeStr(Opc), OpLoc);
+    return ExprError();
+
+  case OR_Deleted:
+    Diag(OpLoc, diag::err_ovl_deleted_oper)
+      << Best->Function->isDeleted()
+      << UnaryOperator::getOpcodeStr(Opc)
+      << getDeletedOrUnavailableSuffix(Best->Function)
+      << Input->getSourceRange();
+    CandidateSet.NoteCandidates(*this, OCD_AllCandidates,
+                                llvm::makeArrayRef(Args, NumArgs),
+                                UnaryOperator::getOpcodeStr(Opc), OpLoc);
+    return ExprError();
+  }
+
+  // Either we found no viable overloaded operator or we matched a
+  // built-in operator. In either case, fall through to trying to
+  // build a built-in operation.
+  return CreateBuiltinUnaryOp(OpLoc, Opc, Input);
+}
+
+/// \brief Create a binary operation that may resolve to an overloaded
+/// operator.
+///
+/// \param OpLoc The location of the operator itself (e.g., '+').
+///
+/// \param OpcIn The BinaryOperator::Opcode that describes this
+/// operator.
+///
+/// \param Functions The set of non-member functions that will be
+/// considered by overload resolution. The caller needs to build this
+/// set based on the context using, e.g.,
+/// LookupOverloadedOperatorName() and ArgumentDependentLookup(). This
+/// set should not contain any member functions; those will be added
+/// by CreateOverloadedBinOp().
+///
+/// \param LHS Left-hand argument.
+/// \param RHS Right-hand argument.
+ExprResult
+Sema::CreateOverloadedBinOp(SourceLocation OpLoc,
+                            unsigned OpcIn,
+                            const UnresolvedSetImpl &Fns,
+                            Expr *LHS, Expr *RHS) {
+  Expr *Args[2] = { LHS, RHS };
+  LHS=RHS=0; //Please use only Args instead of LHS/RHS couple
+
+  BinaryOperator::Opcode Opc = static_cast<BinaryOperator::Opcode>(OpcIn);
+  OverloadedOperatorKind Op = BinaryOperator::getOverloadedOperator(Opc);
+  DeclarationName OpName = Context.DeclarationNames.getCXXOperatorName(Op);
+
+  // If either side is type-dependent, create an appropriate dependent
+  // expression.
+  if (Args[0]->isTypeDependent() || Args[1]->isTypeDependent()) {
+    if (Fns.empty()) {
+      // If there are no functions to store, just build a dependent
+      // BinaryOperator or CompoundAssignment.
+      if (Opc <= BO_Assign || Opc > BO_OrAssign)
+        return Owned(new (Context) BinaryOperator(Args[0], Args[1], Opc,
+                                                  Context.DependentTy,
+                                                  VK_RValue, OK_Ordinary,
+                                                  OpLoc));
+
+      return Owned(new (Context) CompoundAssignOperator(Args[0], Args[1], Opc,
+                                                        Context.DependentTy,
+                                                        VK_LValue,
+                                                        OK_Ordinary,
+                                                        Context.DependentTy,
+                                                        Context.DependentTy,
+                                                        OpLoc));
+    }
+
+    // FIXME: save results of ADL from here?
+    CXXRecordDecl *NamingClass = 0; // because lookup ignores member operators
+    // TODO: provide better source location info in DNLoc component.
+    DeclarationNameInfo OpNameInfo(OpName, OpLoc);
+    UnresolvedLookupExpr *Fn
+      = UnresolvedLookupExpr::Create(Context, NamingClass, 
+                                     NestedNameSpecifierLoc(), OpNameInfo, 
+                                     /*ADL*/ true, IsOverloaded(Fns),
+                                     Fns.begin(), Fns.end());
+    return Owned(new (Context) CXXOperatorCallExpr(Context, Op, Fn,
+                                                   Args, 2,
+                                                   Context.DependentTy,
+                                                   VK_RValue,
+                                                   OpLoc));
+  }
+
+  // Always do placeholder-like conversions on the RHS.
+  if (checkPlaceholderForOverload(*this, Args[1]))
+    return ExprError();
+
+  // Do placeholder-like conversion on the LHS; note that we should
+  // not get here with a PseudoObject LHS.
+  assert(Args[0]->getObjectKind() != OK_ObjCProperty);
+  if (checkPlaceholderForOverload(*this, Args[0]))
+    return ExprError();
+
+  // If this is the assignment operator, we only perform overload resolution
+  // if the left-hand side is a class or enumeration type. This is actually
+  // a hack. The standard requires that we do overload resolution between the
+  // various built-in candidates, but as DR507 points out, this can lead to
+  // problems. So we do it this way, which pretty much follows what GCC does.
+  // Note that we go the traditional code path for compound assignment forms.
+  if (Opc == BO_Assign && !Args[0]->getType()->isOverloadableType())
+    return CreateBuiltinBinOp(OpLoc, Opc, Args[0], Args[1]);
+
+  // If this is the .* operator, which is not overloadable, just
+  // create a built-in binary operator.
+  if (Opc == BO_PtrMemD)
+    return CreateBuiltinBinOp(OpLoc, Opc, Args[0], Args[1]);
+
+  // Build an empty overload set.
+  OverloadCandidateSet CandidateSet(OpLoc);
+
+  // Add the candidates from the given function set.
+  AddFunctionCandidates(Fns, Args, CandidateSet, false);
+
+  // Add operator candidates that are member functions.
+  AddMemberOperatorCandidates(Op, OpLoc, Args, 2, CandidateSet);
+
+  // Add candidates from ADL.
+  AddArgumentDependentLookupCandidates(OpName, /*Operator*/ true,
+                                       OpLoc, Args,
+                                       /*ExplicitTemplateArgs*/ 0,
+                                       CandidateSet);
+
+  // Add builtin operator candidates.
+  AddBuiltinOperatorCandidates(Op, OpLoc, Args, 2, CandidateSet);
+
+  bool HadMultipleCandidates = (CandidateSet.size() > 1);
+
+  // Perform overload resolution.
+  OverloadCandidateSet::iterator Best;
+  switch (CandidateSet.BestViableFunction(*this, OpLoc, Best)) {
+    case OR_Success: {
+      // We found a built-in operator or an overloaded operator.
+      FunctionDecl *FnDecl = Best->Function;
+
+      if (FnDecl) {
+        // We matched an overloaded operator. Build a call to that
+        // operator.
+
+        MarkFunctionReferenced(OpLoc, FnDecl);
+
+        // Convert the arguments.
+        if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(FnDecl)) {
+          // Best->Access is only meaningful for class members.
+          CheckMemberOperatorAccess(OpLoc, Args[0], Args[1], Best->FoundDecl);
+
+          ExprResult Arg1 =
+            PerformCopyInitialization(
+              InitializedEntity::InitializeParameter(Context,
+                                                     FnDecl->getParamDecl(0)),
+              SourceLocation(), Owned(Args[1]));
+          if (Arg1.isInvalid())
+            return ExprError();
+
+          ExprResult Arg0 =
+            PerformObjectArgumentInitialization(Args[0], /*Qualifier=*/0,
+                                                Best->FoundDecl, Method);
+          if (Arg0.isInvalid())
+            return ExprError();
+          Args[0] = Arg0.takeAs<Expr>();
+          Args[1] = RHS = Arg1.takeAs<Expr>();
+        } else {
+          // Convert the arguments.
+          ExprResult Arg0 = PerformCopyInitialization(
+            InitializedEntity::InitializeParameter(Context,
+                                                   FnDecl->getParamDecl(0)),
+            SourceLocation(), Owned(Args[0]));
+          if (Arg0.isInvalid())
+            return ExprError();
+
+          ExprResult Arg1 =
+            PerformCopyInitialization(
+              InitializedEntity::InitializeParameter(Context,
+                                                     FnDecl->getParamDecl(1)),
+              SourceLocation(), Owned(Args[1]));
+          if (Arg1.isInvalid())
+            return ExprError();
+          Args[0] = LHS = Arg0.takeAs<Expr>();
+          Args[1] = RHS = Arg1.takeAs<Expr>();
+        }
+
+        DiagnoseUseOfDecl(Best->FoundDecl, OpLoc);
+
+        // Determine the result type.
+        QualType ResultTy = FnDecl->getResultType();
+        ExprValueKind VK = Expr::getValueKindForType(ResultTy);
+        ResultTy = ResultTy.getNonLValueExprType(Context);
+
+        // Build the actual expression node.
+        ExprResult FnExpr = CreateFunctionRefExpr(*this, FnDecl,
+                                                  HadMultipleCandidates, OpLoc);
+        if (FnExpr.isInvalid())
+          return ExprError();
+
+        CXXOperatorCallExpr *TheCall =
+          new (Context) CXXOperatorCallExpr(Context, Op, FnExpr.take(),
+                                            Args, 2, ResultTy, VK, OpLoc);
+
+        if (CheckCallReturnType(FnDecl->getResultType(), OpLoc, TheCall,
+                                FnDecl))
+          return ExprError();
+
+        return MaybeBindToTemporary(TheCall);
+      } else {
+        // We matched a built-in operator. Convert the arguments, then
+        // break out so that we will build the appropriate built-in
+        // operator node.
+        ExprResult ArgsRes0 =
+          PerformImplicitConversion(Args[0], Best->BuiltinTypes.ParamTypes[0],
+                                    Best->Conversions[0], AA_Passing);
+        if (ArgsRes0.isInvalid())
+          return ExprError();
+        Args[0] = ArgsRes0.take();
+
+        ExprResult ArgsRes1 =
+          PerformImplicitConversion(Args[1], Best->BuiltinTypes.ParamTypes[1],
+                                    Best->Conversions[1], AA_Passing);
+        if (ArgsRes1.isInvalid())
+          return ExprError();
+        Args[1] = ArgsRes1.take();
+        break;
+      }
+    }
+
+    case OR_No_Viable_Function: {
+      // C++ [over.match.oper]p9:
+      //   If the operator is the operator , [...] and there are no
+      //   viable functions, then the operator is assumed to be the
+      //   built-in operator and interpreted according to clause 5.
+      if (Opc == BO_Comma)
+        break;
+
+      // For class as left operand for assignment or compound assigment
+      // operator do not fall through to handling in built-in, but report that
+      // no overloaded assignment operator found
+      ExprResult Result = ExprError();
+      if (Args[0]->getType()->isRecordType() &&
+          Opc >= BO_Assign && Opc <= BO_OrAssign) {
+        Diag(OpLoc,  diag::err_ovl_no_viable_oper)
+             << BinaryOperator::getOpcodeStr(Opc)
+             << Args[0]->getSourceRange() << Args[1]->getSourceRange();
+      } else {
+        // This is an erroneous use of an operator which can be overloaded by
+        // a non-member function. Check for non-member operators which were
+        // defined too late to be candidates.
+        if (DiagnoseTwoPhaseOperatorLookup(*this, Op, OpLoc, Args))
+          // FIXME: Recover by calling the found function.
+          return ExprError();
+
+        // No viable function; try to create a built-in operation, which will
+        // produce an error. Then, show the non-viable candidates.
+        Result = CreateBuiltinBinOp(OpLoc, Opc, Args[0], Args[1]);
+      }
+      assert(Result.isInvalid() &&
+             "C++ binary operator overloading is missing candidates!");
+      if (Result.isInvalid())
+        CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Args,
+                                    BinaryOperator::getOpcodeStr(Opc), OpLoc);
+      return move(Result);
+    }
+
+    case OR_Ambiguous:
+      Diag(OpLoc,  diag::err_ovl_ambiguous_oper_binary)
+          << BinaryOperator::getOpcodeStr(Opc)
+          << Args[0]->getType() << Args[1]->getType()
+          << Args[0]->getSourceRange() << Args[1]->getSourceRange();
+      CandidateSet.NoteCandidates(*this, OCD_ViableCandidates, Args,
+                                  BinaryOperator::getOpcodeStr(Opc), OpLoc);
+      return ExprError();
+
+    case OR_Deleted:
+      if (isImplicitlyDeleted(Best->Function)) {
+        CXXMethodDecl *Method = cast<CXXMethodDecl>(Best->Function);
+        Diag(OpLoc, diag::err_ovl_deleted_special_oper)
+          << getSpecialMember(Method)
+          << BinaryOperator::getOpcodeStr(Opc)
+          << getDeletedOrUnavailableSuffix(Best->Function);
+
+        if (getSpecialMember(Method) != CXXInvalid) {
+          // The user probably meant to call this special member. Just
+          // explain why it's deleted.
+          NoteDeletedFunction(Method);
+          return ExprError();
+        }
+      } else {
+        Diag(OpLoc, diag::err_ovl_deleted_oper)
+          << Best->Function->isDeleted()
+          << BinaryOperator::getOpcodeStr(Opc)
+          << getDeletedOrUnavailableSuffix(Best->Function)
+          << Args[0]->getSourceRange() << Args[1]->getSourceRange();
+      }
+      CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Args,
+                                  BinaryOperator::getOpcodeStr(Opc), OpLoc);
+      return ExprError();
+  }
+
+  // We matched a built-in operator; build it.
+  return CreateBuiltinBinOp(OpLoc, Opc, Args[0], Args[1]);
+}
+
+ExprResult
+Sema::CreateOverloadedArraySubscriptExpr(SourceLocation LLoc,
+                                         SourceLocation RLoc,
+                                         Expr *Base, Expr *Idx) {
+  Expr *Args[2] = { Base, Idx };
+  DeclarationName OpName =
+      Context.DeclarationNames.getCXXOperatorName(OO_Subscript);
+
+  // If either side is type-dependent, create an appropriate dependent
+  // expression.
+  if (Args[0]->isTypeDependent() || Args[1]->isTypeDependent()) {
+
+    CXXRecordDecl *NamingClass = 0; // because lookup ignores member operators
+    // CHECKME: no 'operator' keyword?
+    DeclarationNameInfo OpNameInfo(OpName, LLoc);
+    OpNameInfo.setCXXOperatorNameRange(SourceRange(LLoc, RLoc));
+    UnresolvedLookupExpr *Fn
+      = UnresolvedLookupExpr::Create(Context, NamingClass,
+                                     NestedNameSpecifierLoc(), OpNameInfo,
+                                     /*ADL*/ true, /*Overloaded*/ false,
+                                     UnresolvedSetIterator(),
+                                     UnresolvedSetIterator());
+    // Can't add any actual overloads yet
+
+    return Owned(new (Context) CXXOperatorCallExpr(Context, OO_Subscript, Fn,
+                                                   Args, 2,
+                                                   Context.DependentTy,
+                                                   VK_RValue,
+                                                   RLoc));
+  }
+
+  // Handle placeholders on both operands.
+  if (checkPlaceholderForOverload(*this, Args[0]))
+    return ExprError();
+  if (checkPlaceholderForOverload(*this, Args[1]))
+    return ExprError();
+
+  // Build an empty overload set.
+  OverloadCandidateSet CandidateSet(LLoc);
+
+  // Subscript can only be overloaded as a member function.
+
+  // Add operator candidates that are member functions.
+  AddMemberOperatorCandidates(OO_Subscript, LLoc, Args, 2, CandidateSet);
+
+  // Add builtin operator candidates.
+  AddBuiltinOperatorCandidates(OO_Subscript, LLoc, Args, 2, CandidateSet);
+
+  bool HadMultipleCandidates = (CandidateSet.size() > 1);
+
+  // Perform overload resolution.
+  OverloadCandidateSet::iterator Best;
+  switch (CandidateSet.BestViableFunction(*this, LLoc, Best)) {
+    case OR_Success: {
+      // We found a built-in operator or an overloaded operator.
+      FunctionDecl *FnDecl = Best->Function;
+
+      if (FnDecl) {
+        // We matched an overloaded operator. Build a call to that
+        // operator.
+
+        MarkFunctionReferenced(LLoc, FnDecl);
+
+        CheckMemberOperatorAccess(LLoc, Args[0], Args[1], Best->FoundDecl);
+        DiagnoseUseOfDecl(Best->FoundDecl, LLoc);
+
+        // Convert the arguments.
+        CXXMethodDecl *Method = cast<CXXMethodDecl>(FnDecl);
+        ExprResult Arg0 =
+          PerformObjectArgumentInitialization(Args[0], /*Qualifier=*/0,
+                                              Best->FoundDecl, Method);
+        if (Arg0.isInvalid())
+          return ExprError();
+        Args[0] = Arg0.take();
+
+        // Convert the arguments.
+        ExprResult InputInit
+          = PerformCopyInitialization(InitializedEntity::InitializeParameter(
+                                                      Context,
+                                                      FnDecl->getParamDecl(0)),
+                                      SourceLocation(),
+                                      Owned(Args[1]));
+        if (InputInit.isInvalid())
+          return ExprError();
+
+        Args[1] = InputInit.takeAs<Expr>();
+
+        // Determine the result type
+        QualType ResultTy = FnDecl->getResultType();
+        ExprValueKind VK = Expr::getValueKindForType(ResultTy);
+        ResultTy = ResultTy.getNonLValueExprType(Context);
+
+        // Build the actual expression node.
+        DeclarationNameInfo OpLocInfo(OpName, LLoc);
+        OpLocInfo.setCXXOperatorNameRange(SourceRange(LLoc, RLoc));
+        ExprResult FnExpr = CreateFunctionRefExpr(*this, FnDecl,
+                                                  HadMultipleCandidates,
+                                                  OpLocInfo.getLoc(),
+                                                  OpLocInfo.getInfo());
+        if (FnExpr.isInvalid())
+          return ExprError();
+
+        CXXOperatorCallExpr *TheCall =
+          new (Context) CXXOperatorCallExpr(Context, OO_Subscript,
+                                            FnExpr.take(), Args, 2,
+                                            ResultTy, VK, RLoc);
+
+        if (CheckCallReturnType(FnDecl->getResultType(), LLoc, TheCall,
+                                FnDecl))
+          return ExprError();
+
+        return MaybeBindToTemporary(TheCall);
+      } else {
+        // We matched a built-in operator. Convert the arguments, then
+        // break out so that we will build the appropriate built-in
+        // operator node.
+        ExprResult ArgsRes0 =
+          PerformImplicitConversion(Args[0], Best->BuiltinTypes.ParamTypes[0],
+                                    Best->Conversions[0], AA_Passing);
+        if (ArgsRes0.isInvalid())
+          return ExprError();
+        Args[0] = ArgsRes0.take();
+
+        ExprResult ArgsRes1 =
+          PerformImplicitConversion(Args[1], Best->BuiltinTypes.ParamTypes[1],
+                                    Best->Conversions[1], AA_Passing);
+        if (ArgsRes1.isInvalid())
+          return ExprError();
+        Args[1] = ArgsRes1.take();
+
+        break;
+      }
+    }
+
+    case OR_No_Viable_Function: {
+      if (CandidateSet.empty())
+        Diag(LLoc, diag::err_ovl_no_oper)
+          << Args[0]->getType() << /*subscript*/ 0
+          << Args[0]->getSourceRange() << Args[1]->getSourceRange();
+      else
+        Diag(LLoc, diag::err_ovl_no_viable_subscript)
+          << Args[0]->getType()
+          << Args[0]->getSourceRange() << Args[1]->getSourceRange();
+      CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Args,
+                                  "[]", LLoc);
+      return ExprError();
+    }
+
+    case OR_Ambiguous:
+      Diag(LLoc,  diag::err_ovl_ambiguous_oper_binary)
+          << "[]"
+          << Args[0]->getType() << Args[1]->getType()
+          << Args[0]->getSourceRange() << Args[1]->getSourceRange();
+      CandidateSet.NoteCandidates(*this, OCD_ViableCandidates, Args,
+                                  "[]", LLoc);
+      return ExprError();
+
+    case OR_Deleted:
+      Diag(LLoc, diag::err_ovl_deleted_oper)
+        << Best->Function->isDeleted() << "[]"
+        << getDeletedOrUnavailableSuffix(Best->Function)
+        << Args[0]->getSourceRange() << Args[1]->getSourceRange();
+      CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Args,
+                                  "[]", LLoc);
+      return ExprError();
+    }
+
+  // We matched a built-in operator; build it.
+  return CreateBuiltinArraySubscriptExpr(Args[0], LLoc, Args[1], RLoc);
+}
+
+/// BuildCallToMemberFunction - Build a call to a member
+/// function. MemExpr is the expression that refers to the member
+/// function (and includes the object parameter), Args/NumArgs are the
+/// arguments to the function call (not including the object
+/// parameter). The caller needs to validate that the member
+/// expression refers to a non-static member function or an overloaded
+/// member function.
+ExprResult
+Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE,
+                                SourceLocation LParenLoc, Expr **Args,
+                                unsigned NumArgs, SourceLocation RParenLoc) {
+  assert(MemExprE->getType() == Context.BoundMemberTy ||
+         MemExprE->getType() == Context.OverloadTy);
+
+  // Dig out the member expression. This holds both the object
+  // argument and the member function we're referring to.
+  Expr *NakedMemExpr = MemExprE->IgnoreParens();
+
+  // Determine whether this is a call to a pointer-to-member function.
+  if (BinaryOperator *op = dyn_cast<BinaryOperator>(NakedMemExpr)) {
+    assert(op->getType() == Context.BoundMemberTy);
+    assert(op->getOpcode() == BO_PtrMemD || op->getOpcode() == BO_PtrMemI);
+
+    QualType fnType =
+      op->getRHS()->getType()->castAs<MemberPointerType>()->getPointeeType();
+
+    const FunctionProtoType *proto = fnType->castAs<FunctionProtoType>();
+    QualType resultType = proto->getCallResultType(Context);
+    ExprValueKind valueKind = Expr::getValueKindForType(proto->getResultType());
+
+    // Check that the object type isn't more qualified than the
+    // member function we're calling.
+    Qualifiers funcQuals = Qualifiers::fromCVRMask(proto->getTypeQuals());
+
+    QualType objectType = op->getLHS()->getType();
+    if (op->getOpcode() == BO_PtrMemI)
+      objectType = objectType->castAs<PointerType>()->getPointeeType();
+    Qualifiers objectQuals = objectType.getQualifiers();
+
+    Qualifiers difference = objectQuals - funcQuals;
+    difference.removeObjCGCAttr();
+    difference.removeAddressSpace();
+    if (difference) {
+      std::string qualsString = difference.getAsString();
+      Diag(LParenLoc, diag::err_pointer_to_member_call_drops_quals)
+        << fnType.getUnqualifiedType()
+        << qualsString
+        << (qualsString.find(' ') == std::string::npos ? 1 : 2);
+    }
+              
+    CXXMemberCallExpr *call
+      = new (Context) CXXMemberCallExpr(Context, MemExprE, Args, NumArgs,
+                                        resultType, valueKind, RParenLoc);
+
+    if (CheckCallReturnType(proto->getResultType(),
+                            op->getRHS()->getLocStart(),
+                            call, 0))
+      return ExprError();
+
+    if (ConvertArgumentsForCall(call, op, 0, proto, Args, NumArgs, RParenLoc))
+      return ExprError();
+
+    return MaybeBindToTemporary(call);
+  }
+
+  UnbridgedCastsSet UnbridgedCasts;
+  if (checkArgPlaceholdersForOverload(*this, Args, NumArgs, UnbridgedCasts))
+    return ExprError();
+
+  MemberExpr *MemExpr;
+  CXXMethodDecl *Method = 0;
+  DeclAccessPair FoundDecl = DeclAccessPair::make(0, AS_public);
+  NestedNameSpecifier *Qualifier = 0;
+  if (isa<MemberExpr>(NakedMemExpr)) {
+    MemExpr = cast<MemberExpr>(NakedMemExpr);
+    Method = cast<CXXMethodDecl>(MemExpr->getMemberDecl());
+    FoundDecl = MemExpr->getFoundDecl();
+    Qualifier = MemExpr->getQualifier();
+    UnbridgedCasts.restore();
+  } else {
+    UnresolvedMemberExpr *UnresExpr = cast<UnresolvedMemberExpr>(NakedMemExpr);
+    Qualifier = UnresExpr->getQualifier();
+
+    QualType ObjectType = UnresExpr->getBaseType();
+    Expr::Classification ObjectClassification
+      = UnresExpr->isArrow()? Expr::Classification::makeSimpleLValue()
+                            : UnresExpr->getBase()->Classify(Context);
+
+    // Add overload candidates
+    OverloadCandidateSet CandidateSet(UnresExpr->getMemberLoc());
+
+    // FIXME: avoid copy.
+    TemplateArgumentListInfo TemplateArgsBuffer, *TemplateArgs = 0;
+    if (UnresExpr->hasExplicitTemplateArgs()) {
+      UnresExpr->copyTemplateArgumentsInto(TemplateArgsBuffer);
+      TemplateArgs = &TemplateArgsBuffer;
+    }
+
+    for (UnresolvedMemberExpr::decls_iterator I = UnresExpr->decls_begin(),
+           E = UnresExpr->decls_end(); I != E; ++I) {
+
+      NamedDecl *Func = *I;
+      CXXRecordDecl *ActingDC = cast<CXXRecordDecl>(Func->getDeclContext());
+      if (isa<UsingShadowDecl>(Func))
+        Func = cast<UsingShadowDecl>(Func)->getTargetDecl();
+
+
+      // Microsoft supports direct constructor calls.
+      if (getLangOpts().MicrosoftExt && isa<CXXConstructorDecl>(Func)) {
+        AddOverloadCandidate(cast<CXXConstructorDecl>(Func), I.getPair(),
+                             llvm::makeArrayRef(Args, NumArgs), CandidateSet);
+      } else if ((Method = dyn_cast<CXXMethodDecl>(Func))) {
+        // If explicit template arguments were provided, we can't call a
+        // non-template member function.
+        if (TemplateArgs)
+          continue;
+
+        AddMethodCandidate(Method, I.getPair(), ActingDC, ObjectType,
+                           ObjectClassification,
+                           llvm::makeArrayRef(Args, NumArgs), CandidateSet,
+                           /*SuppressUserConversions=*/false);
+      } else {
+        AddMethodTemplateCandidate(cast<FunctionTemplateDecl>(Func),
+                                   I.getPair(), ActingDC, TemplateArgs,
+                                   ObjectType,  ObjectClassification,
+                                   llvm::makeArrayRef(Args, NumArgs),
+                                   CandidateSet,
+                                   /*SuppressUsedConversions=*/false);
+      }
+    }
+
+    DeclarationName DeclName = UnresExpr->getMemberName();
+
+    UnbridgedCasts.restore();
+
+    OverloadCandidateSet::iterator Best;
+    switch (CandidateSet.BestViableFunction(*this, UnresExpr->getLocStart(),
+                                            Best)) {
+    case OR_Success:
+      Method = cast<CXXMethodDecl>(Best->Function);
+      MarkFunctionReferenced(UnresExpr->getMemberLoc(), Method);
+      FoundDecl = Best->FoundDecl;
+      CheckUnresolvedMemberAccess(UnresExpr, Best->FoundDecl);
+      DiagnoseUseOfDecl(Best->FoundDecl, UnresExpr->getNameLoc());
+      break;
+
+    case OR_No_Viable_Function:
+      Diag(UnresExpr->getMemberLoc(),
+           diag::err_ovl_no_viable_member_function_in_call)
+        << DeclName << MemExprE->getSourceRange();
+      CandidateSet.NoteCandidates(*this, OCD_AllCandidates,
+                                  llvm::makeArrayRef(Args, NumArgs));
+      // FIXME: Leaking incoming expressions!
+      return ExprError();
+
+    case OR_Ambiguous:
+      Diag(UnresExpr->getMemberLoc(), diag::err_ovl_ambiguous_member_call)
+        << DeclName << MemExprE->getSourceRange();
+      CandidateSet.NoteCandidates(*this, OCD_AllCandidates,
+                                  llvm::makeArrayRef(Args, NumArgs));
+      // FIXME: Leaking incoming expressions!
+      return ExprError();
+
+    case OR_Deleted:
+      Diag(UnresExpr->getMemberLoc(), diag::err_ovl_deleted_member_call)
+        << Best->Function->isDeleted()
+        << DeclName 
+        << getDeletedOrUnavailableSuffix(Best->Function)
+        << MemExprE->getSourceRange();
+      CandidateSet.NoteCandidates(*this, OCD_AllCandidates,
+                                  llvm::makeArrayRef(Args, NumArgs));
+      // FIXME: Leaking incoming expressions!
+      return ExprError();
+    }
+
+    MemExprE = FixOverloadedFunctionReference(MemExprE, FoundDecl, Method);
+
+    // If overload resolution picked a static member, build a
+    // non-member call based on that function.
+    if (Method->isStatic()) {
+      return BuildResolvedCallExpr(MemExprE, Method, LParenLoc,
+                                   Args, NumArgs, RParenLoc);
+    }
+
+    MemExpr = cast<MemberExpr>(MemExprE->IgnoreParens());
+  }
+
+  QualType ResultType = Method->getResultType();
+  ExprValueKind VK = Expr::getValueKindForType(ResultType);
+  ResultType = ResultType.getNonLValueExprType(Context);
+
+  assert(Method && "Member call to something that isn't a method?");
+  CXXMemberCallExpr *TheCall =
+    new (Context) CXXMemberCallExpr(Context, MemExprE, Args, NumArgs,
+                                    ResultType, VK, RParenLoc);
+
+  // Check for a valid return type.
+  if (CheckCallReturnType(Method->getResultType(), MemExpr->getMemberLoc(),
+                          TheCall, Method))
+    return ExprError();
+
+  // Convert the object argument (for a non-static member function call).
+  // We only need to do this if there was actually an overload; otherwise
+  // it was done at lookup.
+  if (!Method->isStatic()) {
+    ExprResult ObjectArg =
+      PerformObjectArgumentInitialization(MemExpr->getBase(), Qualifier,
+                                          FoundDecl, Method);
+    if (ObjectArg.isInvalid())
+      return ExprError();
+    MemExpr->setBase(ObjectArg.take());
+  }
+
+  // Convert the rest of the arguments
+  const FunctionProtoType *Proto =
+    Method->getType()->getAs<FunctionProtoType>();
+  if (ConvertArgumentsForCall(TheCall, MemExpr, Method, Proto, Args, NumArgs,
+                              RParenLoc))
+    return ExprError();
+
+  DiagnoseSentinelCalls(Method, LParenLoc, Args, NumArgs);
+
+  if (CheckFunctionCall(Method, TheCall))
+    return ExprError();
+
+  if ((isa<CXXConstructorDecl>(CurContext) || 
+       isa<CXXDestructorDecl>(CurContext)) && 
+      TheCall->getMethodDecl()->isPure()) {
+    const CXXMethodDecl *MD = TheCall->getMethodDecl();
+
+    if (isa<CXXThisExpr>(MemExpr->getBase()->IgnoreParenCasts())) {
+      Diag(MemExpr->getLocStart(), 
+           diag::warn_call_to_pure_virtual_member_function_from_ctor_dtor)
+        << MD->getDeclName() << isa<CXXDestructorDecl>(CurContext)
+        << MD->getParent()->getDeclName();
+
+      Diag(MD->getLocStart(), diag::note_previous_decl) << MD->getDeclName();
+    }
+  }
+  return MaybeBindToTemporary(TheCall);
+}
+
+/// BuildCallToObjectOfClassType - Build a call to an object of class
+/// type (C++ [over.call.object]), which can end up invoking an
+/// overloaded function call operator (@c operator()) or performing a
+/// user-defined conversion on the object argument.
+ExprResult
+Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Obj,
+                                   SourceLocation LParenLoc,
+                                   Expr **Args, unsigned NumArgs,
+                                   SourceLocation RParenLoc) {
+  if (checkPlaceholderForOverload(*this, Obj))
+    return ExprError();
+  ExprResult Object = Owned(Obj);
+
+  UnbridgedCastsSet UnbridgedCasts;
+  if (checkArgPlaceholdersForOverload(*this, Args, NumArgs, UnbridgedCasts))
+    return ExprError();
+
+  assert(Object.get()->getType()->isRecordType() && "Requires object type argument");
+  const RecordType *Record = Object.get()->getType()->getAs<RecordType>();
+
+  // C++ [over.call.object]p1:
+  //  If the primary-expression E in the function call syntax
+  //  evaluates to a class object of type "cv T", then the set of
+  //  candidate functions includes at least the function call
+  //  operators of T. The function call operators of T are obtained by
+  //  ordinary lookup of the name operator() in the context of
+  //  (E).operator().
+  OverloadCandidateSet CandidateSet(LParenLoc);
+  DeclarationName OpName = Context.DeclarationNames.getCXXOperatorName(OO_Call);
+
+  if (RequireCompleteType(LParenLoc, Object.get()->getType(),
+                          PDiag(diag::err_incomplete_object_call)
+                          << Object.get()->getSourceRange()))
+    return true;
+
+  LookupResult R(*this, OpName, LParenLoc, LookupOrdinaryName);
+  LookupQualifiedName(R, Record->getDecl());
+  R.suppressDiagnostics();
+
+  for (LookupResult::iterator Oper = R.begin(), OperEnd = R.end();
+       Oper != OperEnd; ++Oper) {
+    AddMethodCandidate(Oper.getPair(), Object.get()->getType(),
+                       Object.get()->Classify(Context), Args, NumArgs, CandidateSet,
+                       /*SuppressUserConversions=*/ false);
+  }
+
+  // C++ [over.call.object]p2:
+  //   In addition, for each (non-explicit in C++0x) conversion function 
+  //   declared in T of the form
+  //
+  //        operator conversion-type-id () cv-qualifier;
+  //
+  //   where cv-qualifier is the same cv-qualification as, or a
+  //   greater cv-qualification than, cv, and where conversion-type-id
+  //   denotes the type "pointer to function of (P1,...,Pn) returning
+  //   R", or the type "reference to pointer to function of
+  //   (P1,...,Pn) returning R", or the type "reference to function
+  //   of (P1,...,Pn) returning R", a surrogate call function [...]
+  //   is also considered as a candidate function. Similarly,
+  //   surrogate call functions are added to the set of candidate
+  //   functions for each conversion function declared in an
+  //   accessible base class provided the function is not hidden
+  //   within T by another intervening declaration.
+  const UnresolvedSetImpl *Conversions
+    = cast<CXXRecordDecl>(Record->getDecl())->getVisibleConversionFunctions();
+  for (UnresolvedSetImpl::iterator I = Conversions->begin(),
+         E = Conversions->end(); I != E; ++I) {
+    NamedDecl *D = *I;
+    CXXRecordDecl *ActingContext = cast<CXXRecordDecl>(D->getDeclContext());
+    if (isa<UsingShadowDecl>(D))
+      D = cast<UsingShadowDecl>(D)->getTargetDecl();
+
+    // Skip over templated conversion functions; they aren't
+    // surrogates.
+    if (isa<FunctionTemplateDecl>(D))
+      continue;
+
+    CXXConversionDecl *Conv = cast<CXXConversionDecl>(D);
+    if (!Conv->isExplicit()) {
+      // Strip the reference type (if any) and then the pointer type (if
+      // any) to get down to what might be a function type.
+      QualType ConvType = Conv->getConversionType().getNonReferenceType();
+      if (const PointerType *ConvPtrType = ConvType->getAs<PointerType>())
+        ConvType = ConvPtrType->getPointeeType();
+
+      if (const FunctionProtoType *Proto = ConvType->getAs<FunctionProtoType>())
+      {
+        AddSurrogateCandidate(Conv, I.getPair(), ActingContext, Proto,
+                              Object.get(), llvm::makeArrayRef(Args, NumArgs),
+                              CandidateSet);
+      }
+    }
+  }
+
+  bool HadMultipleCandidates = (CandidateSet.size() > 1);
+
+  // Perform overload resolution.
+  OverloadCandidateSet::iterator Best;
+  switch (CandidateSet.BestViableFunction(*this, Object.get()->getLocStart(),
+                             Best)) {
+  case OR_Success:
+    // Overload resolution succeeded; we'll build the appropriate call
+    // below.
+    break;
+
+  case OR_No_Viable_Function:
+    if (CandidateSet.empty())
+      Diag(Object.get()->getLocStart(), diag::err_ovl_no_oper)
+        << Object.get()->getType() << /*call*/ 1
+        << Object.get()->getSourceRange();
+    else
+      Diag(Object.get()->getLocStart(),
+           diag::err_ovl_no_viable_object_call)
+        << Object.get()->getType() << Object.get()->getSourceRange();
+    CandidateSet.NoteCandidates(*this, OCD_AllCandidates,
+                                llvm::makeArrayRef(Args, NumArgs));
+    break;
+
+  case OR_Ambiguous:
+    Diag(Object.get()->getLocStart(),
+         diag::err_ovl_ambiguous_object_call)
+      << Object.get()->getType() << Object.get()->getSourceRange();
+    CandidateSet.NoteCandidates(*this, OCD_ViableCandidates,
+                                llvm::makeArrayRef(Args, NumArgs));
+    break;
+
+  case OR_Deleted:
+    Diag(Object.get()->getLocStart(),
+         diag::err_ovl_deleted_object_call)
+      << Best->Function->isDeleted()
+      << Object.get()->getType() 
+      << getDeletedOrUnavailableSuffix(Best->Function)
+      << Object.get()->getSourceRange();
+    CandidateSet.NoteCandidates(*this, OCD_AllCandidates,
+                                llvm::makeArrayRef(Args, NumArgs));
+    break;
+  }
+
+  if (Best == CandidateSet.end())
+    return true;
+
+  UnbridgedCasts.restore();
+
+  if (Best->Function == 0) {
+    // Since there is no function declaration, this is one of the
+    // surrogate candidates. Dig out the conversion function.
+    CXXConversionDecl *Conv
+      = cast<CXXConversionDecl>(
+                         Best->Conversions[0].UserDefined.ConversionFunction);
+
+    CheckMemberOperatorAccess(LParenLoc, Object.get(), 0, Best->FoundDecl);
+    DiagnoseUseOfDecl(Best->FoundDecl, LParenLoc);
+
+    // We selected one of the surrogate functions that converts the
+    // object parameter to a function pointer. Perform the conversion
+    // on the object argument, then let ActOnCallExpr finish the job.
+
+    // Create an implicit member expr to refer to the conversion operator.
+    // and then call it.
+    ExprResult Call = BuildCXXMemberCallExpr(Object.get(), Best->FoundDecl,
+                                             Conv, HadMultipleCandidates);
+    if (Call.isInvalid())
+      return ExprError();
+    // Record usage of conversion in an implicit cast.
+    Call = Owned(ImplicitCastExpr::Create(Context, Call.get()->getType(),
+                                          CK_UserDefinedConversion,
+                                          Call.get(), 0, VK_RValue));
+
+    return ActOnCallExpr(S, Call.get(), LParenLoc, MultiExprArg(Args, NumArgs),
+                         RParenLoc);
+  }
+
+  MarkFunctionReferenced(LParenLoc, Best->Function);
+  CheckMemberOperatorAccess(LParenLoc, Object.get(), 0, Best->FoundDecl);
+  DiagnoseUseOfDecl(Best->FoundDecl, LParenLoc);
+
+  // We found an overloaded operator(). Build a CXXOperatorCallExpr
+  // that calls this method, using Object for the implicit object
+  // parameter and passing along the remaining arguments.
+  CXXMethodDecl *Method = cast<CXXMethodDecl>(Best->Function);
+  const FunctionProtoType *Proto =
+    Method->getType()->getAs<FunctionProtoType>();
+
+  unsigned NumArgsInProto = Proto->getNumArgs();
+  unsigned NumArgsToCheck = NumArgs;
+
+  // Build the full argument list for the method call (the
+  // implicit object parameter is placed at the beginning of the
+  // list).
+  Expr **MethodArgs;
+  if (NumArgs < NumArgsInProto) {
+    NumArgsToCheck = NumArgsInProto;
+    MethodArgs = new Expr*[NumArgsInProto + 1];
+  } else {
+    MethodArgs = new Expr*[NumArgs + 1];
+  }
+  MethodArgs[0] = Object.get();
+  for (unsigned ArgIdx = 0; ArgIdx < NumArgs; ++ArgIdx)
+    MethodArgs[ArgIdx + 1] = Args[ArgIdx];
+
+  DeclarationNameInfo OpLocInfo(
+               Context.DeclarationNames.getCXXOperatorName(OO_Call), LParenLoc);
+  OpLocInfo.setCXXOperatorNameRange(SourceRange(LParenLoc, RParenLoc));
+  ExprResult NewFn = CreateFunctionRefExpr(*this, Method,
+                                           HadMultipleCandidates,
+                                           OpLocInfo.getLoc(),
+                                           OpLocInfo.getInfo());
+  if (NewFn.isInvalid())
+    return true;
+
+  // Once we've built TheCall, all of the expressions are properly
+  // owned.
+  QualType ResultTy = Method->getResultType();
+  ExprValueKind VK = Expr::getValueKindForType(ResultTy);
+  ResultTy = ResultTy.getNonLValueExprType(Context);
+
+  CXXOperatorCallExpr *TheCall =
+    new (Context) CXXOperatorCallExpr(Context, OO_Call, NewFn.take(),
+                                      MethodArgs, NumArgs + 1,
+                                      ResultTy, VK, RParenLoc);
+  delete [] MethodArgs;
+
+  if (CheckCallReturnType(Method->getResultType(), LParenLoc, TheCall,
+                          Method))
+    return true;
+
+  // We may have default arguments. If so, we need to allocate more
+  // slots in the call for them.
+  if (NumArgs < NumArgsInProto)
+    TheCall->setNumArgs(Context, NumArgsInProto + 1);
+  else if (NumArgs > NumArgsInProto)
+    NumArgsToCheck = NumArgsInProto;
+
+  bool IsError = false;
+
+  // Initialize the implicit object parameter.
+  ExprResult ObjRes =
+    PerformObjectArgumentInitialization(Object.get(), /*Qualifier=*/0,
+                                        Best->FoundDecl, Method);
+  if (ObjRes.isInvalid())
+    IsError = true;
+  else
+    Object = move(ObjRes);
+  TheCall->setArg(0, Object.take());
+
+  // Check the argument types.
+  for (unsigned i = 0; i != NumArgsToCheck; i++) {
+    Expr *Arg;
+    if (i < NumArgs) {
+      Arg = Args[i];
+
+      // Pass the argument.
+
+      ExprResult InputInit
+        = PerformCopyInitialization(InitializedEntity::InitializeParameter(
+                                                    Context,
+                                                    Method->getParamDecl(i)),
+                                    SourceLocation(), Arg);
+
+      IsError |= InputInit.isInvalid();
+      Arg = InputInit.takeAs<Expr>();
+    } else {
+      ExprResult DefArg
+        = BuildCXXDefaultArgExpr(LParenLoc, Method, Method->getParamDecl(i));
+      if (DefArg.isInvalid()) {
+        IsError = true;
+        break;
+      }
+
+      Arg = DefArg.takeAs<Expr>();
+    }
+
+    TheCall->setArg(i + 1, Arg);
+  }
+
+  // If this is a variadic call, handle args passed through "...".
+  if (Proto->isVariadic()) {
+    // Promote the arguments (C99 6.5.2.2p7).
+    for (unsigned i = NumArgsInProto; i != NumArgs; i++) {
+      ExprResult Arg = DefaultVariadicArgumentPromotion(Args[i], VariadicMethod, 0);
+      IsError |= Arg.isInvalid();
+      TheCall->setArg(i + 1, Arg.take());
+    }
+  }
+
+  if (IsError) return true;
+
+  DiagnoseSentinelCalls(Method, LParenLoc, Args, NumArgs);
+
+  if (CheckFunctionCall(Method, TheCall))
+    return true;
+
+  return MaybeBindToTemporary(TheCall);
+}
+
+/// BuildOverloadedArrowExpr - Build a call to an overloaded @c operator->
+///  (if one exists), where @c Base is an expression of class type and
+/// @c Member is the name of the member we're trying to find.
+ExprResult
+Sema::BuildOverloadedArrowExpr(Scope *S, Expr *Base, SourceLocation OpLoc) {
+  assert(Base->getType()->isRecordType() &&
+         "left-hand side must have class type");
+
+  if (checkPlaceholderForOverload(*this, Base))
+    return ExprError();
+
+  SourceLocation Loc = Base->getExprLoc();
+
+  // C++ [over.ref]p1:
+  //
+  //   [...] An expression x->m is interpreted as (x.operator->())->m
+  //   for a class object x of type T if T::operator->() exists and if
+  //   the operator is selected as the best match function by the
+  //   overload resolution mechanism (13.3).
+  DeclarationName OpName =
+    Context.DeclarationNames.getCXXOperatorName(OO_Arrow);
+  OverloadCandidateSet CandidateSet(Loc);
+  const RecordType *BaseRecord = Base->getType()->getAs<RecordType>();
+
+  if (RequireCompleteType(Loc, Base->getType(),
+                          PDiag(diag::err_typecheck_incomplete_tag)
+                            << Base->getSourceRange()))
+    return ExprError();
+
+  LookupResult R(*this, OpName, OpLoc, LookupOrdinaryName);
+  LookupQualifiedName(R, BaseRecord->getDecl());
+  R.suppressDiagnostics();
+
+  for (LookupResult::iterator Oper = R.begin(), OperEnd = R.end();
+       Oper != OperEnd; ++Oper) {
+    AddMethodCandidate(Oper.getPair(), Base->getType(), Base->Classify(Context),
+                       0, 0, CandidateSet, /*SuppressUserConversions=*/false);
+  }
+
+  bool HadMultipleCandidates = (CandidateSet.size() > 1);
+
+  // Perform overload resolution.
+  OverloadCandidateSet::iterator Best;
+  switch (CandidateSet.BestViableFunction(*this, OpLoc, Best)) {
+  case OR_Success:
+    // Overload resolution succeeded; we'll build the call below.
+    break;
+
+  case OR_No_Viable_Function:
+    if (CandidateSet.empty())
+      Diag(OpLoc, diag::err_typecheck_member_reference_arrow)
+        << Base->getType() << Base->getSourceRange();
+    else
+      Diag(OpLoc, diag::err_ovl_no_viable_oper)
+        << "operator->" << Base->getSourceRange();
+    CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Base);
+    return ExprError();
+
+  case OR_Ambiguous:
+    Diag(OpLoc,  diag::err_ovl_ambiguous_oper_unary)
+      << "->" << Base->getType() << Base->getSourceRange();
+    CandidateSet.NoteCandidates(*this, OCD_ViableCandidates, Base);
+    return ExprError();
+
+  case OR_Deleted:
+    Diag(OpLoc,  diag::err_ovl_deleted_oper)
+      << Best->Function->isDeleted()
+      << "->" 
+      << getDeletedOrUnavailableSuffix(Best->Function)
+      << Base->getSourceRange();
+    CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Base);
+    return ExprError();
+  }
+
+  MarkFunctionReferenced(OpLoc, Best->Function);
+  CheckMemberOperatorAccess(OpLoc, Base, 0, Best->FoundDecl);
+  DiagnoseUseOfDecl(Best->FoundDecl, OpLoc);
+
+  // Convert the object parameter.
+  CXXMethodDecl *Method = cast<CXXMethodDecl>(Best->Function);
+  ExprResult BaseResult =
+    PerformObjectArgumentInitialization(Base, /*Qualifier=*/0,
+                                        Best->FoundDecl, Method);
+  if (BaseResult.isInvalid())
+    return ExprError();
+  Base = BaseResult.take();
+
+  // Build the operator call.
+  ExprResult FnExpr = CreateFunctionRefExpr(*this, Method,
+                                            HadMultipleCandidates, OpLoc);
+  if (FnExpr.isInvalid())
+    return ExprError();
+
+  QualType ResultTy = Method->getResultType();
+  ExprValueKind VK = Expr::getValueKindForType(ResultTy);
+  ResultTy = ResultTy.getNonLValueExprType(Context);
+  CXXOperatorCallExpr *TheCall =
+    new (Context) CXXOperatorCallExpr(Context, OO_Arrow, FnExpr.take(),
+                                      &Base, 1, ResultTy, VK, OpLoc);
+
+  if (CheckCallReturnType(Method->getResultType(), OpLoc, TheCall,
+                          Method))
+          return ExprError();
+
+  return MaybeBindToTemporary(TheCall);
+}
+
+/// BuildLiteralOperatorCall - Build a UserDefinedLiteral by creating a call to
+/// a literal operator described by the provided lookup results.
+ExprResult Sema::BuildLiteralOperatorCall(LookupResult &R,
+                                          DeclarationNameInfo &SuffixInfo,
+                                          ArrayRef<Expr*> Args,
+                                          SourceLocation LitEndLoc,
+                                       TemplateArgumentListInfo *TemplateArgs) {
+  SourceLocation UDSuffixLoc = SuffixInfo.getCXXLiteralOperatorNameLoc();
+
+  OverloadCandidateSet CandidateSet(UDSuffixLoc);
+  AddFunctionCandidates(R.asUnresolvedSet(), Args, CandidateSet, true,
+                        TemplateArgs);
+
+  bool HadMultipleCandidates = (CandidateSet.size() > 1);
+
+  // Perform overload resolution. This will usually be trivial, but might need
+  // to perform substitutions for a literal operator template.
+  OverloadCandidateSet::iterator Best;
+  switch (CandidateSet.BestViableFunction(*this, UDSuffixLoc, Best)) {
+  case OR_Success:
+  case OR_Deleted:
+    break;
+
+  case OR_No_Viable_Function:
+    Diag(UDSuffixLoc, diag::err_ovl_no_viable_function_in_call)
+      << R.getLookupName();
+    CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Args);
+    return ExprError();
+
+  case OR_Ambiguous:
+    Diag(R.getNameLoc(), diag::err_ovl_ambiguous_call) << R.getLookupName();
+    CandidateSet.NoteCandidates(*this, OCD_ViableCandidates, Args);
+    return ExprError();
+  }
+
+  FunctionDecl *FD = Best->Function;
+  MarkFunctionReferenced(UDSuffixLoc, FD);
+  DiagnoseUseOfDecl(Best->FoundDecl, UDSuffixLoc);
+
+  ExprResult Fn = CreateFunctionRefExpr(*this, FD, HadMultipleCandidates,
+                                        SuffixInfo.getLoc(),
+                                        SuffixInfo.getInfo());
+  if (Fn.isInvalid())
+    return true;
+
+  // Check the argument types. This should almost always be a no-op, except
+  // that array-to-pointer decay is applied to string literals.
+  Expr *ConvArgs[2];
+  for (unsigned ArgIdx = 0; ArgIdx != Args.size(); ++ArgIdx) {
+    ExprResult InputInit = PerformCopyInitialization(
+      InitializedEntity::InitializeParameter(Context, FD->getParamDecl(ArgIdx)),
+      SourceLocation(), Args[ArgIdx]);
+    if (InputInit.isInvalid())
+      return true;
+    ConvArgs[ArgIdx] = InputInit.take();
+  }
+
+  QualType ResultTy = FD->getResultType();
+  ExprValueKind VK = Expr::getValueKindForType(ResultTy);
+  ResultTy = ResultTy.getNonLValueExprType(Context);
+
+  UserDefinedLiteral *UDL =
+    new (Context) UserDefinedLiteral(Context, Fn.take(), ConvArgs, Args.size(),
+                                     ResultTy, VK, LitEndLoc, UDSuffixLoc);
+
+  if (CheckCallReturnType(FD->getResultType(), UDSuffixLoc, UDL, FD))
+    return ExprError();
+
+  if (CheckFunctionCall(FD, UDL))
+    return ExprError();
+
+  return MaybeBindToTemporary(UDL);
+}
+
+/// FixOverloadedFunctionReference - E is an expression that refers to
+/// a C++ overloaded function (possibly with some parentheses and
+/// perhaps a '&' around it). We have resolved the overloaded function
+/// to the function declaration Fn, so patch up the expression E to
+/// refer (possibly indirectly) to Fn. Returns the new expr.
+Expr *Sema::FixOverloadedFunctionReference(Expr *E, DeclAccessPair Found,
+                                           FunctionDecl *Fn) {
+  if (ParenExpr *PE = dyn_cast<ParenExpr>(E)) {
+    Expr *SubExpr = FixOverloadedFunctionReference(PE->getSubExpr(),
+                                                   Found, Fn);
+    if (SubExpr == PE->getSubExpr())
+      return PE;
+
+    return new (Context) ParenExpr(PE->getLParen(), PE->getRParen(), SubExpr);
+  }
+
+  if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(E)) {
+    Expr *SubExpr = FixOverloadedFunctionReference(ICE->getSubExpr(),
+                                                   Found, Fn);
+    assert(Context.hasSameType(ICE->getSubExpr()->getType(),
+                               SubExpr->getType()) &&
+           "Implicit cast type cannot be determined from overload");
+    assert(ICE->path_empty() && "fixing up hierarchy conversion?");
+    if (SubExpr == ICE->getSubExpr())
+      return ICE;
+
+    return ImplicitCastExpr::Create(Context, ICE->getType(),
+                                    ICE->getCastKind(),
+                                    SubExpr, 0,
+                                    ICE->getValueKind());
+  }
+
+  if (UnaryOperator *UnOp = dyn_cast<UnaryOperator>(E)) {
+    assert(UnOp->getOpcode() == UO_AddrOf &&
+           "Can only take the address of an overloaded function");
+    if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(Fn)) {
+      if (Method->isStatic()) {
+        // Do nothing: static member functions aren't any different
+        // from non-member functions.
+      } else {
+        // Fix the sub expression, which really has to be an
+        // UnresolvedLookupExpr holding an overloaded member function
+        // or template.
+        Expr *SubExpr = FixOverloadedFunctionReference(UnOp->getSubExpr(),
+                                                       Found, Fn);
+        if (SubExpr == UnOp->getSubExpr())
+          return UnOp;
+
+        assert(isa<DeclRefExpr>(SubExpr)
+               && "fixed to something other than a decl ref");
+        assert(cast<DeclRefExpr>(SubExpr)->getQualifier()
+               && "fixed to a member ref with no nested name qualifier");
+
+        // We have taken the address of a pointer to member
+        // function. Perform the computation here so that we get the
+        // appropriate pointer to member type.
+        QualType ClassType
+          = Context.getTypeDeclType(cast<RecordDecl>(Method->getDeclContext()));
+        QualType MemPtrType
+          = Context.getMemberPointerType(Fn->getType(), ClassType.getTypePtr());
+
+        return new (Context) UnaryOperator(SubExpr, UO_AddrOf, MemPtrType,
+                                           VK_RValue, OK_Ordinary,
+                                           UnOp->getOperatorLoc());
+      }
+    }
+    Expr *SubExpr = FixOverloadedFunctionReference(UnOp->getSubExpr(),
+                                                   Found, Fn);
+    if (SubExpr == UnOp->getSubExpr())
+      return UnOp;
+
+    return new (Context) UnaryOperator(SubExpr, UO_AddrOf,
+                                     Context.getPointerType(SubExpr->getType()),
+                                       VK_RValue, OK_Ordinary,
+                                       UnOp->getOperatorLoc());
+  }
+
+  if (UnresolvedLookupExpr *ULE = dyn_cast<UnresolvedLookupExpr>(E)) {
+    // FIXME: avoid copy.
+    TemplateArgumentListInfo TemplateArgsBuffer, *TemplateArgs = 0;
+    if (ULE->hasExplicitTemplateArgs()) {
+      ULE->copyTemplateArgumentsInto(TemplateArgsBuffer);
+      TemplateArgs = &TemplateArgsBuffer;
+    }
+
+    DeclRefExpr *DRE = DeclRefExpr::Create(Context,
+                                           ULE->getQualifierLoc(),
+                                           ULE->getTemplateKeywordLoc(),
+                                           Fn,
+                                           /*enclosing*/ false, // FIXME?
+                                           ULE->getNameLoc(),
+                                           Fn->getType(),
+                                           VK_LValue,
+                                           Found.getDecl(),
+                                           TemplateArgs);
+    MarkDeclRefReferenced(DRE);
+    DRE->setHadMultipleCandidates(ULE->getNumDecls() > 1);
+    return DRE;
+  }
+
+  if (UnresolvedMemberExpr *MemExpr = dyn_cast<UnresolvedMemberExpr>(E)) {
+    // FIXME: avoid copy.
+    TemplateArgumentListInfo TemplateArgsBuffer, *TemplateArgs = 0;
+    if (MemExpr->hasExplicitTemplateArgs()) {
+      MemExpr->copyTemplateArgumentsInto(TemplateArgsBuffer);
+      TemplateArgs = &TemplateArgsBuffer;
+    }
+
+    Expr *Base;
+
+    // If we're filling in a static method where we used to have an
+    // implicit member access, rewrite to a simple decl ref.
+    if (MemExpr->isImplicitAccess()) {
+      if (cast<CXXMethodDecl>(Fn)->isStatic()) {
+        DeclRefExpr *DRE = DeclRefExpr::Create(Context,
+                                               MemExpr->getQualifierLoc(),
+                                               MemExpr->getTemplateKeywordLoc(),
+                                               Fn,
+                                               /*enclosing*/ false,
+                                               MemExpr->getMemberLoc(),
+                                               Fn->getType(),
+                                               VK_LValue,
+                                               Found.getDecl(),
+                                               TemplateArgs);
+        MarkDeclRefReferenced(DRE);
+        DRE->setHadMultipleCandidates(MemExpr->getNumDecls() > 1);
+        return DRE;
+      } else {
+        SourceLocation Loc = MemExpr->getMemberLoc();
+        if (MemExpr->getQualifier())
+          Loc = MemExpr->getQualifierLoc().getBeginLoc();
+        CheckCXXThisCapture(Loc);
+        Base = new (Context) CXXThisExpr(Loc,
+                                         MemExpr->getBaseType(),
+                                         /*isImplicit=*/true);
+      }
+    } else
+      Base = MemExpr->getBase();
+
+    ExprValueKind valueKind;
+    QualType type;
+    if (cast<CXXMethodDecl>(Fn)->isStatic()) {
+      valueKind = VK_LValue;
+      type = Fn->getType();
+    } else {
+      valueKind = VK_RValue;
+      type = Context.BoundMemberTy;
+    }
+
+    MemberExpr *ME = MemberExpr::Create(Context, Base,
+                                        MemExpr->isArrow(),
+                                        MemExpr->getQualifierLoc(),
+                                        MemExpr->getTemplateKeywordLoc(),
+                                        Fn,
+                                        Found,
+                                        MemExpr->getMemberNameInfo(),
+                                        TemplateArgs,
+                                        type, valueKind, OK_Ordinary);
+    ME->setHadMultipleCandidates(true);
+    return ME;
+  }
+
+  llvm_unreachable("Invalid reference to overloaded function");
+}
+
+ExprResult Sema::FixOverloadedFunctionReference(ExprResult E,
+                                                DeclAccessPair Found,
+                                                FunctionDecl *Fn) {
+  return Owned(FixOverloadedFunctionReference((Expr *)E.get(), Found, Fn));
+}
+
+} // end namespace clang
diff --git a/clang/lib/Sema/SemaPseudoObject.cpp b/clang/lib/Sema/SemaPseudoObject.cpp
new file mode 100644
index 0000000..0e66329
--- /dev/null
+++ b/clang/lib/Sema/SemaPseudoObject.cpp
@@ -0,0 +1,1373 @@
+//===--- SemaPseudoObject.cpp - Semantic Analysis for Pseudo-Objects ------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+//  This file implements semantic analysis for expressions involving
+//  pseudo-object references.  Pseudo-objects are conceptual objects
+//  whose storage is entirely abstract and all accesses to which are
+//  translated through some sort of abstraction barrier.
+//
+//  For example, Objective-C objects can have "properties", either
+//  declared or undeclared.  A property may be accessed by writing
+//    expr.prop
+//  where 'expr' is an r-value of Objective-C pointer type and 'prop'
+//  is the name of the property.  If this expression is used in a context
+//  needing an r-value, it is treated as if it were a message-send
+//  of the associated 'getter' selector, typically:
+//    [expr prop]
+//  If it is used as the LHS of a simple assignment, it is treated
+//  as a message-send of the associated 'setter' selector, typically:
+//    [expr setProp: RHS]
+//  If it is used as the LHS of a compound assignment, or the operand
+//  of a unary increment or decrement, both are required;  for example,
+//  'expr.prop *= 100' would be translated to:
+//    [expr setProp: [expr prop] * 100]
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Sema/SemaInternal.h"
+#include "clang/Sema/Initialization.h"
+#include "clang/AST/ExprObjC.h"
+#include "clang/Lex/Preprocessor.h"
+
+using namespace clang;
+using namespace sema;
+
+namespace {
+  // Basically just a very focused copy of TreeTransform.
+  template <class T> struct Rebuilder {
+    Sema &S;
+    Rebuilder(Sema &S) : S(S) {}
+
+    T &getDerived() { return static_cast<T&>(*this); }
+
+    Expr *rebuild(Expr *e) {
+      // Fast path: nothing to look through.
+      if (typename T::specific_type *specific
+            = dyn_cast<typename T::specific_type>(e))
+        return getDerived().rebuildSpecific(specific);
+
+      // Otherwise, we should look through and rebuild anything that
+      // IgnoreParens would.
+
+      if (ParenExpr *parens = dyn_cast<ParenExpr>(e)) {
+        e = rebuild(parens->getSubExpr());
+        return new (S.Context) ParenExpr(parens->getLParen(),
+                                         parens->getRParen(),
+                                         e);
+      }
+
+      if (UnaryOperator *uop = dyn_cast<UnaryOperator>(e)) {
+        assert(uop->getOpcode() == UO_Extension);
+        e = rebuild(uop->getSubExpr());
+        return new (S.Context) UnaryOperator(e, uop->getOpcode(),
+                                             uop->getType(),
+                                             uop->getValueKind(),
+                                             uop->getObjectKind(),
+                                             uop->getOperatorLoc());
+      }
+
+      if (GenericSelectionExpr *gse = dyn_cast<GenericSelectionExpr>(e)) {
+        assert(!gse->isResultDependent());
+        unsigned resultIndex = gse->getResultIndex();
+        unsigned numAssocs = gse->getNumAssocs();
+
+        SmallVector<Expr*, 8> assocs(numAssocs);
+        SmallVector<TypeSourceInfo*, 8> assocTypes(numAssocs);
+
+        for (unsigned i = 0; i != numAssocs; ++i) {
+          Expr *assoc = gse->getAssocExpr(i);
+          if (i == resultIndex) assoc = rebuild(assoc);
+          assocs[i] = assoc;
+          assocTypes[i] = gse->getAssocTypeSourceInfo(i);
+        }
+
+        return new (S.Context) GenericSelectionExpr(S.Context,
+                                                    gse->getGenericLoc(),
+                                                    gse->getControllingExpr(),
+                                                    assocTypes.data(),
+                                                    assocs.data(),
+                                                    numAssocs,
+                                                    gse->getDefaultLoc(),
+                                                    gse->getRParenLoc(),
+                                      gse->containsUnexpandedParameterPack(),
+                                                    resultIndex);
+      }
+
+      llvm_unreachable("bad expression to rebuild!");
+    }
+  };
+
+  struct ObjCPropertyRefRebuilder : Rebuilder<ObjCPropertyRefRebuilder> {
+    Expr *NewBase;
+    ObjCPropertyRefRebuilder(Sema &S, Expr *newBase)
+      : Rebuilder<ObjCPropertyRefRebuilder>(S), NewBase(newBase) {}
+
+    typedef ObjCPropertyRefExpr specific_type;
+    Expr *rebuildSpecific(ObjCPropertyRefExpr *refExpr) {
+      // Fortunately, the constraint that we're rebuilding something
+      // with a base limits the number of cases here.
+      assert(refExpr->getBase());
+
+      if (refExpr->isExplicitProperty()) {
+        return new (S.Context)
+          ObjCPropertyRefExpr(refExpr->getExplicitProperty(),
+                              refExpr->getType(), refExpr->getValueKind(),
+                              refExpr->getObjectKind(), refExpr->getLocation(),
+                              NewBase);
+      }
+      return new (S.Context)
+        ObjCPropertyRefExpr(refExpr->getImplicitPropertyGetter(),
+                            refExpr->getImplicitPropertySetter(),
+                            refExpr->getType(), refExpr->getValueKind(),
+                            refExpr->getObjectKind(),refExpr->getLocation(),
+                            NewBase);
+    }
+  };
+
+  struct ObjCSubscriptRefRebuilder : Rebuilder<ObjCSubscriptRefRebuilder> {
+    Expr *NewBase;
+    Expr *NewKeyExpr;
+    ObjCSubscriptRefRebuilder(Sema &S, Expr *newBase, Expr *newKeyExpr)
+    : Rebuilder<ObjCSubscriptRefRebuilder>(S), 
+      NewBase(newBase), NewKeyExpr(newKeyExpr) {}
+    
+    typedef ObjCSubscriptRefExpr specific_type;
+    Expr *rebuildSpecific(ObjCSubscriptRefExpr *refExpr) {
+      assert(refExpr->getBaseExpr());
+      assert(refExpr->getKeyExpr());
+      
+      return new (S.Context)
+        ObjCSubscriptRefExpr(NewBase,
+                             NewKeyExpr,
+                             refExpr->getType(), refExpr->getValueKind(),
+                             refExpr->getObjectKind(),refExpr->getAtIndexMethodDecl(),
+                             refExpr->setAtIndexMethodDecl(),
+                             refExpr->getRBracket());
+    }
+  };
+  
+  class PseudoOpBuilder {
+  public:
+    Sema &S;
+    unsigned ResultIndex;
+    SourceLocation GenericLoc;
+    SmallVector<Expr *, 4> Semantics;
+
+    PseudoOpBuilder(Sema &S, SourceLocation genericLoc)
+      : S(S), ResultIndex(PseudoObjectExpr::NoResult),
+        GenericLoc(genericLoc) {}
+
+    virtual ~PseudoOpBuilder() {}
+
+    /// Add a normal semantic expression.
+    void addSemanticExpr(Expr *semantic) {
+      Semantics.push_back(semantic);
+    }
+
+    /// Add the 'result' semantic expression.
+    void addResultSemanticExpr(Expr *resultExpr) {
+      assert(ResultIndex == PseudoObjectExpr::NoResult);
+      ResultIndex = Semantics.size();
+      Semantics.push_back(resultExpr);
+    }
+
+    ExprResult buildRValueOperation(Expr *op);
+    ExprResult buildAssignmentOperation(Scope *Sc,
+                                        SourceLocation opLoc,
+                                        BinaryOperatorKind opcode,
+                                        Expr *LHS, Expr *RHS);
+    ExprResult buildIncDecOperation(Scope *Sc, SourceLocation opLoc,
+                                    UnaryOperatorKind opcode,
+                                    Expr *op);
+
+    ExprResult complete(Expr *syntacticForm);
+
+    OpaqueValueExpr *capture(Expr *op);
+    OpaqueValueExpr *captureValueAsResult(Expr *op);
+
+    void setResultToLastSemantic() {
+      assert(ResultIndex == PseudoObjectExpr::NoResult);
+      ResultIndex = Semantics.size() - 1;
+    }
+
+    /// Return true if assignments have a non-void result.
+    virtual bool assignmentsHaveResult() { return true; }
+
+    virtual Expr *rebuildAndCaptureObject(Expr *) = 0;
+    virtual ExprResult buildGet() = 0;
+    virtual ExprResult buildSet(Expr *, SourceLocation,
+                                bool captureSetValueAsResult) = 0;
+  };
+
+  /// A PseudoOpBuilder for Objective-C @properties.
+  class ObjCPropertyOpBuilder : public PseudoOpBuilder {
+    ObjCPropertyRefExpr *RefExpr;
+    ObjCPropertyRefExpr *SyntacticRefExpr;
+    OpaqueValueExpr *InstanceReceiver;
+    ObjCMethodDecl *Getter;
+
+    ObjCMethodDecl *Setter;
+    Selector SetterSelector;
+    Selector GetterSelector;
+
+  public:
+    ObjCPropertyOpBuilder(Sema &S, ObjCPropertyRefExpr *refExpr) :
+      PseudoOpBuilder(S, refExpr->getLocation()), RefExpr(refExpr),
+      SyntacticRefExpr(0), InstanceReceiver(0), Getter(0), Setter(0) {
+    }
+
+    ExprResult buildRValueOperation(Expr *op);
+    ExprResult buildAssignmentOperation(Scope *Sc,
+                                        SourceLocation opLoc,
+                                        BinaryOperatorKind opcode,
+                                        Expr *LHS, Expr *RHS);
+    ExprResult buildIncDecOperation(Scope *Sc, SourceLocation opLoc,
+                                    UnaryOperatorKind opcode,
+                                    Expr *op);
+
+    bool tryBuildGetOfReference(Expr *op, ExprResult &result);
+    bool findSetter();
+    bool findGetter();
+
+    Expr *rebuildAndCaptureObject(Expr *syntacticBase);
+    ExprResult buildGet();
+    ExprResult buildSet(Expr *op, SourceLocation, bool);
+  };
+
+ /// A PseudoOpBuilder for Objective-C array/dictionary indexing.
+ class ObjCSubscriptOpBuilder : public PseudoOpBuilder {
+   ObjCSubscriptRefExpr *RefExpr;
+   OpaqueValueExpr *InstanceBase;
+   OpaqueValueExpr *InstanceKey;
+   ObjCMethodDecl *AtIndexGetter;
+   Selector AtIndexGetterSelector;
+  
+   ObjCMethodDecl *AtIndexSetter;
+   Selector AtIndexSetterSelector;
+  
+ public:
+    ObjCSubscriptOpBuilder(Sema &S, ObjCSubscriptRefExpr *refExpr) :
+      PseudoOpBuilder(S, refExpr->getSourceRange().getBegin()), 
+      RefExpr(refExpr),
+    InstanceBase(0), InstanceKey(0), 
+    AtIndexGetter(0), AtIndexSetter(0) { }
+  
+   ExprResult buildRValueOperation(Expr *op);
+   ExprResult buildAssignmentOperation(Scope *Sc,
+                                       SourceLocation opLoc,
+                                       BinaryOperatorKind opcode,
+                                       Expr *LHS, Expr *RHS);
+   Expr *rebuildAndCaptureObject(Expr *syntacticBase);
+   
+   bool findAtIndexGetter();
+   bool findAtIndexSetter();
+  
+   ExprResult buildGet();
+   ExprResult buildSet(Expr *op, SourceLocation, bool);
+ };
+
+}
+
+/// Capture the given expression in an OpaqueValueExpr.
+OpaqueValueExpr *PseudoOpBuilder::capture(Expr *e) {
+  // Make a new OVE whose source is the given expression.
+  OpaqueValueExpr *captured = 
+    new (S.Context) OpaqueValueExpr(GenericLoc, e->getType(),
+                                    e->getValueKind(), e->getObjectKind(),
+                                    e);
+  
+  // Make sure we bind that in the semantics.
+  addSemanticExpr(captured);
+  return captured;
+}
+
+/// Capture the given expression as the result of this pseudo-object
+/// operation.  This routine is safe against expressions which may
+/// already be captured.
+///
+/// \param Returns the captured expression, which will be the
+///   same as the input if the input was already captured
+OpaqueValueExpr *PseudoOpBuilder::captureValueAsResult(Expr *e) {
+  assert(ResultIndex == PseudoObjectExpr::NoResult);
+
+  // If the expression hasn't already been captured, just capture it
+  // and set the new semantic 
+  if (!isa<OpaqueValueExpr>(e)) {
+    OpaqueValueExpr *cap = capture(e);
+    setResultToLastSemantic();
+    return cap;
+  }
+
+  // Otherwise, it must already be one of our semantic expressions;
+  // set ResultIndex to its index.
+  unsigned index = 0;
+  for (;; ++index) {
+    assert(index < Semantics.size() &&
+           "captured expression not found in semantics!");
+    if (e == Semantics[index]) break;
+  }
+  ResultIndex = index;
+  return cast<OpaqueValueExpr>(e);
+}
+
+/// The routine which creates the final PseudoObjectExpr.
+ExprResult PseudoOpBuilder::complete(Expr *syntactic) {
+  return PseudoObjectExpr::Create(S.Context, syntactic,
+                                  Semantics, ResultIndex);
+}
+
+/// The main skeleton for building an r-value operation.
+ExprResult PseudoOpBuilder::buildRValueOperation(Expr *op) {
+  Expr *syntacticBase = rebuildAndCaptureObject(op);
+
+  ExprResult getExpr = buildGet();
+  if (getExpr.isInvalid()) return ExprError();
+  addResultSemanticExpr(getExpr.take());
+
+  return complete(syntacticBase);
+}
+
+/// The basic skeleton for building a simple or compound
+/// assignment operation.
+ExprResult
+PseudoOpBuilder::buildAssignmentOperation(Scope *Sc, SourceLocation opcLoc,
+                                          BinaryOperatorKind opcode,
+                                          Expr *LHS, Expr *RHS) {
+  assert(BinaryOperator::isAssignmentOp(opcode));
+
+  Expr *syntacticLHS = rebuildAndCaptureObject(LHS);
+  OpaqueValueExpr *capturedRHS = capture(RHS);
+
+  Expr *syntactic;
+
+  ExprResult result;
+  if (opcode == BO_Assign) {
+    result = capturedRHS;
+    syntactic = new (S.Context) BinaryOperator(syntacticLHS, capturedRHS,
+                                               opcode, capturedRHS->getType(),
+                                               capturedRHS->getValueKind(),
+                                               OK_Ordinary, opcLoc);
+  } else {
+    ExprResult opLHS = buildGet();
+    if (opLHS.isInvalid()) return ExprError();
+
+    // Build an ordinary, non-compound operation.
+    BinaryOperatorKind nonCompound =
+      BinaryOperator::getOpForCompoundAssignment(opcode);
+    result = S.BuildBinOp(Sc, opcLoc, nonCompound,
+                          opLHS.take(), capturedRHS);
+    if (result.isInvalid()) return ExprError();
+
+    syntactic =
+      new (S.Context) CompoundAssignOperator(syntacticLHS, capturedRHS, opcode,
+                                             result.get()->getType(),
+                                             result.get()->getValueKind(),
+                                             OK_Ordinary,
+                                             opLHS.get()->getType(),
+                                             result.get()->getType(),
+                                             opcLoc);
+  }
+
+  // The result of the assignment, if not void, is the value set into
+  // the l-value.
+  result = buildSet(result.take(), opcLoc, assignmentsHaveResult());
+  if (result.isInvalid()) return ExprError();
+  addSemanticExpr(result.take());
+
+  return complete(syntactic);
+}
+
+/// The basic skeleton for building an increment or decrement
+/// operation.
+ExprResult
+PseudoOpBuilder::buildIncDecOperation(Scope *Sc, SourceLocation opcLoc,
+                                      UnaryOperatorKind opcode,
+                                      Expr *op) {
+  assert(UnaryOperator::isIncrementDecrementOp(opcode));
+
+  Expr *syntacticOp = rebuildAndCaptureObject(op);
+
+  // Load the value.
+  ExprResult result = buildGet();
+  if (result.isInvalid()) return ExprError();
+
+  QualType resultType = result.get()->getType();
+
+  // That's the postfix result.
+  if (UnaryOperator::isPostfix(opcode) && assignmentsHaveResult()) {
+    result = capture(result.take());
+    setResultToLastSemantic();
+  }
+
+  // Add or subtract a literal 1.
+  llvm::APInt oneV(S.Context.getTypeSize(S.Context.IntTy), 1);
+  Expr *one = IntegerLiteral::Create(S.Context, oneV, S.Context.IntTy,
+                                     GenericLoc);
+
+  if (UnaryOperator::isIncrementOp(opcode)) {
+    result = S.BuildBinOp(Sc, opcLoc, BO_Add, result.take(), one);
+  } else {
+    result = S.BuildBinOp(Sc, opcLoc, BO_Sub, result.take(), one);
+  }
+  if (result.isInvalid()) return ExprError();
+
+  // Store that back into the result.  The value stored is the result
+  // of a prefix operation.
+  result = buildSet(result.take(), opcLoc,
+             UnaryOperator::isPrefix(opcode) && assignmentsHaveResult());
+  if (result.isInvalid()) return ExprError();
+  addSemanticExpr(result.take());
+
+  UnaryOperator *syntactic =
+    new (S.Context) UnaryOperator(syntacticOp, opcode, resultType,
+                                  VK_LValue, OK_Ordinary, opcLoc);
+  return complete(syntactic);
+}
+
+
+//===----------------------------------------------------------------------===//
+//  Objective-C @property and implicit property references
+//===----------------------------------------------------------------------===//
+
+/// Look up a method in the receiver type of an Objective-C property
+/// reference.
+static ObjCMethodDecl *LookupMethodInReceiverType(Sema &S, Selector sel,
+                                            const ObjCPropertyRefExpr *PRE) {
+  if (PRE->isObjectReceiver()) {
+    const ObjCObjectPointerType *PT =
+      PRE->getBase()->getType()->castAs<ObjCObjectPointerType>();
+
+    // Special case for 'self' in class method implementations.
+    if (PT->isObjCClassType() &&
+        S.isSelfExpr(const_cast<Expr*>(PRE->getBase()))) {
+      // This cast is safe because isSelfExpr is only true within
+      // methods.
+      ObjCMethodDecl *method =
+        cast<ObjCMethodDecl>(S.CurContext->getNonClosureAncestor());
+      return S.LookupMethodInObjectType(sel,
+                 S.Context.getObjCInterfaceType(method->getClassInterface()),
+                                        /*instance*/ false);
+    }
+
+    return S.LookupMethodInObjectType(sel, PT->getPointeeType(), true);
+  }
+
+  if (PRE->isSuperReceiver()) {
+    if (const ObjCObjectPointerType *PT =
+        PRE->getSuperReceiverType()->getAs<ObjCObjectPointerType>())
+      return S.LookupMethodInObjectType(sel, PT->getPointeeType(), true);
+
+    return S.LookupMethodInObjectType(sel, PRE->getSuperReceiverType(), false);
+  }
+
+  assert(PRE->isClassReceiver() && "Invalid expression");
+  QualType IT = S.Context.getObjCInterfaceType(PRE->getClassReceiver());
+  return S.LookupMethodInObjectType(sel, IT, false);
+}
+
+bool ObjCPropertyOpBuilder::findGetter() {
+  if (Getter) return true;
+
+  // For implicit properties, just trust the lookup we already did.
+  if (RefExpr->isImplicitProperty()) {
+    if ((Getter = RefExpr->getImplicitPropertyGetter())) {
+      GetterSelector = Getter->getSelector();
+      return true;
+    }
+    else {
+      // Must build the getter selector the hard way.
+      ObjCMethodDecl *setter = RefExpr->getImplicitPropertySetter();
+      assert(setter && "both setter and getter are null - cannot happen");
+      IdentifierInfo *setterName = 
+        setter->getSelector().getIdentifierInfoForSlot(0);
+      const char *compStr = setterName->getNameStart();
+      compStr += 3;
+      IdentifierInfo *getterName = &S.Context.Idents.get(compStr);
+      GetterSelector = 
+        S.PP.getSelectorTable().getNullarySelector(getterName);
+      return false;
+
+    }
+  }
+
+  ObjCPropertyDecl *prop = RefExpr->getExplicitProperty();
+  Getter = LookupMethodInReceiverType(S, prop->getGetterName(), RefExpr);
+  return (Getter != 0);
+}
+
+/// Try to find the most accurate setter declaration for the property
+/// reference.
+///
+/// \return true if a setter was found, in which case Setter 
+bool ObjCPropertyOpBuilder::findSetter() {
+  // For implicit properties, just trust the lookup we already did.
+  if (RefExpr->isImplicitProperty()) {
+    if (ObjCMethodDecl *setter = RefExpr->getImplicitPropertySetter()) {
+      Setter = setter;
+      SetterSelector = setter->getSelector();
+      return true;
+    } else {
+      IdentifierInfo *getterName =
+        RefExpr->getImplicitPropertyGetter()->getSelector()
+          .getIdentifierInfoForSlot(0);
+      SetterSelector =
+        SelectorTable::constructSetterName(S.PP.getIdentifierTable(),
+                                           S.PP.getSelectorTable(),
+                                           getterName);
+      return false;
+    }
+  }
+
+  // For explicit properties, this is more involved.
+  ObjCPropertyDecl *prop = RefExpr->getExplicitProperty();
+  SetterSelector = prop->getSetterName();
+
+  // Do a normal method lookup first.
+  if (ObjCMethodDecl *setter =
+        LookupMethodInReceiverType(S, SetterSelector, RefExpr)) {
+    Setter = setter;
+    return true;
+  }
+
+  // That can fail in the somewhat crazy situation that we're
+  // type-checking a message send within the @interface declaration
+  // that declared the @property.  But it's not clear that that's
+  // valuable to support.
+
+  return false;
+}
+
+/// Capture the base object of an Objective-C property expression.
+Expr *ObjCPropertyOpBuilder::rebuildAndCaptureObject(Expr *syntacticBase) {
+  assert(InstanceReceiver == 0);
+
+  // If we have a base, capture it in an OVE and rebuild the syntactic
+  // form to use the OVE as its base.
+  if (RefExpr->isObjectReceiver()) {
+    InstanceReceiver = capture(RefExpr->getBase());
+
+    syntacticBase =
+      ObjCPropertyRefRebuilder(S, InstanceReceiver).rebuild(syntacticBase);
+  }
+
+  if (ObjCPropertyRefExpr *
+        refE = dyn_cast<ObjCPropertyRefExpr>(syntacticBase->IgnoreParens()))
+    SyntacticRefExpr = refE;
+
+  return syntacticBase;
+}
+
+/// Load from an Objective-C property reference.
+ExprResult ObjCPropertyOpBuilder::buildGet() {
+  findGetter();
+  assert(Getter);
+
+  if (SyntacticRefExpr)
+    SyntacticRefExpr->setIsMessagingGetter();
+
+  QualType receiverType;
+  if (RefExpr->isClassReceiver()) {
+    receiverType = S.Context.getObjCInterfaceType(RefExpr->getClassReceiver());
+  } else if (RefExpr->isSuperReceiver()) {
+    receiverType = RefExpr->getSuperReceiverType();
+  } else {
+    assert(InstanceReceiver);
+    receiverType = InstanceReceiver->getType();
+  }
+
+  // Build a message-send.
+  ExprResult msg;
+  if (Getter->isInstanceMethod() || RefExpr->isObjectReceiver()) {
+    assert(InstanceReceiver || RefExpr->isSuperReceiver());
+    msg = S.BuildInstanceMessageImplicit(InstanceReceiver, receiverType,
+                                         GenericLoc, Getter->getSelector(),
+                                         Getter, MultiExprArg());
+  } else {
+    msg = S.BuildClassMessageImplicit(receiverType, RefExpr->isSuperReceiver(),
+                                      GenericLoc,
+                                      Getter->getSelector(), Getter,
+                                      MultiExprArg());
+  }
+  return msg;
+}
+
+/// Store to an Objective-C property reference.
+///
+/// \param bindSetValueAsResult - If true, capture the actual
+///   value being set as the value of the property operation.
+ExprResult ObjCPropertyOpBuilder::buildSet(Expr *op, SourceLocation opcLoc,
+                                           bool captureSetValueAsResult) {
+  bool hasSetter = findSetter();
+  assert(hasSetter); (void) hasSetter;
+
+  if (SyntacticRefExpr)
+    SyntacticRefExpr->setIsMessagingSetter();
+
+  QualType receiverType;
+  if (RefExpr->isClassReceiver()) {
+    receiverType = S.Context.getObjCInterfaceType(RefExpr->getClassReceiver());
+  } else if (RefExpr->isSuperReceiver()) {
+    receiverType = RefExpr->getSuperReceiverType();
+  } else {
+    assert(InstanceReceiver);
+    receiverType = InstanceReceiver->getType();
+  }
+
+  // Use assignment constraints when possible; they give us better
+  // diagnostics.  "When possible" basically means anything except a
+  // C++ class type.
+  if (!S.getLangOpts().CPlusPlus || !op->getType()->isRecordType()) {
+    QualType paramType = (*Setter->param_begin())->getType();
+    if (!S.getLangOpts().CPlusPlus || !paramType->isRecordType()) {
+      ExprResult opResult = op;
+      Sema::AssignConvertType assignResult
+        = S.CheckSingleAssignmentConstraints(paramType, opResult);
+      if (S.DiagnoseAssignmentResult(assignResult, opcLoc, paramType,
+                                     op->getType(), opResult.get(),
+                                     Sema::AA_Assigning))
+        return ExprError();
+
+      op = opResult.take();
+      assert(op && "successful assignment left argument invalid?");
+    }
+  }
+
+  // Arguments.
+  Expr *args[] = { op };
+
+  // Build a message-send.
+  ExprResult msg;
+  if (Setter->isInstanceMethod() || RefExpr->isObjectReceiver()) {
+    msg = S.BuildInstanceMessageImplicit(InstanceReceiver, receiverType,
+                                         GenericLoc, SetterSelector, Setter,
+                                         MultiExprArg(args, 1));
+  } else {
+    msg = S.BuildClassMessageImplicit(receiverType, RefExpr->isSuperReceiver(),
+                                      GenericLoc,
+                                      SetterSelector, Setter,
+                                      MultiExprArg(args, 1));
+  }
+
+  if (!msg.isInvalid() && captureSetValueAsResult) {
+    ObjCMessageExpr *msgExpr =
+      cast<ObjCMessageExpr>(msg.get()->IgnoreImplicit());
+    Expr *arg = msgExpr->getArg(0);
+    msgExpr->setArg(0, captureValueAsResult(arg));
+  }
+
+  return msg;
+}
+
+/// @property-specific behavior for doing lvalue-to-rvalue conversion.
+ExprResult ObjCPropertyOpBuilder::buildRValueOperation(Expr *op) {
+  // Explicit properties always have getters, but implicit ones don't.
+  // Check that before proceeding.
+  if (RefExpr->isImplicitProperty() &&
+      !RefExpr->getImplicitPropertyGetter()) {
+    S.Diag(RefExpr->getLocation(), diag::err_getter_not_found)
+      << RefExpr->getBase()->getType();
+    return ExprError();
+  }
+
+  ExprResult result = PseudoOpBuilder::buildRValueOperation(op);
+  if (result.isInvalid()) return ExprError();
+
+  if (RefExpr->isExplicitProperty() && !Getter->hasRelatedResultType())
+    S.DiagnosePropertyAccessorMismatch(RefExpr->getExplicitProperty(),
+                                       Getter, RefExpr->getLocation());
+
+  // As a special case, if the method returns 'id', try to get
+  // a better type from the property.
+  if (RefExpr->isExplicitProperty() && result.get()->isRValue() &&
+      result.get()->getType()->isObjCIdType()) {
+    QualType propType = RefExpr->getExplicitProperty()->getType();
+    if (const ObjCObjectPointerType *ptr
+          = propType->getAs<ObjCObjectPointerType>()) {
+      if (!ptr->isObjCIdType())
+        result = S.ImpCastExprToType(result.get(), propType, CK_BitCast);
+    }
+  }
+
+  return result;
+}
+
+/// Try to build this as a call to a getter that returns a reference.
+///
+/// \return true if it was possible, whether or not it actually
+///   succeeded
+bool ObjCPropertyOpBuilder::tryBuildGetOfReference(Expr *op,
+                                                   ExprResult &result) {
+  if (!S.getLangOpts().CPlusPlus) return false;
+
+  findGetter();
+  assert(Getter && "property has no setter and no getter!");
+
+  // Only do this if the getter returns an l-value reference type.
+  QualType resultType = Getter->getResultType();
+  if (!resultType->isLValueReferenceType()) return false;
+
+  result = buildRValueOperation(op);
+  return true;
+}
+
+/// @property-specific behavior for doing assignments.
+ExprResult
+ObjCPropertyOpBuilder::buildAssignmentOperation(Scope *Sc,
+                                                SourceLocation opcLoc,
+                                                BinaryOperatorKind opcode,
+                                                Expr *LHS, Expr *RHS) {
+  assert(BinaryOperator::isAssignmentOp(opcode));
+
+  // If there's no setter, we have no choice but to try to assign to
+  // the result of the getter.
+  if (!findSetter()) {
+    ExprResult result;
+    if (tryBuildGetOfReference(LHS, result)) {
+      if (result.isInvalid()) return ExprError();
+      return S.BuildBinOp(Sc, opcLoc, opcode, result.take(), RHS);
+    }
+
+    // Otherwise, it's an error.
+    S.Diag(opcLoc, diag::err_nosetter_property_assignment)
+      << unsigned(RefExpr->isImplicitProperty())
+      << SetterSelector
+      << LHS->getSourceRange() << RHS->getSourceRange();
+    return ExprError();
+  }
+
+  // If there is a setter, we definitely want to use it.
+
+  // Verify that we can do a compound assignment.
+  if (opcode != BO_Assign && !findGetter()) {
+    S.Diag(opcLoc, diag::err_nogetter_property_compound_assignment)
+      << LHS->getSourceRange() << RHS->getSourceRange();
+    return ExprError();
+  }
+
+  ExprResult result =
+    PseudoOpBuilder::buildAssignmentOperation(Sc, opcLoc, opcode, LHS, RHS);
+  if (result.isInvalid()) return ExprError();
+
+  // Various warnings about property assignments in ARC.
+  if (S.getLangOpts().ObjCAutoRefCount && InstanceReceiver) {
+    S.checkRetainCycles(InstanceReceiver->getSourceExpr(), RHS);
+    S.checkUnsafeExprAssigns(opcLoc, LHS, RHS);
+  }
+
+  return result;
+}
+
+/// @property-specific behavior for doing increments and decrements.
+ExprResult
+ObjCPropertyOpBuilder::buildIncDecOperation(Scope *Sc, SourceLocation opcLoc,
+                                            UnaryOperatorKind opcode,
+                                            Expr *op) {
+  // If there's no setter, we have no choice but to try to assign to
+  // the result of the getter.
+  if (!findSetter()) {
+    ExprResult result;
+    if (tryBuildGetOfReference(op, result)) {
+      if (result.isInvalid()) return ExprError();
+      return S.BuildUnaryOp(Sc, opcLoc, opcode, result.take());
+    }
+
+    // Otherwise, it's an error.
+    S.Diag(opcLoc, diag::err_nosetter_property_incdec)
+      << unsigned(RefExpr->isImplicitProperty())
+      << unsigned(UnaryOperator::isDecrementOp(opcode))
+      << SetterSelector
+      << op->getSourceRange();
+    return ExprError();
+  }
+
+  // If there is a setter, we definitely want to use it.
+
+  // We also need a getter.
+  if (!findGetter()) {
+    assert(RefExpr->isImplicitProperty());
+    S.Diag(opcLoc, diag::err_nogetter_property_incdec)
+      << unsigned(UnaryOperator::isDecrementOp(opcode))
+      << GetterSelector
+      << op->getSourceRange();
+    return ExprError();
+  }
+
+  return PseudoOpBuilder::buildIncDecOperation(Sc, opcLoc, opcode, op);
+}
+
+// ObjCSubscript build stuff.
+//
+
+/// objective-c subscripting-specific behavior for doing lvalue-to-rvalue 
+/// conversion.
+/// FIXME. Remove this routine if it is proven that no additional 
+/// specifity is needed.
+ExprResult ObjCSubscriptOpBuilder::buildRValueOperation(Expr *op) {
+  ExprResult result = PseudoOpBuilder::buildRValueOperation(op);
+  if (result.isInvalid()) return ExprError();
+  return result;
+}
+
+/// objective-c subscripting-specific  behavior for doing assignments.
+ExprResult
+ObjCSubscriptOpBuilder::buildAssignmentOperation(Scope *Sc,
+                                                SourceLocation opcLoc,
+                                                BinaryOperatorKind opcode,
+                                                Expr *LHS, Expr *RHS) {
+  assert(BinaryOperator::isAssignmentOp(opcode));
+  // There must be a method to do the Index'ed assignment.
+  if (!findAtIndexSetter())
+    return ExprError();
+  
+  // Verify that we can do a compound assignment.
+  if (opcode != BO_Assign && !findAtIndexGetter())
+    return ExprError();
+  
+  ExprResult result =
+  PseudoOpBuilder::buildAssignmentOperation(Sc, opcLoc, opcode, LHS, RHS);
+  if (result.isInvalid()) return ExprError();
+  
+  // Various warnings about objc Index'ed assignments in ARC.
+  if (S.getLangOpts().ObjCAutoRefCount && InstanceBase) {
+    S.checkRetainCycles(InstanceBase->getSourceExpr(), RHS);
+    S.checkUnsafeExprAssigns(opcLoc, LHS, RHS);
+  }
+  
+  return result;
+}
+
+/// Capture the base object of an Objective-C Index'ed expression.
+Expr *ObjCSubscriptOpBuilder::rebuildAndCaptureObject(Expr *syntacticBase) {
+  assert(InstanceBase == 0);
+  
+  // Capture base expression in an OVE and rebuild the syntactic
+  // form to use the OVE as its base expression.
+  InstanceBase = capture(RefExpr->getBaseExpr());
+  InstanceKey = capture(RefExpr->getKeyExpr());
+    
+  syntacticBase =
+    ObjCSubscriptRefRebuilder(S, InstanceBase, 
+                              InstanceKey).rebuild(syntacticBase);
+  
+  return syntacticBase;
+}
+
+/// CheckSubscriptingKind - This routine decide what type 
+/// of indexing represented by "FromE" is being done.
+Sema::ObjCSubscriptKind 
+  Sema::CheckSubscriptingKind(Expr *FromE) {
+  // If the expression already has integral or enumeration type, we're golden.
+  QualType T = FromE->getType();
+  if (T->isIntegralOrEnumerationType())
+    return OS_Array;
+  
+  // If we don't have a class type in C++, there's no way we can get an
+  // expression of integral or enumeration type.
+  const RecordType *RecordTy = T->getAs<RecordType>();
+  if (!RecordTy && T->isObjCObjectPointerType())
+    // All other scalar cases are assumed to be dictionary indexing which
+    // caller handles, with diagnostics if needed.
+    return OS_Dictionary;
+  if (!getLangOpts().CPlusPlus || 
+      !RecordTy || RecordTy->isIncompleteType()) {
+    // No indexing can be done. Issue diagnostics and quit.
+    const Expr *IndexExpr = FromE->IgnoreParenImpCasts();
+    if (isa<StringLiteral>(IndexExpr))
+      Diag(FromE->getExprLoc(), diag::err_objc_subscript_pointer)
+        << T << FixItHint::CreateInsertion(FromE->getExprLoc(), "@");
+    else
+      Diag(FromE->getExprLoc(), diag::err_objc_subscript_type_conversion)
+        << T;
+    return OS_Error;
+  }
+  
+  // We must have a complete class type.
+  if (RequireCompleteType(FromE->getExprLoc(), T, 
+                          PDiag(diag::err_objc_index_incomplete_class_type)
+                          << FromE->getSourceRange()))
+    return OS_Error;
+  
+  // Look for a conversion to an integral, enumeration type, or
+  // objective-C pointer type.
+  UnresolvedSet<4> ViableConversions;
+  UnresolvedSet<4> ExplicitConversions;
+  const UnresolvedSetImpl *Conversions
+    = cast<CXXRecordDecl>(RecordTy->getDecl())->getVisibleConversionFunctions();
+  
+  int NoIntegrals=0, NoObjCIdPointers=0;
+  SmallVector<CXXConversionDecl *, 4> ConversionDecls;
+    
+  for (UnresolvedSetImpl::iterator I = Conversions->begin(),
+       E = Conversions->end();
+       I != E;
+       ++I) {
+    if (CXXConversionDecl *Conversion
+        = dyn_cast<CXXConversionDecl>((*I)->getUnderlyingDecl())) {
+      QualType CT = Conversion->getConversionType().getNonReferenceType();
+      if (CT->isIntegralOrEnumerationType()) {
+        ++NoIntegrals;
+        ConversionDecls.push_back(Conversion);
+      }
+      else if (CT->isObjCIdType() ||CT->isBlockPointerType()) {
+        ++NoObjCIdPointers;
+        ConversionDecls.push_back(Conversion);
+      }
+    }
+  }
+  if (NoIntegrals ==1 && NoObjCIdPointers == 0)
+    return OS_Array;
+  if (NoIntegrals == 0 && NoObjCIdPointers == 1)
+    return OS_Dictionary;
+  if (NoIntegrals == 0 && NoObjCIdPointers == 0) {
+    // No conversion function was found. Issue diagnostic and return.
+    Diag(FromE->getExprLoc(), diag::err_objc_subscript_type_conversion)
+      << FromE->getType();
+    return OS_Error;
+  }
+  Diag(FromE->getExprLoc(), diag::err_objc_multiple_subscript_type_conversion)
+      << FromE->getType();
+  for (unsigned int i = 0; i < ConversionDecls.size(); i++)
+    Diag(ConversionDecls[i]->getLocation(), diag::not_conv_function_declared_at);
+    
+  return OS_Error;
+}
+
+bool ObjCSubscriptOpBuilder::findAtIndexGetter() {
+  if (AtIndexGetter)
+    return true;
+  
+  Expr *BaseExpr = RefExpr->getBaseExpr();
+  QualType BaseT = BaseExpr->getType();
+  
+  QualType ResultType;
+  if (const ObjCObjectPointerType *PTy =
+      BaseT->getAs<ObjCObjectPointerType>()) {
+    ResultType = PTy->getPointeeType();
+    if (const ObjCObjectType *iQFaceTy = 
+        ResultType->getAsObjCQualifiedInterfaceType())
+      ResultType = iQFaceTy->getBaseType();
+  }
+  Sema::ObjCSubscriptKind Res = 
+    S.CheckSubscriptingKind(RefExpr->getKeyExpr());
+  if (Res == Sema::OS_Error)
+    return false;
+  bool arrayRef = (Res == Sema::OS_Array);
+  
+  if (ResultType.isNull()) {
+    S.Diag(BaseExpr->getExprLoc(), diag::err_objc_subscript_base_type)
+      << BaseExpr->getType() << arrayRef;
+    return false;
+  }
+  if (!arrayRef) {
+    // dictionary subscripting.
+    // - (id)objectForKeyedSubscript:(id)key;
+    IdentifierInfo *KeyIdents[] = {
+      &S.Context.Idents.get("objectForKeyedSubscript")  
+    };
+    AtIndexGetterSelector = S.Context.Selectors.getSelector(1, KeyIdents);
+  }
+  else {
+    // - (id)objectAtIndexedSubscript:(size_t)index;
+    IdentifierInfo *KeyIdents[] = {
+      &S.Context.Idents.get("objectAtIndexedSubscript")  
+    };
+  
+    AtIndexGetterSelector = S.Context.Selectors.getSelector(1, KeyIdents);
+  }
+  
+  AtIndexGetter = S.LookupMethodInObjectType(AtIndexGetterSelector, ResultType, 
+                                             true /*instance*/);
+  bool receiverIdType = (BaseT->isObjCIdType() ||
+                         BaseT->isObjCQualifiedIdType());
+  
+  if (!AtIndexGetter && S.getLangOpts().DebuggerObjCLiteral) {
+    AtIndexGetter = ObjCMethodDecl::Create(S.Context, SourceLocation(), 
+                           SourceLocation(), AtIndexGetterSelector,
+                           S.Context.getObjCIdType() /*ReturnType*/,
+                           0 /*TypeSourceInfo */,
+                           S.Context.getTranslationUnitDecl(),
+                           true /*Instance*/, false/*isVariadic*/,
+                           /*isSynthesized=*/false,
+                           /*isImplicitlyDeclared=*/true, /*isDefined=*/false,
+                           ObjCMethodDecl::Required,
+                           false);
+    ParmVarDecl *Argument = ParmVarDecl::Create(S.Context, AtIndexGetter,
+                                                SourceLocation(), SourceLocation(),
+                                                arrayRef ? &S.Context.Idents.get("index")
+                                                         : &S.Context.Idents.get("key"),
+                                                arrayRef ? S.Context.UnsignedLongTy
+                                                         : S.Context.getObjCIdType(),
+                                                /*TInfo=*/0,
+                                                SC_None,
+                                                SC_None,
+                                                0);
+    AtIndexGetter->setMethodParams(S.Context, Argument, 
+                                   ArrayRef<SourceLocation>());
+  }
+
+  if (!AtIndexGetter) {
+    if (!receiverIdType) {
+      S.Diag(BaseExpr->getExprLoc(), diag::err_objc_subscript_method_not_found)
+      << BaseExpr->getType() << 0 << arrayRef;
+      return false;
+    }
+    AtIndexGetter = 
+      S.LookupInstanceMethodInGlobalPool(AtIndexGetterSelector, 
+                                         RefExpr->getSourceRange(), 
+                                         true, false);
+  }
+  
+  if (AtIndexGetter) {
+    QualType T = AtIndexGetter->param_begin()[0]->getType();
+    if ((arrayRef && !T->isIntegralOrEnumerationType()) ||
+        (!arrayRef && !T->isObjCObjectPointerType())) {
+      S.Diag(RefExpr->getKeyExpr()->getExprLoc(), 
+             arrayRef ? diag::err_objc_subscript_index_type
+                      : diag::err_objc_subscript_key_type) << T;
+      S.Diag(AtIndexGetter->param_begin()[0]->getLocation(), 
+             diag::note_parameter_type) << T;
+      return false;
+    }
+    QualType R = AtIndexGetter->getResultType();
+    if (!R->isObjCObjectPointerType()) {
+      S.Diag(RefExpr->getKeyExpr()->getExprLoc(),
+             diag::err_objc_indexing_method_result_type) << R << arrayRef;
+      S.Diag(AtIndexGetter->getLocation(), diag::note_method_declared_at) <<
+        AtIndexGetter->getDeclName();
+    }
+  }
+  return true;
+}
+
+bool ObjCSubscriptOpBuilder::findAtIndexSetter() {
+  if (AtIndexSetter)
+    return true;
+  
+  Expr *BaseExpr = RefExpr->getBaseExpr();
+  QualType BaseT = BaseExpr->getType();
+  
+  QualType ResultType;
+  if (const ObjCObjectPointerType *PTy =
+      BaseT->getAs<ObjCObjectPointerType>()) {
+    ResultType = PTy->getPointeeType();
+    if (const ObjCObjectType *iQFaceTy = 
+        ResultType->getAsObjCQualifiedInterfaceType())
+      ResultType = iQFaceTy->getBaseType();
+  }
+  
+  Sema::ObjCSubscriptKind Res = 
+    S.CheckSubscriptingKind(RefExpr->getKeyExpr());
+  if (Res == Sema::OS_Error)
+    return false;
+  bool arrayRef = (Res == Sema::OS_Array);
+  
+  if (ResultType.isNull()) {
+    S.Diag(BaseExpr->getExprLoc(), diag::err_objc_subscript_base_type)
+      << BaseExpr->getType() << arrayRef;
+    return false;
+  }
+  
+  if (!arrayRef) {
+    // dictionary subscripting.
+    // - (void)setObject:(id)object forKeyedSubscript:(id)key;
+    IdentifierInfo *KeyIdents[] = {
+      &S.Context.Idents.get("setObject"),
+      &S.Context.Idents.get("forKeyedSubscript")
+    };
+    AtIndexSetterSelector = S.Context.Selectors.getSelector(2, KeyIdents);
+  }
+  else {
+    // - (void)setObject:(id)object atIndexedSubscript:(NSInteger)index;
+    IdentifierInfo *KeyIdents[] = {
+      &S.Context.Idents.get("setObject"),
+      &S.Context.Idents.get("atIndexedSubscript")
+    };
+    AtIndexSetterSelector = S.Context.Selectors.getSelector(2, KeyIdents);
+  }
+  AtIndexSetter = S.LookupMethodInObjectType(AtIndexSetterSelector, ResultType, 
+                                             true /*instance*/);
+  
+  bool receiverIdType = (BaseT->isObjCIdType() ||
+                         BaseT->isObjCQualifiedIdType());
+
+  if (!AtIndexSetter && S.getLangOpts().DebuggerObjCLiteral) {
+    TypeSourceInfo *ResultTInfo = 0;
+    QualType ReturnType = S.Context.VoidTy;
+    AtIndexSetter = ObjCMethodDecl::Create(S.Context, SourceLocation(),
+                           SourceLocation(), AtIndexSetterSelector,
+                           ReturnType,
+                           ResultTInfo,
+                           S.Context.getTranslationUnitDecl(),
+                           true /*Instance*/, false/*isVariadic*/,
+                           /*isSynthesized=*/false,
+                           /*isImplicitlyDeclared=*/true, /*isDefined=*/false,
+                           ObjCMethodDecl::Required,
+                           false); 
+    SmallVector<ParmVarDecl *, 2> Params;
+    ParmVarDecl *object = ParmVarDecl::Create(S.Context, AtIndexSetter,
+                                                SourceLocation(), SourceLocation(),
+                                                &S.Context.Idents.get("object"),
+                                                S.Context.getObjCIdType(),
+                                                /*TInfo=*/0,
+                                                SC_None,
+                                                SC_None,
+                                                0);
+    Params.push_back(object);
+    ParmVarDecl *key = ParmVarDecl::Create(S.Context, AtIndexSetter,
+                                                SourceLocation(), SourceLocation(),
+                                                arrayRef ?  &S.Context.Idents.get("index")
+                                                         :  &S.Context.Idents.get("key"),
+                                                arrayRef ? S.Context.UnsignedLongTy
+                                                         : S.Context.getObjCIdType(),
+                                                /*TInfo=*/0,
+                                                SC_None,
+                                                SC_None,
+                                                0);
+    Params.push_back(key);
+    AtIndexSetter->setMethodParams(S.Context, Params, ArrayRef<SourceLocation>());
+  }
+  
+  if (!AtIndexSetter) {
+    if (!receiverIdType) {
+      S.Diag(BaseExpr->getExprLoc(), 
+             diag::err_objc_subscript_method_not_found)
+      << BaseExpr->getType() << 1 << arrayRef;
+      return false;
+    }
+    AtIndexSetter = 
+      S.LookupInstanceMethodInGlobalPool(AtIndexSetterSelector, 
+                                         RefExpr->getSourceRange(), 
+                                         true, false);
+  }
+  
+  bool err = false;
+  if (AtIndexSetter && arrayRef) {
+    QualType T = AtIndexSetter->param_begin()[1]->getType();
+    if (!T->isIntegralOrEnumerationType()) {
+      S.Diag(RefExpr->getKeyExpr()->getExprLoc(), 
+             diag::err_objc_subscript_index_type) << T;
+      S.Diag(AtIndexSetter->param_begin()[1]->getLocation(), 
+             diag::note_parameter_type) << T;
+      err = true;
+    }
+    T = AtIndexSetter->param_begin()[0]->getType();
+    if (!T->isObjCObjectPointerType()) {
+      S.Diag(RefExpr->getBaseExpr()->getExprLoc(), 
+             diag::err_objc_subscript_object_type) << T << arrayRef;
+      S.Diag(AtIndexSetter->param_begin()[0]->getLocation(), 
+             diag::note_parameter_type) << T;
+      err = true;
+    }
+  }
+  else if (AtIndexSetter && !arrayRef)
+    for (unsigned i=0; i <2; i++) {
+      QualType T = AtIndexSetter->param_begin()[i]->getType();
+      if (!T->isObjCObjectPointerType()) {
+        if (i == 1)
+          S.Diag(RefExpr->getKeyExpr()->getExprLoc(),
+                 diag::err_objc_subscript_key_type) << T;
+        else
+          S.Diag(RefExpr->getBaseExpr()->getExprLoc(),
+                 diag::err_objc_subscript_dic_object_type) << T;
+        S.Diag(AtIndexSetter->param_begin()[i]->getLocation(), 
+               diag::note_parameter_type) << T;
+        err = true;
+      }
+    }
+
+  return !err;
+}
+
+// Get the object at "Index" position in the container.
+// [BaseExpr objectAtIndexedSubscript : IndexExpr];
+ExprResult ObjCSubscriptOpBuilder::buildGet() {
+  if (!findAtIndexGetter())
+    return ExprError();
+  
+  QualType receiverType = InstanceBase->getType();
+    
+  // Build a message-send.
+  ExprResult msg;
+  Expr *Index = InstanceKey;
+  
+  // Arguments.
+  Expr *args[] = { Index };
+  assert(InstanceBase);
+  msg = S.BuildInstanceMessageImplicit(InstanceBase, receiverType,
+                                       GenericLoc,
+                                       AtIndexGetterSelector, AtIndexGetter,
+                                       MultiExprArg(args, 1));
+  return msg;
+}
+
+/// Store into the container the "op" object at "Index"'ed location
+/// by building this messaging expression:
+/// - (void)setObject:(id)object atIndexedSubscript:(NSInteger)index;
+/// \param bindSetValueAsResult - If true, capture the actual
+///   value being set as the value of the property operation.
+ExprResult ObjCSubscriptOpBuilder::buildSet(Expr *op, SourceLocation opcLoc,
+                                           bool captureSetValueAsResult) {
+  if (!findAtIndexSetter())
+    return ExprError();
+  
+  QualType receiverType = InstanceBase->getType();
+  Expr *Index = InstanceKey;
+  
+  // Arguments.
+  Expr *args[] = { op, Index };
+  
+  // Build a message-send.
+  ExprResult msg = S.BuildInstanceMessageImplicit(InstanceBase, receiverType,
+                                                  GenericLoc,
+                                                  AtIndexSetterSelector,
+                                                  AtIndexSetter,
+                                                  MultiExprArg(args, 2));
+  
+  if (!msg.isInvalid() && captureSetValueAsResult) {
+    ObjCMessageExpr *msgExpr =
+      cast<ObjCMessageExpr>(msg.get()->IgnoreImplicit());
+    Expr *arg = msgExpr->getArg(0);
+    msgExpr->setArg(0, captureValueAsResult(arg));
+  }
+  
+  return msg;
+}
+
+//===----------------------------------------------------------------------===//
+//  General Sema routines.
+//===----------------------------------------------------------------------===//
+
+ExprResult Sema::checkPseudoObjectRValue(Expr *E) {
+  Expr *opaqueRef = E->IgnoreParens();
+  if (ObjCPropertyRefExpr *refExpr
+        = dyn_cast<ObjCPropertyRefExpr>(opaqueRef)) {
+    ObjCPropertyOpBuilder builder(*this, refExpr);
+    return builder.buildRValueOperation(E);
+  }
+  else if (ObjCSubscriptRefExpr *refExpr
+           = dyn_cast<ObjCSubscriptRefExpr>(opaqueRef)) {
+    ObjCSubscriptOpBuilder builder(*this, refExpr);
+    return builder.buildRValueOperation(E);
+  } else {
+    llvm_unreachable("unknown pseudo-object kind!");
+  }
+}
+
+/// Check an increment or decrement of a pseudo-object expression.
+ExprResult Sema::checkPseudoObjectIncDec(Scope *Sc, SourceLocation opcLoc,
+                                         UnaryOperatorKind opcode, Expr *op) {
+  // Do nothing if the operand is dependent.
+  if (op->isTypeDependent())
+    return new (Context) UnaryOperator(op, opcode, Context.DependentTy,
+                                       VK_RValue, OK_Ordinary, opcLoc);
+
+  assert(UnaryOperator::isIncrementDecrementOp(opcode));
+  Expr *opaqueRef = op->IgnoreParens();
+  if (ObjCPropertyRefExpr *refExpr
+        = dyn_cast<ObjCPropertyRefExpr>(opaqueRef)) {
+    ObjCPropertyOpBuilder builder(*this, refExpr);
+    return builder.buildIncDecOperation(Sc, opcLoc, opcode, op);
+  } else if (isa<ObjCSubscriptRefExpr>(opaqueRef)) {
+    Diag(opcLoc, diag::err_illegal_container_subscripting_op);
+    return ExprError();
+  } else {
+    llvm_unreachable("unknown pseudo-object kind!");
+  }
+}
+
+ExprResult Sema::checkPseudoObjectAssignment(Scope *S, SourceLocation opcLoc,
+                                             BinaryOperatorKind opcode,
+                                             Expr *LHS, Expr *RHS) {
+  // Do nothing if either argument is dependent.
+  if (LHS->isTypeDependent() || RHS->isTypeDependent())
+    return new (Context) BinaryOperator(LHS, RHS, opcode, Context.DependentTy,
+                                        VK_RValue, OK_Ordinary, opcLoc);
+
+  // Filter out non-overload placeholder types in the RHS.
+  if (RHS->getType()->isNonOverloadPlaceholderType()) {
+    ExprResult result = CheckPlaceholderExpr(RHS);
+    if (result.isInvalid()) return ExprError();
+    RHS = result.take();
+  }
+
+  Expr *opaqueRef = LHS->IgnoreParens();
+  if (ObjCPropertyRefExpr *refExpr
+        = dyn_cast<ObjCPropertyRefExpr>(opaqueRef)) {
+    ObjCPropertyOpBuilder builder(*this, refExpr);
+    return builder.buildAssignmentOperation(S, opcLoc, opcode, LHS, RHS);
+  } else if (ObjCSubscriptRefExpr *refExpr
+             = dyn_cast<ObjCSubscriptRefExpr>(opaqueRef)) {
+    ObjCSubscriptOpBuilder builder(*this, refExpr);
+    return builder.buildAssignmentOperation(S, opcLoc, opcode, LHS, RHS);
+  } else {
+    llvm_unreachable("unknown pseudo-object kind!");
+  }
+}
+
+/// Given a pseudo-object reference, rebuild it without the opaque
+/// values.  Basically, undo the behavior of rebuildAndCaptureObject.
+/// This should never operate in-place.
+static Expr *stripOpaqueValuesFromPseudoObjectRef(Sema &S, Expr *E) {
+  Expr *opaqueRef = E->IgnoreParens();
+  if (ObjCPropertyRefExpr *refExpr
+        = dyn_cast<ObjCPropertyRefExpr>(opaqueRef)) {
+    // Class and super property references don't have opaque values in them.
+    if (refExpr->isClassReceiver() || refExpr->isSuperReceiver())
+      return E;
+    
+    assert(refExpr->isObjectReceiver() && "Unknown receiver kind?");
+    OpaqueValueExpr *baseOVE = cast<OpaqueValueExpr>(refExpr->getBase());
+    return ObjCPropertyRefRebuilder(S, baseOVE->getSourceExpr()).rebuild(E);
+  } else if (ObjCSubscriptRefExpr *refExpr
+               = dyn_cast<ObjCSubscriptRefExpr>(opaqueRef)) {
+    OpaqueValueExpr *baseOVE = cast<OpaqueValueExpr>(refExpr->getBaseExpr());
+    OpaqueValueExpr *keyOVE = cast<OpaqueValueExpr>(refExpr->getKeyExpr());
+    return ObjCSubscriptRefRebuilder(S, baseOVE->getSourceExpr(), 
+                                     keyOVE->getSourceExpr()).rebuild(E);
+  } else {
+    llvm_unreachable("unknown pseudo-object kind!");
+  }
+}
+
+/// Given a pseudo-object expression, recreate what it looks like
+/// syntactically without the attendant OpaqueValueExprs.
+///
+/// This is a hack which should be removed when TreeTransform is
+/// capable of rebuilding a tree without stripping implicit
+/// operations.
+Expr *Sema::recreateSyntacticForm(PseudoObjectExpr *E) {
+  Expr *syntax = E->getSyntacticForm();
+  if (UnaryOperator *uop = dyn_cast<UnaryOperator>(syntax)) {
+    Expr *op = stripOpaqueValuesFromPseudoObjectRef(*this, uop->getSubExpr());
+    return new (Context) UnaryOperator(op, uop->getOpcode(), uop->getType(),
+                                       uop->getValueKind(), uop->getObjectKind(),
+                                       uop->getOperatorLoc());
+  } else if (CompoundAssignOperator *cop
+               = dyn_cast<CompoundAssignOperator>(syntax)) {
+    Expr *lhs = stripOpaqueValuesFromPseudoObjectRef(*this, cop->getLHS());
+    Expr *rhs = cast<OpaqueValueExpr>(cop->getRHS())->getSourceExpr();
+    return new (Context) CompoundAssignOperator(lhs, rhs, cop->getOpcode(),
+                                                cop->getType(),
+                                                cop->getValueKind(),
+                                                cop->getObjectKind(),
+                                                cop->getComputationLHSType(),
+                                                cop->getComputationResultType(),
+                                                cop->getOperatorLoc());
+  } else if (BinaryOperator *bop = dyn_cast<BinaryOperator>(syntax)) {
+    Expr *lhs = stripOpaqueValuesFromPseudoObjectRef(*this, bop->getLHS());
+    Expr *rhs = cast<OpaqueValueExpr>(bop->getRHS())->getSourceExpr();
+    return new (Context) BinaryOperator(lhs, rhs, bop->getOpcode(),
+                                        bop->getType(), bop->getValueKind(),
+                                        bop->getObjectKind(),
+                                        bop->getOperatorLoc());
+  } else {
+    assert(syntax->hasPlaceholderType(BuiltinType::PseudoObject));
+    return stripOpaqueValuesFromPseudoObjectRef(*this, syntax);
+  }
+}
diff --git a/clang/lib/Sema/SemaStmt.cpp b/clang/lib/Sema/SemaStmt.cpp
new file mode 100644
index 0000000..9052278
--- /dev/null
+++ b/clang/lib/Sema/SemaStmt.cpp
@@ -0,0 +1,2663 @@
+//===--- SemaStmt.cpp - Semantic Analysis for Statements ------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+//  This file implements semantic analysis for statements.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Sema/SemaInternal.h"
+#include "clang/Sema/Scope.h"
+#include "clang/Sema/ScopeInfo.h"
+#include "clang/Sema/Initialization.h"
+#include "clang/Sema/Lookup.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/CharUnits.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/AST/ExprCXX.h"
+#include "clang/AST/ExprObjC.h"
+#include "clang/AST/StmtObjC.h"
+#include "clang/AST/StmtCXX.h"
+#include "clang/AST/TypeLoc.h"
+#include "clang/Lex/Preprocessor.h"
+#include "clang/Basic/TargetInfo.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SmallVector.h"
+using namespace clang;
+using namespace sema;
+
+StmtResult Sema::ActOnExprStmt(FullExprArg expr) {
+  Expr *E = expr.get();
+  if (!E) // FIXME: FullExprArg has no error state?
+    return StmtError();
+
+  // C99 6.8.3p2: The expression in an expression statement is evaluated as a
+  // void expression for its side effects.  Conversion to void allows any
+  // operand, even incomplete types.
+
+  // Same thing in for stmt first clause (when expr) and third clause.
+  return Owned(static_cast<Stmt*>(E));
+}
+
+
+StmtResult Sema::ActOnNullStmt(SourceLocation SemiLoc,
+                               bool HasLeadingEmptyMacro) {
+  return Owned(new (Context) NullStmt(SemiLoc, HasLeadingEmptyMacro));
+}
+
+StmtResult Sema::ActOnDeclStmt(DeclGroupPtrTy dg, SourceLocation StartLoc,
+                               SourceLocation EndLoc) {
+  DeclGroupRef DG = dg.getAsVal<DeclGroupRef>();
+
+  // If we have an invalid decl, just return an error.
+  if (DG.isNull()) return StmtError();
+
+  return Owned(new (Context) DeclStmt(DG, StartLoc, EndLoc));
+}
+
+void Sema::ActOnForEachDeclStmt(DeclGroupPtrTy dg) {
+  DeclGroupRef DG = dg.getAsVal<DeclGroupRef>();
+
+  // If we have an invalid decl, just return.
+  if (DG.isNull() || !DG.isSingleDecl()) return;
+  VarDecl *var = cast<VarDecl>(DG.getSingleDecl());
+
+  // suppress any potential 'unused variable' warning.
+  var->setUsed();
+
+  // foreach variables are never actually initialized in the way that
+  // the parser came up with.
+  var->setInit(0);
+
+  // In ARC, we don't need to retain the iteration variable of a fast
+  // enumeration loop.  Rather than actually trying to catch that
+  // during declaration processing, we remove the consequences here.
+  if (getLangOpts().ObjCAutoRefCount) {
+    QualType type = var->getType();
+
+    // Only do this if we inferred the lifetime.  Inferred lifetime
+    // will show up as a local qualifier because explicit lifetime
+    // should have shown up as an AttributedType instead.
+    if (type.getLocalQualifiers().getObjCLifetime() == Qualifiers::OCL_Strong) {
+      // Add 'const' and mark the variable as pseudo-strong.
+      var->setType(type.withConst());
+      var->setARCPseudoStrong(true);
+    }
+  }
+}
+
+/// \brief Diagnose unused '==' and '!=' as likely typos for '=' or '|='.
+///
+/// Adding a cast to void (or other expression wrappers) will prevent the
+/// warning from firing.
+static bool DiagnoseUnusedComparison(Sema &S, const Expr *E) {
+  SourceLocation Loc;
+  bool IsNotEqual, CanAssign;
+
+  if (const BinaryOperator *Op = dyn_cast<BinaryOperator>(E)) {
+    if (Op->getOpcode() != BO_EQ && Op->getOpcode() != BO_NE)
+      return false;
+
+    Loc = Op->getOperatorLoc();
+    IsNotEqual = Op->getOpcode() == BO_NE;
+    CanAssign = Op->getLHS()->IgnoreParenImpCasts()->isLValue();
+  } else if (const CXXOperatorCallExpr *Op = dyn_cast<CXXOperatorCallExpr>(E)) {
+    if (Op->getOperator() != OO_EqualEqual &&
+        Op->getOperator() != OO_ExclaimEqual)
+      return false;
+
+    Loc = Op->getOperatorLoc();
+    IsNotEqual = Op->getOperator() == OO_ExclaimEqual;
+    CanAssign = Op->getArg(0)->IgnoreParenImpCasts()->isLValue();
+  } else {
+    // Not a typo-prone comparison.
+    return false;
+  }
+
+  // Suppress warnings when the operator, suspicious as it may be, comes from
+  // a macro expansion.
+  if (Loc.isMacroID())
+    return false;
+
+  S.Diag(Loc, diag::warn_unused_comparison)
+    << (unsigned)IsNotEqual << E->getSourceRange();
+
+  // If the LHS is a plausible entity to assign to, provide a fixit hint to
+  // correct common typos.
+  if (CanAssign) {
+    if (IsNotEqual)
+      S.Diag(Loc, diag::note_inequality_comparison_to_or_assign)
+        << FixItHint::CreateReplacement(Loc, "|=");
+    else
+      S.Diag(Loc, diag::note_equality_comparison_to_assign)
+        << FixItHint::CreateReplacement(Loc, "=");
+  }
+
+  return true;
+}
+
+void Sema::DiagnoseUnusedExprResult(const Stmt *S) {
+  if (const LabelStmt *Label = dyn_cast_or_null<LabelStmt>(S))
+    return DiagnoseUnusedExprResult(Label->getSubStmt());
+
+  const Expr *E = dyn_cast_or_null<Expr>(S);
+  if (!E)
+    return;
+
+  SourceLocation Loc;
+  SourceRange R1, R2;
+  if (SourceMgr.isInSystemMacro(E->getExprLoc()) ||
+      !E->isUnusedResultAWarning(Loc, R1, R2, Context))
+    return;
+
+  // Okay, we have an unused result.  Depending on what the base expression is,
+  // we might want to make a more specific diagnostic.  Check for one of these
+  // cases now.
+  unsigned DiagID = diag::warn_unused_expr;
+  if (const ExprWithCleanups *Temps = dyn_cast<ExprWithCleanups>(E))
+    E = Temps->getSubExpr();
+  if (const CXXBindTemporaryExpr *TempExpr = dyn_cast<CXXBindTemporaryExpr>(E))
+    E = TempExpr->getSubExpr();
+
+  if (DiagnoseUnusedComparison(*this, E))
+    return;
+
+  E = E->IgnoreParenImpCasts();
+  if (const CallExpr *CE = dyn_cast<CallExpr>(E)) {
+    if (E->getType()->isVoidType())
+      return;
+
+    // If the callee has attribute pure, const, or warn_unused_result, warn with
+    // a more specific message to make it clear what is happening.
+    if (const Decl *FD = CE->getCalleeDecl()) {
+      if (FD->getAttr<WarnUnusedResultAttr>()) {
+        Diag(Loc, diag::warn_unused_result) << R1 << R2;
+        return;
+      }
+      if (FD->getAttr<PureAttr>()) {
+        Diag(Loc, diag::warn_unused_call) << R1 << R2 << "pure";
+        return;
+      }
+      if (FD->getAttr<ConstAttr>()) {
+        Diag(Loc, diag::warn_unused_call) << R1 << R2 << "const";
+        return;
+      }
+    }
+  } else if (const ObjCMessageExpr *ME = dyn_cast<ObjCMessageExpr>(E)) {
+    if (getLangOpts().ObjCAutoRefCount && ME->isDelegateInitCall()) {
+      Diag(Loc, diag::err_arc_unused_init_message) << R1;
+      return;
+    }
+    const ObjCMethodDecl *MD = ME->getMethodDecl();
+    if (MD && MD->getAttr<WarnUnusedResultAttr>()) {
+      Diag(Loc, diag::warn_unused_result) << R1 << R2;
+      return;
+    }
+  } else if (const PseudoObjectExpr *POE = dyn_cast<PseudoObjectExpr>(E)) {
+    const Expr *Source = POE->getSyntacticForm();
+    if (isa<ObjCSubscriptRefExpr>(Source))
+      DiagID = diag::warn_unused_container_subscript_expr;
+    else
+      DiagID = diag::warn_unused_property_expr;
+  } else if (const CXXFunctionalCastExpr *FC
+                                       = dyn_cast<CXXFunctionalCastExpr>(E)) {
+    if (isa<CXXConstructExpr>(FC->getSubExpr()) ||
+        isa<CXXTemporaryObjectExpr>(FC->getSubExpr()))
+      return;
+  }
+  // Diagnose "(void*) blah" as a typo for "(void) blah".
+  else if (const CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(E)) {
+    TypeSourceInfo *TI = CE->getTypeInfoAsWritten();
+    QualType T = TI->getType();
+
+    // We really do want to use the non-canonical type here.
+    if (T == Context.VoidPtrTy) {
+      PointerTypeLoc TL = cast<PointerTypeLoc>(TI->getTypeLoc());
+
+      Diag(Loc, diag::warn_unused_voidptr)
+        << FixItHint::CreateRemoval(TL.getStarLoc());
+      return;
+    }
+  }
+
+  DiagRuntimeBehavior(Loc, 0, PDiag(DiagID) << R1 << R2);
+}
+
+void Sema::ActOnStartOfCompoundStmt() {
+  PushCompoundScope();
+}
+
+void Sema::ActOnFinishOfCompoundStmt() {
+  PopCompoundScope();
+}
+
+sema::CompoundScopeInfo &Sema::getCurCompoundScope() const {
+  return getCurFunction()->CompoundScopes.back();
+}
+
+StmtResult
+Sema::ActOnCompoundStmt(SourceLocation L, SourceLocation R,
+                        MultiStmtArg elts, bool isStmtExpr) {
+  unsigned NumElts = elts.size();
+  Stmt **Elts = reinterpret_cast<Stmt**>(elts.release());
+  // If we're in C89 mode, check that we don't have any decls after stmts.  If
+  // so, emit an extension diagnostic.
+  if (!getLangOpts().C99 && !getLangOpts().CPlusPlus) {
+    // Note that __extension__ can be around a decl.
+    unsigned i = 0;
+    // Skip over all declarations.
+    for (; i != NumElts && isa<DeclStmt>(Elts[i]); ++i)
+      /*empty*/;
+
+    // We found the end of the list or a statement.  Scan for another declstmt.
+    for (; i != NumElts && !isa<DeclStmt>(Elts[i]); ++i)
+      /*empty*/;
+
+    if (i != NumElts) {
+      Decl *D = *cast<DeclStmt>(Elts[i])->decl_begin();
+      Diag(D->getLocation(), diag::ext_mixed_decls_code);
+    }
+  }
+  // Warn about unused expressions in statements.
+  for (unsigned i = 0; i != NumElts; ++i) {
+    // Ignore statements that are last in a statement expression.
+    if (isStmtExpr && i == NumElts - 1)
+      continue;
+
+    DiagnoseUnusedExprResult(Elts[i]);
+  }
+
+  // Check for suspicious empty body (null statement) in `for' and `while'
+  // statements.  Don't do anything for template instantiations, this just adds
+  // noise.
+  if (NumElts != 0 && !CurrentInstantiationScope &&
+      getCurCompoundScope().HasEmptyLoopBodies) {
+    for (unsigned i = 0; i != NumElts - 1; ++i)
+      DiagnoseEmptyLoopBody(Elts[i], Elts[i + 1]);
+  }
+
+  return Owned(new (Context) CompoundStmt(Context, Elts, NumElts, L, R));
+}
+
+StmtResult
+Sema::ActOnCaseStmt(SourceLocation CaseLoc, Expr *LHSVal,
+                    SourceLocation DotDotDotLoc, Expr *RHSVal,
+                    SourceLocation ColonLoc) {
+  assert((LHSVal != 0) && "missing expression in case statement");
+
+  if (getCurFunction()->SwitchStack.empty()) {
+    Diag(CaseLoc, diag::err_case_not_in_switch);
+    return StmtError();
+  }
+
+  if (!getLangOpts().CPlusPlus0x) {
+    // C99 6.8.4.2p3: The expression shall be an integer constant.
+    // However, GCC allows any evaluatable integer expression.
+    if (!LHSVal->isTypeDependent() && !LHSVal->isValueDependent()) {
+      LHSVal = VerifyIntegerConstantExpression(LHSVal).take();
+      if (!LHSVal)
+        return StmtError();
+    }
+
+    // GCC extension: The expression shall be an integer constant.
+
+    if (RHSVal && !RHSVal->isTypeDependent() && !RHSVal->isValueDependent()) {
+      RHSVal = VerifyIntegerConstantExpression(RHSVal).take();
+      // Recover from an error by just forgetting about it.
+    }
+  }
+
+  CaseStmt *CS = new (Context) CaseStmt(LHSVal, RHSVal, CaseLoc, DotDotDotLoc,
+                                        ColonLoc);
+  getCurFunction()->SwitchStack.back()->addSwitchCase(CS);
+  return Owned(CS);
+}
+
+/// ActOnCaseStmtBody - This installs a statement as the body of a case.
+void Sema::ActOnCaseStmtBody(Stmt *caseStmt, Stmt *SubStmt) {
+  DiagnoseUnusedExprResult(SubStmt);
+
+  CaseStmt *CS = static_cast<CaseStmt*>(caseStmt);
+  CS->setSubStmt(SubStmt);
+}
+
+StmtResult
+Sema::ActOnDefaultStmt(SourceLocation DefaultLoc, SourceLocation ColonLoc,
+                       Stmt *SubStmt, Scope *CurScope) {
+  DiagnoseUnusedExprResult(SubStmt);
+
+  if (getCurFunction()->SwitchStack.empty()) {
+    Diag(DefaultLoc, diag::err_default_not_in_switch);
+    return Owned(SubStmt);
+  }
+
+  DefaultStmt *DS = new (Context) DefaultStmt(DefaultLoc, ColonLoc, SubStmt);
+  getCurFunction()->SwitchStack.back()->addSwitchCase(DS);
+  return Owned(DS);
+}
+
+StmtResult
+Sema::ActOnLabelStmt(SourceLocation IdentLoc, LabelDecl *TheDecl,
+                     SourceLocation ColonLoc, Stmt *SubStmt) {
+  // If the label was multiply defined, reject it now.
+  if (TheDecl->getStmt()) {
+    Diag(IdentLoc, diag::err_redefinition_of_label) << TheDecl->getDeclName();
+    Diag(TheDecl->getLocation(), diag::note_previous_definition);
+    return Owned(SubStmt);
+  }
+
+  // Otherwise, things are good.  Fill in the declaration and return it.
+  LabelStmt *LS = new (Context) LabelStmt(IdentLoc, TheDecl, SubStmt);
+  TheDecl->setStmt(LS);
+  if (!TheDecl->isGnuLocal())
+    TheDecl->setLocation(IdentLoc);
+  return Owned(LS);
+}
+
+StmtResult Sema::ActOnAttributedStmt(SourceLocation AttrLoc,
+                                     const AttrVec &Attrs,
+                                     Stmt *SubStmt) {
+  // Fill in the declaration and return it. Variable length will require to
+  // change this to AttributedStmt::Create(Context, ....);
+  // and probably using ArrayRef
+  AttributedStmt *LS = new (Context) AttributedStmt(AttrLoc, Attrs, SubStmt);
+  return Owned(LS);
+}
+
+StmtResult
+Sema::ActOnIfStmt(SourceLocation IfLoc, FullExprArg CondVal, Decl *CondVar,
+                  Stmt *thenStmt, SourceLocation ElseLoc,
+                  Stmt *elseStmt) {
+  ExprResult CondResult(CondVal.release());
+
+  VarDecl *ConditionVar = 0;
+  if (CondVar) {
+    ConditionVar = cast<VarDecl>(CondVar);
+    CondResult = CheckConditionVariable(ConditionVar, IfLoc, true);
+    if (CondResult.isInvalid())
+      return StmtError();
+  }
+  Expr *ConditionExpr = CondResult.takeAs<Expr>();
+  if (!ConditionExpr)
+    return StmtError();
+
+  DiagnoseUnusedExprResult(thenStmt);
+
+  if (!elseStmt) {
+    DiagnoseEmptyStmtBody(ConditionExpr->getLocEnd(), thenStmt,
+                          diag::warn_empty_if_body);
+  }
+
+  DiagnoseUnusedExprResult(elseStmt);
+
+  return Owned(new (Context) IfStmt(Context, IfLoc, ConditionVar, ConditionExpr,
+                                    thenStmt, ElseLoc, elseStmt));
+}
+
+/// ConvertIntegerToTypeWarnOnOverflow - Convert the specified APInt to have
+/// the specified width and sign.  If an overflow occurs, detect it and emit
+/// the specified diagnostic.
+void Sema::ConvertIntegerToTypeWarnOnOverflow(llvm::APSInt &Val,
+                                              unsigned NewWidth, bool NewSign,
+                                              SourceLocation Loc,
+                                              unsigned DiagID) {
+  // Perform a conversion to the promoted condition type if needed.
+  if (NewWidth > Val.getBitWidth()) {
+    // If this is an extension, just do it.
+    Val = Val.extend(NewWidth);
+    Val.setIsSigned(NewSign);
+
+    // If the input was signed and negative and the output is
+    // unsigned, don't bother to warn: this is implementation-defined
+    // behavior.
+    // FIXME: Introduce a second, default-ignored warning for this case?
+  } else if (NewWidth < Val.getBitWidth()) {
+    // If this is a truncation, check for overflow.
+    llvm::APSInt ConvVal(Val);
+    ConvVal = ConvVal.trunc(NewWidth);
+    ConvVal.setIsSigned(NewSign);
+    ConvVal = ConvVal.extend(Val.getBitWidth());
+    ConvVal.setIsSigned(Val.isSigned());
+    if (ConvVal != Val)
+      Diag(Loc, DiagID) << Val.toString(10) << ConvVal.toString(10);
+
+    // Regardless of whether a diagnostic was emitted, really do the
+    // truncation.
+    Val = Val.trunc(NewWidth);
+    Val.setIsSigned(NewSign);
+  } else if (NewSign != Val.isSigned()) {
+    // Convert the sign to match the sign of the condition.  This can cause
+    // overflow as well: unsigned(INTMIN)
+    // We don't diagnose this overflow, because it is implementation-defined
+    // behavior.
+    // FIXME: Introduce a second, default-ignored warning for this case?
+    llvm::APSInt OldVal(Val);
+    Val.setIsSigned(NewSign);
+  }
+}
+
+namespace {
+  struct CaseCompareFunctor {
+    bool operator()(const std::pair<llvm::APSInt, CaseStmt*> &LHS,
+                    const llvm::APSInt &RHS) {
+      return LHS.first < RHS;
+    }
+    bool operator()(const std::pair<llvm::APSInt, CaseStmt*> &LHS,
+                    const std::pair<llvm::APSInt, CaseStmt*> &RHS) {
+      return LHS.first < RHS.first;
+    }
+    bool operator()(const llvm::APSInt &LHS,
+                    const std::pair<llvm::APSInt, CaseStmt*> &RHS) {
+      return LHS < RHS.first;
+    }
+  };
+}
+
+/// CmpCaseVals - Comparison predicate for sorting case values.
+///
+static bool CmpCaseVals(const std::pair<llvm::APSInt, CaseStmt*>& lhs,
+                        const std::pair<llvm::APSInt, CaseStmt*>& rhs) {
+  if (lhs.first < rhs.first)
+    return true;
+
+  if (lhs.first == rhs.first &&
+      lhs.second->getCaseLoc().getRawEncoding()
+       < rhs.second->getCaseLoc().getRawEncoding())
+    return true;
+  return false;
+}
+
+/// CmpEnumVals - Comparison predicate for sorting enumeration values.
+///
+static bool CmpEnumVals(const std::pair<llvm::APSInt, EnumConstantDecl*>& lhs,
+                        const std::pair<llvm::APSInt, EnumConstantDecl*>& rhs)
+{
+  return lhs.first < rhs.first;
+}
+
+/// EqEnumVals - Comparison preficate for uniqing enumeration values.
+///
+static bool EqEnumVals(const std::pair<llvm::APSInt, EnumConstantDecl*>& lhs,
+                       const std::pair<llvm::APSInt, EnumConstantDecl*>& rhs)
+{
+  return lhs.first == rhs.first;
+}
+
+/// GetTypeBeforeIntegralPromotion - Returns the pre-promotion type of
+/// potentially integral-promoted expression @p expr.
+static QualType GetTypeBeforeIntegralPromotion(Expr *&expr) {
+  if (ExprWithCleanups *cleanups = dyn_cast<ExprWithCleanups>(expr))
+    expr = cleanups->getSubExpr();
+  while (ImplicitCastExpr *impcast = dyn_cast<ImplicitCastExpr>(expr)) {
+    if (impcast->getCastKind() != CK_IntegralCast) break;
+    expr = impcast->getSubExpr();
+  }
+  return expr->getType();
+}
+
+StmtResult
+Sema::ActOnStartOfSwitchStmt(SourceLocation SwitchLoc, Expr *Cond,
+                             Decl *CondVar) {
+  ExprResult CondResult;
+
+  VarDecl *ConditionVar = 0;
+  if (CondVar) {
+    ConditionVar = cast<VarDecl>(CondVar);
+    CondResult = CheckConditionVariable(ConditionVar, SourceLocation(), false);
+    if (CondResult.isInvalid())
+      return StmtError();
+
+    Cond = CondResult.release();
+  }
+
+  if (!Cond)
+    return StmtError();
+
+  CondResult
+    = ConvertToIntegralOrEnumerationType(SwitchLoc, Cond,
+                          PDiag(diag::err_typecheck_statement_requires_integer),
+                                   PDiag(diag::err_switch_incomplete_class_type)
+                                     << Cond->getSourceRange(),
+                                   PDiag(diag::err_switch_explicit_conversion),
+                                         PDiag(diag::note_switch_conversion),
+                                   PDiag(diag::err_switch_multiple_conversions),
+                                         PDiag(diag::note_switch_conversion),
+                                         PDiag(0),
+                                         /*AllowScopedEnumerations*/ true);
+  if (CondResult.isInvalid()) return StmtError();
+  Cond = CondResult.take();
+
+  // C99 6.8.4.2p5 - Integer promotions are performed on the controlling expr.
+  CondResult = UsualUnaryConversions(Cond);
+  if (CondResult.isInvalid()) return StmtError();
+  Cond = CondResult.take();
+
+  if (!CondVar) {
+    CheckImplicitConversions(Cond, SwitchLoc);
+    CondResult = MaybeCreateExprWithCleanups(Cond);
+    if (CondResult.isInvalid())
+      return StmtError();
+    Cond = CondResult.take();
+  }
+
+  getCurFunction()->setHasBranchIntoScope();
+
+  SwitchStmt *SS = new (Context) SwitchStmt(Context, ConditionVar, Cond);
+  getCurFunction()->SwitchStack.push_back(SS);
+  return Owned(SS);
+}
+
+static void AdjustAPSInt(llvm::APSInt &Val, unsigned BitWidth, bool IsSigned) {
+  if (Val.getBitWidth() < BitWidth)
+    Val = Val.extend(BitWidth);
+  else if (Val.getBitWidth() > BitWidth)
+    Val = Val.trunc(BitWidth);
+  Val.setIsSigned(IsSigned);
+}
+
+StmtResult
+Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch,
+                            Stmt *BodyStmt) {
+  SwitchStmt *SS = cast<SwitchStmt>(Switch);
+  assert(SS == getCurFunction()->SwitchStack.back() &&
+         "switch stack missing push/pop!");
+
+  SS->setBody(BodyStmt, SwitchLoc);
+  getCurFunction()->SwitchStack.pop_back();
+
+  Expr *CondExpr = SS->getCond();
+  if (!CondExpr) return StmtError();
+
+  QualType CondType = CondExpr->getType();
+
+  Expr *CondExprBeforePromotion = CondExpr;
+  QualType CondTypeBeforePromotion =
+      GetTypeBeforeIntegralPromotion(CondExprBeforePromotion);
+
+  // C++ 6.4.2.p2:
+  // Integral promotions are performed (on the switch condition).
+  //
+  // A case value unrepresentable by the original switch condition
+  // type (before the promotion) doesn't make sense, even when it can
+  // be represented by the promoted type.  Therefore we need to find
+  // the pre-promotion type of the switch condition.
+  if (!CondExpr->isTypeDependent()) {
+    // We have already converted the expression to an integral or enumeration
+    // type, when we started the switch statement. If we don't have an
+    // appropriate type now, just return an error.
+    if (!CondType->isIntegralOrEnumerationType())
+      return StmtError();
+
+    if (CondExpr->isKnownToHaveBooleanValue()) {
+      // switch(bool_expr) {...} is often a programmer error, e.g.
+      //   switch(n && mask) { ... }  // Doh - should be "n & mask".
+      // One can always use an if statement instead of switch(bool_expr).
+      Diag(SwitchLoc, diag::warn_bool_switch_condition)
+          << CondExpr->getSourceRange();
+    }
+  }
+
+  // Get the bitwidth of the switched-on value before promotions.  We must
+  // convert the integer case values to this width before comparison.
+  bool HasDependentValue
+    = CondExpr->isTypeDependent() || CondExpr->isValueDependent();
+  unsigned CondWidth
+    = HasDependentValue ? 0 : Context.getIntWidth(CondTypeBeforePromotion);
+  bool CondIsSigned 
+    = CondTypeBeforePromotion->isSignedIntegerOrEnumerationType();
+
+  // Accumulate all of the case values in a vector so that we can sort them
+  // and detect duplicates.  This vector contains the APInt for the case after
+  // it has been converted to the condition type.
+  typedef SmallVector<std::pair<llvm::APSInt, CaseStmt*>, 64> CaseValsTy;
+  CaseValsTy CaseVals;
+
+  // Keep track of any GNU case ranges we see.  The APSInt is the low value.
+  typedef std::vector<std::pair<llvm::APSInt, CaseStmt*> > CaseRangesTy;
+  CaseRangesTy CaseRanges;
+
+  DefaultStmt *TheDefaultStmt = 0;
+
+  bool CaseListIsErroneous = false;
+
+  for (SwitchCase *SC = SS->getSwitchCaseList(); SC && !HasDependentValue;
+       SC = SC->getNextSwitchCase()) {
+
+    if (DefaultStmt *DS = dyn_cast<DefaultStmt>(SC)) {
+      if (TheDefaultStmt) {
+        Diag(DS->getDefaultLoc(), diag::err_multiple_default_labels_defined);
+        Diag(TheDefaultStmt->getDefaultLoc(), diag::note_duplicate_case_prev);
+
+        // FIXME: Remove the default statement from the switch block so that
+        // we'll return a valid AST.  This requires recursing down the AST and
+        // finding it, not something we are set up to do right now.  For now,
+        // just lop the entire switch stmt out of the AST.
+        CaseListIsErroneous = true;
+      }
+      TheDefaultStmt = DS;
+
+    } else {
+      CaseStmt *CS = cast<CaseStmt>(SC);
+
+      Expr *Lo = CS->getLHS();
+
+      if (Lo->isTypeDependent() || Lo->isValueDependent()) {
+        HasDependentValue = true;
+        break;
+      }
+
+      llvm::APSInt LoVal;
+
+      if (getLangOpts().CPlusPlus0x) {
+        // C++11 [stmt.switch]p2: the constant-expression shall be a converted
+        // constant expression of the promoted type of the switch condition.
+        ExprResult ConvLo =
+          CheckConvertedConstantExpression(Lo, CondType, LoVal, CCEK_CaseValue);
+        if (ConvLo.isInvalid()) {
+          CaseListIsErroneous = true;
+          continue;
+        }
+        Lo = ConvLo.take();
+      } else {
+        // We already verified that the expression has a i-c-e value (C99
+        // 6.8.4.2p3) - get that value now.
+        LoVal = Lo->EvaluateKnownConstInt(Context);
+
+        // If the LHS is not the same type as the condition, insert an implicit
+        // cast.
+        Lo = DefaultLvalueConversion(Lo).take();
+        Lo = ImpCastExprToType(Lo, CondType, CK_IntegralCast).take();
+      }
+
+      // Convert the value to the same width/sign as the condition had prior to
+      // integral promotions.
+      //
+      // FIXME: This causes us to reject valid code:
+      //   switch ((char)c) { case 256: case 0: return 0; }
+      // Here we claim there is a duplicated condition value, but there is not.
+      ConvertIntegerToTypeWarnOnOverflow(LoVal, CondWidth, CondIsSigned,
+                                         Lo->getLocStart(),
+                                         diag::warn_case_value_overflow);
+
+      CS->setLHS(Lo);
+
+      // If this is a case range, remember it in CaseRanges, otherwise CaseVals.
+      if (CS->getRHS()) {
+        if (CS->getRHS()->isTypeDependent() ||
+            CS->getRHS()->isValueDependent()) {
+          HasDependentValue = true;
+          break;
+        }
+        CaseRanges.push_back(std::make_pair(LoVal, CS));
+      } else
+        CaseVals.push_back(std::make_pair(LoVal, CS));
+    }
+  }
+
+  if (!HasDependentValue) {
+    // If we don't have a default statement, check whether the
+    // condition is constant.
+    llvm::APSInt ConstantCondValue;
+    bool HasConstantCond = false;
+    if (!HasDependentValue && !TheDefaultStmt) {
+      HasConstantCond
+        = CondExprBeforePromotion->EvaluateAsInt(ConstantCondValue, Context,
+                                                 Expr::SE_AllowSideEffects);
+      assert(!HasConstantCond ||
+             (ConstantCondValue.getBitWidth() == CondWidth &&
+              ConstantCondValue.isSigned() == CondIsSigned));
+    }
+    bool ShouldCheckConstantCond = HasConstantCond;
+
+    // Sort all the scalar case values so we can easily detect duplicates.
+    std::stable_sort(CaseVals.begin(), CaseVals.end(), CmpCaseVals);
+
+    if (!CaseVals.empty()) {
+      for (unsigned i = 0, e = CaseVals.size(); i != e; ++i) {
+        if (ShouldCheckConstantCond &&
+            CaseVals[i].first == ConstantCondValue)
+          ShouldCheckConstantCond = false;
+
+        if (i != 0 && CaseVals[i].first == CaseVals[i-1].first) {
+          // If we have a duplicate, report it.
+          Diag(CaseVals[i].second->getLHS()->getLocStart(),
+               diag::err_duplicate_case) << CaseVals[i].first.toString(10);
+          Diag(CaseVals[i-1].second->getLHS()->getLocStart(),
+               diag::note_duplicate_case_prev);
+          // FIXME: We really want to remove the bogus case stmt from the
+          // substmt, but we have no way to do this right now.
+          CaseListIsErroneous = true;
+        }
+      }
+    }
+
+    // Detect duplicate case ranges, which usually don't exist at all in
+    // the first place.
+    if (!CaseRanges.empty()) {
+      // Sort all the case ranges by their low value so we can easily detect
+      // overlaps between ranges.
+      std::stable_sort(CaseRanges.begin(), CaseRanges.end());
+
+      // Scan the ranges, computing the high values and removing empty ranges.
+      std::vector<llvm::APSInt> HiVals;
+      for (unsigned i = 0, e = CaseRanges.size(); i != e; ++i) {
+        llvm::APSInt &LoVal = CaseRanges[i].first;
+        CaseStmt *CR = CaseRanges[i].second;
+        Expr *Hi = CR->getRHS();
+        llvm::APSInt HiVal;
+
+        if (getLangOpts().CPlusPlus0x) {
+          // C++11 [stmt.switch]p2: the constant-expression shall be a converted
+          // constant expression of the promoted type of the switch condition.
+          ExprResult ConvHi =
+            CheckConvertedConstantExpression(Hi, CondType, HiVal,
+                                             CCEK_CaseValue);
+          if (ConvHi.isInvalid()) {
+            CaseListIsErroneous = true;
+            continue;
+          }
+          Hi = ConvHi.take();
+        } else {
+          HiVal = Hi->EvaluateKnownConstInt(Context);
+
+          // If the RHS is not the same type as the condition, insert an
+          // implicit cast.
+          Hi = DefaultLvalueConversion(Hi).take();
+          Hi = ImpCastExprToType(Hi, CondType, CK_IntegralCast).take();
+        }
+
+        // Convert the value to the same width/sign as the condition.
+        ConvertIntegerToTypeWarnOnOverflow(HiVal, CondWidth, CondIsSigned,
+                                           Hi->getLocStart(),
+                                           diag::warn_case_value_overflow);
+
+        CR->setRHS(Hi);
+
+        // If the low value is bigger than the high value, the case is empty.
+        if (LoVal > HiVal) {
+          Diag(CR->getLHS()->getLocStart(), diag::warn_case_empty_range)
+            << SourceRange(CR->getLHS()->getLocStart(),
+                           Hi->getLocEnd());
+          CaseRanges.erase(CaseRanges.begin()+i);
+          --i, --e;
+          continue;
+        }
+
+        if (ShouldCheckConstantCond &&
+            LoVal <= ConstantCondValue &&
+            ConstantCondValue <= HiVal)
+          ShouldCheckConstantCond = false;
+
+        HiVals.push_back(HiVal);
+      }
+
+      // Rescan the ranges, looking for overlap with singleton values and other
+      // ranges.  Since the range list is sorted, we only need to compare case
+      // ranges with their neighbors.
+      for (unsigned i = 0, e = CaseRanges.size(); i != e; ++i) {
+        llvm::APSInt &CRLo = CaseRanges[i].first;
+        llvm::APSInt &CRHi = HiVals[i];
+        CaseStmt *CR = CaseRanges[i].second;
+
+        // Check to see whether the case range overlaps with any
+        // singleton cases.
+        CaseStmt *OverlapStmt = 0;
+        llvm::APSInt OverlapVal(32);
+
+        // Find the smallest value >= the lower bound.  If I is in the
+        // case range, then we have overlap.
+        CaseValsTy::iterator I = std::lower_bound(CaseVals.begin(),
+                                                  CaseVals.end(), CRLo,
+                                                  CaseCompareFunctor());
+        if (I != CaseVals.end() && I->first < CRHi) {
+          OverlapVal  = I->first;   // Found overlap with scalar.
+          OverlapStmt = I->second;
+        }
+
+        // Find the smallest value bigger than the upper bound.
+        I = std::upper_bound(I, CaseVals.end(), CRHi, CaseCompareFunctor());
+        if (I != CaseVals.begin() && (I-1)->first >= CRLo) {
+          OverlapVal  = (I-1)->first;      // Found overlap with scalar.
+          OverlapStmt = (I-1)->second;
+        }
+
+        // Check to see if this case stmt overlaps with the subsequent
+        // case range.
+        if (i && CRLo <= HiVals[i-1]) {
+          OverlapVal  = HiVals[i-1];       // Found overlap with range.
+          OverlapStmt = CaseRanges[i-1].second;
+        }
+
+        if (OverlapStmt) {
+          // If we have a duplicate, report it.
+          Diag(CR->getLHS()->getLocStart(), diag::err_duplicate_case)
+            << OverlapVal.toString(10);
+          Diag(OverlapStmt->getLHS()->getLocStart(),
+               diag::note_duplicate_case_prev);
+          // FIXME: We really want to remove the bogus case stmt from the
+          // substmt, but we have no way to do this right now.
+          CaseListIsErroneous = true;
+        }
+      }
+    }
+
+    // Complain if we have a constant condition and we didn't find a match.
+    if (!CaseListIsErroneous && ShouldCheckConstantCond) {
+      // TODO: it would be nice if we printed enums as enums, chars as
+      // chars, etc.
+      Diag(CondExpr->getExprLoc(), diag::warn_missing_case_for_condition)
+        << ConstantCondValue.toString(10)
+        << CondExpr->getSourceRange();
+    }
+
+    // Check to see if switch is over an Enum and handles all of its
+    // values.  We only issue a warning if there is not 'default:', but
+    // we still do the analysis to preserve this information in the AST
+    // (which can be used by flow-based analyes).
+    //
+    const EnumType *ET = CondTypeBeforePromotion->getAs<EnumType>();
+
+    // If switch has default case, then ignore it.
+    if (!CaseListIsErroneous  && !HasConstantCond && ET) {
+      const EnumDecl *ED = ET->getDecl();
+      typedef SmallVector<std::pair<llvm::APSInt, EnumConstantDecl*>, 64>
+        EnumValsTy;
+      EnumValsTy EnumVals;
+
+      // Gather all enum values, set their type and sort them,
+      // allowing easier comparison with CaseVals.
+      for (EnumDecl::enumerator_iterator EDI = ED->enumerator_begin();
+           EDI != ED->enumerator_end(); ++EDI) {
+        llvm::APSInt Val = EDI->getInitVal();
+        AdjustAPSInt(Val, CondWidth, CondIsSigned);
+        EnumVals.push_back(std::make_pair(Val, *EDI));
+      }
+      std::stable_sort(EnumVals.begin(), EnumVals.end(), CmpEnumVals);
+      EnumValsTy::iterator EIend =
+        std::unique(EnumVals.begin(), EnumVals.end(), EqEnumVals);
+
+      // See which case values aren't in enum.
+      EnumValsTy::const_iterator EI = EnumVals.begin();
+      for (CaseValsTy::const_iterator CI = CaseVals.begin();
+           CI != CaseVals.end(); CI++) {
+        while (EI != EIend && EI->first < CI->first)
+          EI++;
+        if (EI == EIend || EI->first > CI->first)
+          Diag(CI->second->getLHS()->getExprLoc(), diag::warn_not_in_enum)
+            << CondTypeBeforePromotion;
+      }
+      // See which of case ranges aren't in enum
+      EI = EnumVals.begin();
+      for (CaseRangesTy::const_iterator RI = CaseRanges.begin();
+           RI != CaseRanges.end() && EI != EIend; RI++) {
+        while (EI != EIend && EI->first < RI->first)
+          EI++;
+
+        if (EI == EIend || EI->first != RI->first) {
+          Diag(RI->second->getLHS()->getExprLoc(), diag::warn_not_in_enum)
+            << CondTypeBeforePromotion;
+        }
+
+        llvm::APSInt Hi = 
+          RI->second->getRHS()->EvaluateKnownConstInt(Context);
+        AdjustAPSInt(Hi, CondWidth, CondIsSigned);
+        while (EI != EIend && EI->first < Hi)
+          EI++;
+        if (EI == EIend || EI->first != Hi)
+          Diag(RI->second->getRHS()->getExprLoc(), diag::warn_not_in_enum)
+            << CondTypeBeforePromotion;
+      }
+
+      // Check which enum vals aren't in switch
+      CaseValsTy::const_iterator CI = CaseVals.begin();
+      CaseRangesTy::const_iterator RI = CaseRanges.begin();
+      bool hasCasesNotInSwitch = false;
+
+      SmallVector<DeclarationName,8> UnhandledNames;
+
+      for (EI = EnumVals.begin(); EI != EIend; EI++){
+        // Drop unneeded case values
+        llvm::APSInt CIVal;
+        while (CI != CaseVals.end() && CI->first < EI->first)
+          CI++;
+
+        if (CI != CaseVals.end() && CI->first == EI->first)
+          continue;
+
+        // Drop unneeded case ranges
+        for (; RI != CaseRanges.end(); RI++) {
+          llvm::APSInt Hi =
+            RI->second->getRHS()->EvaluateKnownConstInt(Context);
+          AdjustAPSInt(Hi, CondWidth, CondIsSigned);
+          if (EI->first <= Hi)
+            break;
+        }
+
+        if (RI == CaseRanges.end() || EI->first < RI->first) {
+          hasCasesNotInSwitch = true;
+          UnhandledNames.push_back(EI->second->getDeclName());
+        }
+      }
+
+      if (TheDefaultStmt && UnhandledNames.empty())
+        Diag(TheDefaultStmt->getDefaultLoc(), diag::warn_unreachable_default);
+
+      // Produce a nice diagnostic if multiple values aren't handled.
+      switch (UnhandledNames.size()) {
+      case 0: break;
+      case 1:
+        Diag(CondExpr->getExprLoc(), TheDefaultStmt 
+          ? diag::warn_def_missing_case1 : diag::warn_missing_case1)
+          << UnhandledNames[0];
+        break;
+      case 2:
+        Diag(CondExpr->getExprLoc(), TheDefaultStmt 
+          ? diag::warn_def_missing_case2 : diag::warn_missing_case2)
+          << UnhandledNames[0] << UnhandledNames[1];
+        break;
+      case 3:
+        Diag(CondExpr->getExprLoc(), TheDefaultStmt
+          ? diag::warn_def_missing_case3 : diag::warn_missing_case3)
+          << UnhandledNames[0] << UnhandledNames[1] << UnhandledNames[2];
+        break;
+      default:
+        Diag(CondExpr->getExprLoc(), TheDefaultStmt
+          ? diag::warn_def_missing_cases : diag::warn_missing_cases)
+          << (unsigned)UnhandledNames.size()
+          << UnhandledNames[0] << UnhandledNames[1] << UnhandledNames[2];
+        break;
+      }
+
+      if (!hasCasesNotInSwitch)
+        SS->setAllEnumCasesCovered();
+    }
+  }
+
+  DiagnoseEmptyStmtBody(CondExpr->getLocEnd(), BodyStmt,
+                        diag::warn_empty_switch_body);
+
+  // FIXME: If the case list was broken is some way, we don't have a good system
+  // to patch it up.  Instead, just return the whole substmt as broken.
+  if (CaseListIsErroneous)
+    return StmtError();
+
+  return Owned(SS);
+}
+
+StmtResult
+Sema::ActOnWhileStmt(SourceLocation WhileLoc, FullExprArg Cond,
+                     Decl *CondVar, Stmt *Body) {
+  ExprResult CondResult(Cond.release());
+
+  VarDecl *ConditionVar = 0;
+  if (CondVar) {
+    ConditionVar = cast<VarDecl>(CondVar);
+    CondResult = CheckConditionVariable(ConditionVar, WhileLoc, true);
+    if (CondResult.isInvalid())
+      return StmtError();
+  }
+  Expr *ConditionExpr = CondResult.take();
+  if (!ConditionExpr)
+    return StmtError();
+
+  DiagnoseUnusedExprResult(Body);
+
+  if (isa<NullStmt>(Body))
+    getCurCompoundScope().setHasEmptyLoopBodies();
+
+  return Owned(new (Context) WhileStmt(Context, ConditionVar, ConditionExpr,
+                                       Body, WhileLoc));
+}
+
+StmtResult
+Sema::ActOnDoStmt(SourceLocation DoLoc, Stmt *Body,
+                  SourceLocation WhileLoc, SourceLocation CondLParen,
+                  Expr *Cond, SourceLocation CondRParen) {
+  assert(Cond && "ActOnDoStmt(): missing expression");
+
+  ExprResult CondResult = CheckBooleanCondition(Cond, DoLoc);
+  if (CondResult.isInvalid() || CondResult.isInvalid())
+    return StmtError();
+  Cond = CondResult.take();
+
+  CheckImplicitConversions(Cond, DoLoc);
+  CondResult = MaybeCreateExprWithCleanups(Cond);
+  if (CondResult.isInvalid())
+    return StmtError();
+  Cond = CondResult.take();
+
+  DiagnoseUnusedExprResult(Body);
+
+  return Owned(new (Context) DoStmt(Body, Cond, DoLoc, WhileLoc, CondRParen));
+}
+
+StmtResult
+Sema::ActOnForStmt(SourceLocation ForLoc, SourceLocation LParenLoc,
+                   Stmt *First, FullExprArg second, Decl *secondVar,
+                   FullExprArg third,
+                   SourceLocation RParenLoc, Stmt *Body) {
+  if (!getLangOpts().CPlusPlus) {
+    if (DeclStmt *DS = dyn_cast_or_null<DeclStmt>(First)) {
+      // C99 6.8.5p3: The declaration part of a 'for' statement shall only
+      // declare identifiers for objects having storage class 'auto' or
+      // 'register'.
+      for (DeclStmt::decl_iterator DI=DS->decl_begin(), DE=DS->decl_end();
+           DI!=DE; ++DI) {
+        VarDecl *VD = dyn_cast<VarDecl>(*DI);
+        if (VD && VD->isLocalVarDecl() && !VD->hasLocalStorage())
+          VD = 0;
+        if (VD == 0)
+          Diag((*DI)->getLocation(), diag::err_non_variable_decl_in_for);
+        // FIXME: mark decl erroneous!
+      }
+    }
+  }
+
+  ExprResult SecondResult(second.release());
+  VarDecl *ConditionVar = 0;
+  if (secondVar) {
+    ConditionVar = cast<VarDecl>(secondVar);
+    SecondResult = CheckConditionVariable(ConditionVar, ForLoc, true);
+    if (SecondResult.isInvalid())
+      return StmtError();
+  }
+
+  Expr *Third  = third.release().takeAs<Expr>();
+
+  DiagnoseUnusedExprResult(First);
+  DiagnoseUnusedExprResult(Third);
+  DiagnoseUnusedExprResult(Body);
+
+  if (isa<NullStmt>(Body))
+    getCurCompoundScope().setHasEmptyLoopBodies();
+
+  return Owned(new (Context) ForStmt(Context, First,
+                                     SecondResult.take(), ConditionVar,
+                                     Third, Body, ForLoc, LParenLoc,
+                                     RParenLoc));
+}
+
+/// In an Objective C collection iteration statement:
+///   for (x in y)
+/// x can be an arbitrary l-value expression.  Bind it up as a
+/// full-expression.
+StmtResult Sema::ActOnForEachLValueExpr(Expr *E) {
+  // Reduce placeholder expressions here.  Note that this rejects the
+  // use of pseudo-object l-values in this position.
+  ExprResult result = CheckPlaceholderExpr(E);
+  if (result.isInvalid()) return StmtError();
+  E = result.take();
+
+  CheckImplicitConversions(E);
+
+  result = MaybeCreateExprWithCleanups(E);
+  if (result.isInvalid()) return StmtError();
+
+  return Owned(static_cast<Stmt*>(result.take()));
+}
+
+ExprResult
+Sema::ActOnObjCForCollectionOperand(SourceLocation forLoc, Expr *collection) {
+  assert(collection);
+
+  // Bail out early if we've got a type-dependent expression.
+  if (collection->isTypeDependent()) return Owned(collection);
+
+  // Perform normal l-value conversion.
+  ExprResult result = DefaultFunctionArrayLvalueConversion(collection);
+  if (result.isInvalid())
+    return ExprError();
+  collection = result.take();
+
+  // The operand needs to have object-pointer type.
+  // TODO: should we do a contextual conversion?
+  const ObjCObjectPointerType *pointerType =
+    collection->getType()->getAs<ObjCObjectPointerType>();
+  if (!pointerType)
+    return Diag(forLoc, diag::err_collection_expr_type)
+             << collection->getType() << collection->getSourceRange();
+
+  // Check that the operand provides
+  //   - countByEnumeratingWithState:objects:count:
+  const ObjCObjectType *objectType = pointerType->getObjectType();
+  ObjCInterfaceDecl *iface = objectType->getInterface();
+
+  // If we have a forward-declared type, we can't do this check.
+  // Under ARC, it is an error not to have a forward-declared class.
+  if (iface && 
+      RequireCompleteType(forLoc, QualType(objectType, 0),
+                          getLangOpts().ObjCAutoRefCount
+                            ? PDiag(diag::err_arc_collection_forward)
+                                << collection->getSourceRange()
+                          : PDiag(0))) {
+    // Otherwise, if we have any useful type information, check that
+    // the type declares the appropriate method.
+  } else if (iface || !objectType->qual_empty()) {
+    IdentifierInfo *selectorIdents[] = {
+      &Context.Idents.get("countByEnumeratingWithState"),
+      &Context.Idents.get("objects"),
+      &Context.Idents.get("count")
+    };
+    Selector selector = Context.Selectors.getSelector(3, &selectorIdents[0]);
+
+    ObjCMethodDecl *method = 0;
+
+    // If there's an interface, look in both the public and private APIs.
+    if (iface) {
+      method = iface->lookupInstanceMethod(selector);
+      if (!method) method = LookupPrivateInstanceMethod(selector, iface);
+    }
+
+    // Also check protocol qualifiers.
+    if (!method)
+      method = LookupMethodInQualifiedType(selector, pointerType,
+                                           /*instance*/ true);
+
+    // If we didn't find it anywhere, give up.
+    if (!method) {
+      Diag(forLoc, diag::warn_collection_expr_type)
+        << collection->getType() << selector << collection->getSourceRange();
+    }
+
+    // TODO: check for an incompatible signature?
+  }
+
+  // Wrap up any cleanups in the expression.
+  return Owned(MaybeCreateExprWithCleanups(collection));
+}
+
+StmtResult
+Sema::ActOnObjCForCollectionStmt(SourceLocation ForLoc,
+                                 SourceLocation LParenLoc,
+                                 Stmt *First, Expr *Second,
+                                 SourceLocation RParenLoc, Stmt *Body) {
+  if (First) {
+    QualType FirstType;
+    if (DeclStmt *DS = dyn_cast<DeclStmt>(First)) {
+      if (!DS->isSingleDecl())
+        return StmtError(Diag((*DS->decl_begin())->getLocation(),
+                         diag::err_toomany_element_decls));
+
+      VarDecl *D = cast<VarDecl>(DS->getSingleDecl());
+      FirstType = D->getType();
+      // C99 6.8.5p3: The declaration part of a 'for' statement shall only
+      // declare identifiers for objects having storage class 'auto' or
+      // 'register'.
+      if (!D->hasLocalStorage())
+        return StmtError(Diag(D->getLocation(),
+                              diag::err_non_variable_decl_in_for));
+    } else {
+      Expr *FirstE = cast<Expr>(First);
+      if (!FirstE->isTypeDependent() && !FirstE->isLValue())
+        return StmtError(Diag(First->getLocStart(),
+                   diag::err_selector_element_not_lvalue)
+          << First->getSourceRange());
+
+      FirstType = static_cast<Expr*>(First)->getType();
+    }
+    if (!FirstType->isDependentType() &&
+        !FirstType->isObjCObjectPointerType() &&
+        !FirstType->isBlockPointerType())
+        Diag(ForLoc, diag::err_selector_element_type)
+          << FirstType << First->getSourceRange();
+  }
+
+  return Owned(new (Context) ObjCForCollectionStmt(First, Second, Body,
+                                                   ForLoc, RParenLoc));
+}
+
+namespace {
+
+enum BeginEndFunction {
+  BEF_begin,
+  BEF_end
+};
+
+/// Build a variable declaration for a for-range statement.
+static VarDecl *BuildForRangeVarDecl(Sema &SemaRef, SourceLocation Loc,
+                                     QualType Type, const char *Name) {
+  DeclContext *DC = SemaRef.CurContext;
+  IdentifierInfo *II = &SemaRef.PP.getIdentifierTable().get(Name);
+  TypeSourceInfo *TInfo = SemaRef.Context.getTrivialTypeSourceInfo(Type, Loc);
+  VarDecl *Decl = VarDecl::Create(SemaRef.Context, DC, Loc, Loc, II, Type,
+                                  TInfo, SC_Auto, SC_None);
+  Decl->setImplicit();
+  return Decl;
+}
+
+/// Finish building a variable declaration for a for-range statement.
+/// \return true if an error occurs.
+static bool FinishForRangeVarDecl(Sema &SemaRef, VarDecl *Decl, Expr *Init,
+                                  SourceLocation Loc, int diag) {
+  // Deduce the type for the iterator variable now rather than leaving it to
+  // AddInitializerToDecl, so we can produce a more suitable diagnostic.
+  TypeSourceInfo *InitTSI = 0;
+  if ((!isa<InitListExpr>(Init) && Init->getType()->isVoidType()) ||
+      SemaRef.DeduceAutoType(Decl->getTypeSourceInfo(), Init, InitTSI) ==
+          Sema::DAR_Failed)
+    SemaRef.Diag(Loc, diag) << Init->getType();
+  if (!InitTSI) {
+    Decl->setInvalidDecl();
+    return true;
+  }
+  Decl->setTypeSourceInfo(InitTSI);
+  Decl->setType(InitTSI->getType());
+
+  // In ARC, infer lifetime.
+  // FIXME: ARC may want to turn this into 'const __unsafe_unretained' if
+  // we're doing the equivalent of fast iteration.
+  if (SemaRef.getLangOpts().ObjCAutoRefCount && 
+      SemaRef.inferObjCARCLifetime(Decl))
+    Decl->setInvalidDecl();
+
+  SemaRef.AddInitializerToDecl(Decl, Init, /*DirectInit=*/false,
+                               /*TypeMayContainAuto=*/false);
+  SemaRef.FinalizeDeclaration(Decl);
+  SemaRef.CurContext->addHiddenDecl(Decl);
+  return false;
+}
+
+/// Produce a note indicating which begin/end function was implicitly called
+/// by a C++0x for-range statement. This is often not obvious from the code,
+/// nor from the diagnostics produced when analysing the implicit expressions
+/// required in a for-range statement.
+void NoteForRangeBeginEndFunction(Sema &SemaRef, Expr *E,
+                                  BeginEndFunction BEF) {
+  CallExpr *CE = dyn_cast<CallExpr>(E);
+  if (!CE)
+    return;
+  FunctionDecl *D = dyn_cast<FunctionDecl>(CE->getCalleeDecl());
+  if (!D)
+    return;
+  SourceLocation Loc = D->getLocation();
+
+  std::string Description;
+  bool IsTemplate = false;
+  if (FunctionTemplateDecl *FunTmpl = D->getPrimaryTemplate()) {
+    Description = SemaRef.getTemplateArgumentBindingsText(
+      FunTmpl->getTemplateParameters(), *D->getTemplateSpecializationArgs());
+    IsTemplate = true;
+  }
+
+  SemaRef.Diag(Loc, diag::note_for_range_begin_end)
+    << BEF << IsTemplate << Description << E->getType();
+}
+
+/// Build a call to 'begin' or 'end' for a C++0x for-range statement. If the
+/// given LookupResult is non-empty, it is assumed to describe a member which
+/// will be invoked. Otherwise, the function will be found via argument
+/// dependent lookup.
+static ExprResult BuildForRangeBeginEndCall(Sema &SemaRef, Scope *S,
+                                            SourceLocation Loc,
+                                            VarDecl *Decl,
+                                            BeginEndFunction BEF,
+                                            const DeclarationNameInfo &NameInfo,
+                                            LookupResult &MemberLookup,
+                                            Expr *Range) {
+  ExprResult CallExpr;
+  if (!MemberLookup.empty()) {
+    ExprResult MemberRef =
+      SemaRef.BuildMemberReferenceExpr(Range, Range->getType(), Loc,
+                                       /*IsPtr=*/false, CXXScopeSpec(),
+                                       /*TemplateKWLoc=*/SourceLocation(),
+                                       /*FirstQualifierInScope=*/0,
+                                       MemberLookup,
+                                       /*TemplateArgs=*/0);
+    if (MemberRef.isInvalid())
+      return ExprError();
+    CallExpr = SemaRef.ActOnCallExpr(S, MemberRef.get(), Loc, MultiExprArg(),
+                                     Loc, 0);
+    if (CallExpr.isInvalid())
+      return ExprError();
+  } else {
+    UnresolvedSet<0> FoundNames;
+    // C++0x [stmt.ranged]p1: For the purposes of this name lookup, namespace
+    // std is an associated namespace.
+    UnresolvedLookupExpr *Fn =
+      UnresolvedLookupExpr::Create(SemaRef.Context, /*NamingClass=*/0,
+                                   NestedNameSpecifierLoc(), NameInfo,
+                                   /*NeedsADL=*/true, /*Overloaded=*/false,
+                                   FoundNames.begin(), FoundNames.end(),
+                                   /*LookInStdNamespace=*/true);
+    CallExpr = SemaRef.BuildOverloadedCallExpr(S, Fn, Fn, Loc, &Range, 1, Loc,
+                                               0, /*AllowTypoCorrection=*/false);
+    if (CallExpr.isInvalid()) {
+      SemaRef.Diag(Range->getLocStart(), diag::note_for_range_type)
+        << Range->getType();
+      return ExprError();
+    }
+  }
+  if (FinishForRangeVarDecl(SemaRef, Decl, CallExpr.get(), Loc,
+                            diag::err_for_range_iter_deduction_failure)) {
+    NoteForRangeBeginEndFunction(SemaRef, CallExpr.get(), BEF);
+    return ExprError();
+  }
+  return CallExpr;
+}
+
+}
+
+/// ActOnCXXForRangeStmt - Check and build a C++0x for-range statement.
+///
+/// C++0x [stmt.ranged]:
+///   A range-based for statement is equivalent to
+///
+///   {
+///     auto && __range = range-init;
+///     for ( auto __begin = begin-expr,
+///           __end = end-expr;
+///           __begin != __end;
+///           ++__begin ) {
+///       for-range-declaration = *__begin;
+///       statement
+///     }
+///   }
+///
+/// The body of the loop is not available yet, since it cannot be analysed until
+/// we have determined the type of the for-range-declaration.
+StmtResult
+Sema::ActOnCXXForRangeStmt(SourceLocation ForLoc, SourceLocation LParenLoc,
+                           Stmt *First, SourceLocation ColonLoc, Expr *Range,
+                           SourceLocation RParenLoc) {
+  if (!First || !Range)
+    return StmtError();
+
+  DeclStmt *DS = dyn_cast<DeclStmt>(First);
+  assert(DS && "first part of for range not a decl stmt");
+
+  if (!DS->isSingleDecl()) {
+    Diag(DS->getStartLoc(), diag::err_type_defined_in_for_range);
+    return StmtError();
+  }
+  if (DS->getSingleDecl()->isInvalidDecl())
+    return StmtError();
+
+  if (DiagnoseUnexpandedParameterPack(Range, UPPC_Expression))
+    return StmtError();
+
+  // Build  auto && __range = range-init
+  SourceLocation RangeLoc = Range->getLocStart();
+  VarDecl *RangeVar = BuildForRangeVarDecl(*this, RangeLoc,
+                                           Context.getAutoRRefDeductType(),
+                                           "__range");
+  if (FinishForRangeVarDecl(*this, RangeVar, Range, RangeLoc,
+                            diag::err_for_range_deduction_failure))
+    return StmtError();
+
+  // Claim the type doesn't contain auto: we've already done the checking.
+  DeclGroupPtrTy RangeGroup =
+    BuildDeclaratorGroup((Decl**)&RangeVar, 1, /*TypeMayContainAuto=*/false);
+  StmtResult RangeDecl = ActOnDeclStmt(RangeGroup, RangeLoc, RangeLoc);
+  if (RangeDecl.isInvalid())
+    return StmtError();
+
+  return BuildCXXForRangeStmt(ForLoc, ColonLoc, RangeDecl.get(),
+                              /*BeginEndDecl=*/0, /*Cond=*/0, /*Inc=*/0, DS,
+                              RParenLoc);
+}
+
+/// BuildCXXForRangeStmt - Build or instantiate a C++0x for-range statement.
+StmtResult
+Sema::BuildCXXForRangeStmt(SourceLocation ForLoc, SourceLocation ColonLoc,
+                           Stmt *RangeDecl, Stmt *BeginEnd, Expr *Cond,
+                           Expr *Inc, Stmt *LoopVarDecl,
+                           SourceLocation RParenLoc) {
+  Scope *S = getCurScope();
+
+  DeclStmt *RangeDS = cast<DeclStmt>(RangeDecl);
+  VarDecl *RangeVar = cast<VarDecl>(RangeDS->getSingleDecl());
+  QualType RangeVarType = RangeVar->getType();
+
+  DeclStmt *LoopVarDS = cast<DeclStmt>(LoopVarDecl);
+  VarDecl *LoopVar = cast<VarDecl>(LoopVarDS->getSingleDecl());
+
+  StmtResult BeginEndDecl = BeginEnd;
+  ExprResult NotEqExpr = Cond, IncrExpr = Inc;
+
+  if (!BeginEndDecl.get() && !RangeVarType->isDependentType()) {
+    SourceLocation RangeLoc = RangeVar->getLocation();
+
+    const QualType RangeVarNonRefType = RangeVarType.getNonReferenceType();
+
+    ExprResult BeginRangeRef = BuildDeclRefExpr(RangeVar, RangeVarNonRefType,
+                                                VK_LValue, ColonLoc);
+    if (BeginRangeRef.isInvalid())
+      return StmtError();
+
+    ExprResult EndRangeRef = BuildDeclRefExpr(RangeVar, RangeVarNonRefType,
+                                              VK_LValue, ColonLoc);
+    if (EndRangeRef.isInvalid())
+      return StmtError();
+
+    QualType AutoType = Context.getAutoDeductType();
+    Expr *Range = RangeVar->getInit();
+    if (!Range)
+      return StmtError();
+    QualType RangeType = Range->getType();
+
+    if (RequireCompleteType(RangeLoc, RangeType,
+                            PDiag(diag::err_for_range_incomplete_type)))
+      return StmtError();
+
+    // Build auto __begin = begin-expr, __end = end-expr.
+    VarDecl *BeginVar = BuildForRangeVarDecl(*this, ColonLoc, AutoType,
+                                             "__begin");
+    VarDecl *EndVar = BuildForRangeVarDecl(*this, ColonLoc, AutoType,
+                                           "__end");
+
+    // Build begin-expr and end-expr and attach to __begin and __end variables.
+    ExprResult BeginExpr, EndExpr;
+    if (const ArrayType *UnqAT = RangeType->getAsArrayTypeUnsafe()) {
+      // - if _RangeT is an array type, begin-expr and end-expr are __range and
+      //   __range + __bound, respectively, where __bound is the array bound. If
+      //   _RangeT is an array of unknown size or an array of incomplete type,
+      //   the program is ill-formed;
+
+      // begin-expr is __range.
+      BeginExpr = BeginRangeRef;
+      if (FinishForRangeVarDecl(*this, BeginVar, BeginRangeRef.get(), ColonLoc,
+                                diag::err_for_range_iter_deduction_failure)) {
+        NoteForRangeBeginEndFunction(*this, BeginExpr.get(), BEF_begin);
+        return StmtError();
+      }
+
+      // Find the array bound.
+      ExprResult BoundExpr;
+      if (const ConstantArrayType *CAT = dyn_cast<ConstantArrayType>(UnqAT))
+        BoundExpr = Owned(IntegerLiteral::Create(Context, CAT->getSize(),
+                                                 Context.getPointerDiffType(),
+                                                 RangeLoc));
+      else if (const VariableArrayType *VAT =
+               dyn_cast<VariableArrayType>(UnqAT))
+        BoundExpr = VAT->getSizeExpr();
+      else {
+        // Can't be a DependentSizedArrayType or an IncompleteArrayType since
+        // UnqAT is not incomplete and Range is not type-dependent.
+        llvm_unreachable("Unexpected array type in for-range");
+      }
+
+      // end-expr is __range + __bound.
+      EndExpr = ActOnBinOp(S, ColonLoc, tok::plus, EndRangeRef.get(),
+                           BoundExpr.get());
+      if (EndExpr.isInvalid())
+        return StmtError();
+      if (FinishForRangeVarDecl(*this, EndVar, EndExpr.get(), ColonLoc,
+                                diag::err_for_range_iter_deduction_failure)) {
+        NoteForRangeBeginEndFunction(*this, EndExpr.get(), BEF_end);
+        return StmtError();
+      }
+    } else {
+      DeclarationNameInfo BeginNameInfo(&PP.getIdentifierTable().get("begin"),
+                                        ColonLoc);
+      DeclarationNameInfo EndNameInfo(&PP.getIdentifierTable().get("end"),
+                                      ColonLoc);
+
+      LookupResult BeginMemberLookup(*this, BeginNameInfo, LookupMemberName);
+      LookupResult EndMemberLookup(*this, EndNameInfo, LookupMemberName);
+
+      if (CXXRecordDecl *D = RangeType->getAsCXXRecordDecl()) {
+        // - if _RangeT is a class type, the unqualified-ids begin and end are
+        //   looked up in the scope of class _RangeT as if by class member access
+        //   lookup (3.4.5), and if either (or both) finds at least one
+        //   declaration, begin-expr and end-expr are __range.begin() and
+        //   __range.end(), respectively;
+        LookupQualifiedName(BeginMemberLookup, D);
+        LookupQualifiedName(EndMemberLookup, D);
+
+        if (BeginMemberLookup.empty() != EndMemberLookup.empty()) {
+          Diag(ColonLoc, diag::err_for_range_member_begin_end_mismatch)
+            << RangeType << BeginMemberLookup.empty();
+          return StmtError();
+        }
+      } else {
+        // - otherwise, begin-expr and end-expr are begin(__range) and
+        //   end(__range), respectively, where begin and end are looked up with
+        //   argument-dependent lookup (3.4.2). For the purposes of this name
+        //   lookup, namespace std is an associated namespace.
+      }
+
+      BeginExpr = BuildForRangeBeginEndCall(*this, S, ColonLoc, BeginVar,
+                                            BEF_begin, BeginNameInfo,
+                                            BeginMemberLookup,
+                                            BeginRangeRef.get());
+      if (BeginExpr.isInvalid())
+        return StmtError();
+
+      EndExpr = BuildForRangeBeginEndCall(*this, S, ColonLoc, EndVar,
+                                          BEF_end, EndNameInfo,
+                                          EndMemberLookup, EndRangeRef.get());
+      if (EndExpr.isInvalid())
+        return StmtError();
+    }
+
+    // C++0x [decl.spec.auto]p6: BeginType and EndType must be the same.
+    QualType BeginType = BeginVar->getType(), EndType = EndVar->getType();
+    if (!Context.hasSameType(BeginType, EndType)) {
+      Diag(RangeLoc, diag::err_for_range_begin_end_types_differ)
+        << BeginType << EndType;
+      NoteForRangeBeginEndFunction(*this, BeginExpr.get(), BEF_begin);
+      NoteForRangeBeginEndFunction(*this, EndExpr.get(), BEF_end);
+    }
+
+    Decl *BeginEndDecls[] = { BeginVar, EndVar };
+    // Claim the type doesn't contain auto: we've already done the checking.
+    DeclGroupPtrTy BeginEndGroup =
+      BuildDeclaratorGroup(BeginEndDecls, 2, /*TypeMayContainAuto=*/false);
+    BeginEndDecl = ActOnDeclStmt(BeginEndGroup, ColonLoc, ColonLoc);
+
+    const QualType BeginRefNonRefType = BeginType.getNonReferenceType();
+    ExprResult BeginRef = BuildDeclRefExpr(BeginVar, BeginRefNonRefType,
+                                           VK_LValue, ColonLoc);
+    if (BeginRef.isInvalid())
+      return StmtError();
+
+    ExprResult EndRef = BuildDeclRefExpr(EndVar, EndType.getNonReferenceType(),
+                                         VK_LValue, ColonLoc);
+    if (EndRef.isInvalid())
+      return StmtError();
+
+    // Build and check __begin != __end expression.
+    NotEqExpr = ActOnBinOp(S, ColonLoc, tok::exclaimequal,
+                           BeginRef.get(), EndRef.get());
+    NotEqExpr = ActOnBooleanCondition(S, ColonLoc, NotEqExpr.get());
+    NotEqExpr = ActOnFinishFullExpr(NotEqExpr.get());
+    if (NotEqExpr.isInvalid()) {
+      NoteForRangeBeginEndFunction(*this, BeginExpr.get(), BEF_begin);
+      if (!Context.hasSameType(BeginType, EndType))
+        NoteForRangeBeginEndFunction(*this, EndExpr.get(), BEF_end);
+      return StmtError();
+    }
+
+    // Build and check ++__begin expression.
+    BeginRef = BuildDeclRefExpr(BeginVar, BeginRefNonRefType,
+                                VK_LValue, ColonLoc);
+    if (BeginRef.isInvalid())
+      return StmtError();
+
+    IncrExpr = ActOnUnaryOp(S, ColonLoc, tok::plusplus, BeginRef.get());
+    IncrExpr = ActOnFinishFullExpr(IncrExpr.get());
+    if (IncrExpr.isInvalid()) {
+      NoteForRangeBeginEndFunction(*this, BeginExpr.get(), BEF_begin);
+      return StmtError();
+    }
+
+    // Build and check *__begin  expression.
+    BeginRef = BuildDeclRefExpr(BeginVar, BeginRefNonRefType,
+                                VK_LValue, ColonLoc);
+    if (BeginRef.isInvalid())
+      return StmtError();
+
+    ExprResult DerefExpr = ActOnUnaryOp(S, ColonLoc, tok::star, BeginRef.get());
+    if (DerefExpr.isInvalid()) {
+      NoteForRangeBeginEndFunction(*this, BeginExpr.get(), BEF_begin);
+      return StmtError();
+    }
+
+    // Attach  *__begin  as initializer for VD.
+    if (!LoopVar->isInvalidDecl()) {
+      AddInitializerToDecl(LoopVar, DerefExpr.get(), /*DirectInit=*/false,
+                           /*TypeMayContainAuto=*/true);
+      if (LoopVar->isInvalidDecl())
+        NoteForRangeBeginEndFunction(*this, BeginExpr.get(), BEF_begin);
+    }
+  } else {
+    // The range is implicitly used as a placeholder when it is dependent.
+    RangeVar->setUsed();
+  }
+
+  return Owned(new (Context) CXXForRangeStmt(RangeDS,
+                                     cast_or_null<DeclStmt>(BeginEndDecl.get()),
+                                             NotEqExpr.take(), IncrExpr.take(),
+                                             LoopVarDS, /*Body=*/0, ForLoc,
+                                             ColonLoc, RParenLoc));
+}
+
+/// FinishCXXForRangeStmt - Attach the body to a C++0x for-range statement.
+/// This is a separate step from ActOnCXXForRangeStmt because analysis of the
+/// body cannot be performed until after the type of the range variable is
+/// determined.
+StmtResult Sema::FinishCXXForRangeStmt(Stmt *S, Stmt *B) {
+  if (!S || !B)
+    return StmtError();
+
+  CXXForRangeStmt *ForStmt = cast<CXXForRangeStmt>(S);
+  ForStmt->setBody(B);
+
+  DiagnoseEmptyStmtBody(ForStmt->getRParenLoc(), B,
+                        diag::warn_empty_range_based_for_body);
+
+  return S;
+}
+
+StmtResult Sema::ActOnGotoStmt(SourceLocation GotoLoc,
+                               SourceLocation LabelLoc,
+                               LabelDecl *TheDecl) {
+  getCurFunction()->setHasBranchIntoScope();
+  TheDecl->setUsed();
+  return Owned(new (Context) GotoStmt(TheDecl, GotoLoc, LabelLoc));
+}
+
+StmtResult
+Sema::ActOnIndirectGotoStmt(SourceLocation GotoLoc, SourceLocation StarLoc,
+                            Expr *E) {
+  // Convert operand to void*
+  if (!E->isTypeDependent()) {
+    QualType ETy = E->getType();
+    QualType DestTy = Context.getPointerType(Context.VoidTy.withConst());
+    ExprResult ExprRes = Owned(E);
+    AssignConvertType ConvTy =
+      CheckSingleAssignmentConstraints(DestTy, ExprRes);
+    if (ExprRes.isInvalid())
+      return StmtError();
+    E = ExprRes.take();
+    if (DiagnoseAssignmentResult(ConvTy, StarLoc, DestTy, ETy, E, AA_Passing))
+      return StmtError();
+    E = MaybeCreateExprWithCleanups(E);
+  }
+
+  getCurFunction()->setHasIndirectGoto();
+
+  return Owned(new (Context) IndirectGotoStmt(GotoLoc, StarLoc, E));
+}
+
+StmtResult
+Sema::ActOnContinueStmt(SourceLocation ContinueLoc, Scope *CurScope) {
+  Scope *S = CurScope->getContinueParent();
+  if (!S) {
+    // C99 6.8.6.2p1: A break shall appear only in or as a loop body.
+    return StmtError(Diag(ContinueLoc, diag::err_continue_not_in_loop));
+  }
+
+  return Owned(new (Context) ContinueStmt(ContinueLoc));
+}
+
+StmtResult
+Sema::ActOnBreakStmt(SourceLocation BreakLoc, Scope *CurScope) {
+  Scope *S = CurScope->getBreakParent();
+  if (!S) {
+    // C99 6.8.6.3p1: A break shall appear only in or as a switch/loop body.
+    return StmtError(Diag(BreakLoc, diag::err_break_not_in_loop_or_switch));
+  }
+
+  return Owned(new (Context) BreakStmt(BreakLoc));
+}
+
+/// \brief Determine whether the given expression is a candidate for
+/// copy elision in either a return statement or a throw expression.
+///
+/// \param ReturnType If we're determining the copy elision candidate for
+/// a return statement, this is the return type of the function. If we're
+/// determining the copy elision candidate for a throw expression, this will
+/// be a NULL type.
+///
+/// \param E The expression being returned from the function or block, or
+/// being thrown.
+///
+/// \param AllowFunctionParameter Whether we allow function parameters to
+/// be considered NRVO candidates. C++ prohibits this for NRVO itself, but
+/// we re-use this logic to determine whether we should try to move as part of
+/// a return or throw (which does allow function parameters).
+///
+/// \returns The NRVO candidate variable, if the return statement may use the
+/// NRVO, or NULL if there is no such candidate.
+const VarDecl *Sema::getCopyElisionCandidate(QualType ReturnType,
+                                             Expr *E,
+                                             bool AllowFunctionParameter) {
+  QualType ExprType = E->getType();
+  // - in a return statement in a function with ...
+  // ... a class return type ...
+  if (!ReturnType.isNull()) {
+    if (!ReturnType->isRecordType())
+      return 0;
+    // ... the same cv-unqualified type as the function return type ...
+    if (!Context.hasSameUnqualifiedType(ReturnType, ExprType))
+      return 0;
+  }
+
+  // ... the expression is the name of a non-volatile automatic object
+  // (other than a function or catch-clause parameter)) ...
+  const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(E->IgnoreParens());
+  if (!DR)
+    return 0;
+  const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl());
+  if (!VD)
+    return 0;
+
+  // ...object (other than a function or catch-clause parameter)...
+  if (VD->getKind() != Decl::Var &&
+      !(AllowFunctionParameter && VD->getKind() == Decl::ParmVar))
+    return 0;
+  if (VD->isExceptionVariable()) return 0;
+
+  // ...automatic...
+  if (!VD->hasLocalStorage()) return 0;
+
+  // ...non-volatile...
+  if (VD->getType().isVolatileQualified()) return 0;
+  if (VD->getType()->isReferenceType()) return 0;
+
+  // __block variables can't be allocated in a way that permits NRVO.
+  if (VD->hasAttr<BlocksAttr>()) return 0;
+
+  // Variables with higher required alignment than their type's ABI
+  // alignment cannot use NRVO.
+  if (VD->hasAttr<AlignedAttr>() &&
+      Context.getDeclAlign(VD) > Context.getTypeAlignInChars(VD->getType()))
+    return 0;
+
+  return VD;
+}
+
+/// \brief Perform the initialization of a potentially-movable value, which
+/// is the result of return value.
+///
+/// This routine implements C++0x [class.copy]p33, which attempts to treat
+/// returned lvalues as rvalues in certain cases (to prefer move construction),
+/// then falls back to treating them as lvalues if that failed.
+ExprResult
+Sema::PerformMoveOrCopyInitialization(const InitializedEntity &Entity,
+                                      const VarDecl *NRVOCandidate,
+                                      QualType ResultType,
+                                      Expr *Value,
+                                      bool AllowNRVO) {
+  // C++0x [class.copy]p33:
+  //   When the criteria for elision of a copy operation are met or would
+  //   be met save for the fact that the source object is a function
+  //   parameter, and the object to be copied is designated by an lvalue,
+  //   overload resolution to select the constructor for the copy is first
+  //   performed as if the object were designated by an rvalue.
+  ExprResult Res = ExprError();
+  if (AllowNRVO &&
+      (NRVOCandidate || getCopyElisionCandidate(ResultType, Value, true))) {
+    ImplicitCastExpr AsRvalue(ImplicitCastExpr::OnStack,
+                              Value->getType(), CK_LValueToRValue,
+                              Value, VK_XValue);
+
+    Expr *InitExpr = &AsRvalue;
+    InitializationKind Kind
+      = InitializationKind::CreateCopy(Value->getLocStart(),
+                                       Value->getLocStart());
+    InitializationSequence Seq(*this, Entity, Kind, &InitExpr, 1);
+
+    //   [...] If overload resolution fails, or if the type of the first
+    //   parameter of the selected constructor is not an rvalue reference
+    //   to the object's type (possibly cv-qualified), overload resolution
+    //   is performed again, considering the object as an lvalue.
+    if (Seq) {
+      for (InitializationSequence::step_iterator Step = Seq.step_begin(),
+           StepEnd = Seq.step_end();
+           Step != StepEnd; ++Step) {
+        if (Step->Kind != InitializationSequence::SK_ConstructorInitialization)
+          continue;
+
+        CXXConstructorDecl *Constructor
+        = cast<CXXConstructorDecl>(Step->Function.Function);
+
+        const RValueReferenceType *RRefType
+          = Constructor->getParamDecl(0)->getType()
+                                                 ->getAs<RValueReferenceType>();
+
+        // If we don't meet the criteria, break out now.
+        if (!RRefType ||
+            !Context.hasSameUnqualifiedType(RRefType->getPointeeType(),
+                            Context.getTypeDeclType(Constructor->getParent())))
+          break;
+
+        // Promote "AsRvalue" to the heap, since we now need this
+        // expression node to persist.
+        Value = ImplicitCastExpr::Create(Context, Value->getType(),
+                                         CK_LValueToRValue, Value, 0,
+                                         VK_XValue);
+
+        // Complete type-checking the initialization of the return type
+        // using the constructor we found.
+        Res = Seq.Perform(*this, Entity, Kind, MultiExprArg(&Value, 1));
+      }
+    }
+  }
+
+  // Either we didn't meet the criteria for treating an lvalue as an rvalue,
+  // above, or overload resolution failed. Either way, we need to try
+  // (again) now with the return value expression as written.
+  if (Res.isInvalid())
+    Res = PerformCopyInitialization(Entity, SourceLocation(), Value);
+
+  return Res;
+}
+
+/// ActOnCapScopeReturnStmt - Utility routine to type-check return statements
+/// for capturing scopes.
+///
+StmtResult
+Sema::ActOnCapScopeReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) {
+  // If this is the first return we've seen, infer the return type.
+  // [expr.prim.lambda]p4 in C++11; block literals follow a superset of those
+  // rules which allows multiple return statements.
+  CapturingScopeInfo *CurCap = cast<CapturingScopeInfo>(getCurFunction());
+  if (CurCap->HasImplicitReturnType) {
+    QualType ReturnT;
+    if (RetValExp && !isa<InitListExpr>(RetValExp)) {
+      ExprResult Result = DefaultFunctionArrayLvalueConversion(RetValExp);
+      if (Result.isInvalid())
+        return StmtError();
+      RetValExp = Result.take();
+
+      if (!RetValExp->isTypeDependent())
+        ReturnT = RetValExp->getType();
+      else
+        ReturnT = Context.DependentTy;
+    } else { 
+      if (RetValExp) {
+        // C++11 [expr.lambda.prim]p4 bans inferring the result from an
+        // initializer list, because it is not an expression (even
+        // though we represent it as one). We still deduce 'void'.
+        Diag(ReturnLoc, diag::err_lambda_return_init_list)
+          << RetValExp->getSourceRange();
+      }
+
+      ReturnT = Context.VoidTy;
+    }
+    // We require the return types to strictly match here.
+    if (!CurCap->ReturnType.isNull() &&
+        !CurCap->ReturnType->isDependentType() &&
+        !ReturnT->isDependentType() &&
+        !Context.hasSameType(ReturnT, CurCap->ReturnType)) { 
+      Diag(ReturnLoc, diag::err_typecheck_missing_return_type_incompatible) 
+          << ReturnT << CurCap->ReturnType
+          << (getCurLambda() != 0);
+      return StmtError();
+    }
+    CurCap->ReturnType = ReturnT;
+  }
+  QualType FnRetType = CurCap->ReturnType;
+  assert(!FnRetType.isNull());
+
+  if (BlockScopeInfo *CurBlock = dyn_cast<BlockScopeInfo>(CurCap)) {
+    if (CurBlock->FunctionType->getAs<FunctionType>()->getNoReturnAttr()) {
+      Diag(ReturnLoc, diag::err_noreturn_block_has_return_expr);
+      return StmtError();
+    }
+  } else {
+    LambdaScopeInfo *LSI = cast<LambdaScopeInfo>(CurCap);
+    if (LSI->CallOperator->getType()->getAs<FunctionType>()->getNoReturnAttr()){
+      Diag(ReturnLoc, diag::err_noreturn_lambda_has_return_expr);
+      return StmtError();
+    }
+  }
+
+  // Otherwise, verify that this result type matches the previous one.  We are
+  // pickier with blocks than for normal functions because we don't have GCC
+  // compatibility to worry about here.
+  const VarDecl *NRVOCandidate = 0;
+  if (FnRetType->isDependentType()) {
+    // Delay processing for now.  TODO: there are lots of dependent
+    // types we can conclusively prove aren't void.
+  } else if (FnRetType->isVoidType()) {
+    if (RetValExp && !isa<InitListExpr>(RetValExp) &&
+        !(getLangOpts().CPlusPlus &&
+          (RetValExp->isTypeDependent() ||
+           RetValExp->getType()->isVoidType()))) {
+      if (!getLangOpts().CPlusPlus &&
+          RetValExp->getType()->isVoidType())
+        Diag(ReturnLoc, diag::ext_return_has_void_expr) << "literal" << 2;
+      else {
+        Diag(ReturnLoc, diag::err_return_block_has_expr);
+        RetValExp = 0;
+      }
+    }
+  } else if (!RetValExp) {
+    return StmtError(Diag(ReturnLoc, diag::err_block_return_missing_expr));
+  } else if (!RetValExp->isTypeDependent()) {
+    // we have a non-void block with an expression, continue checking
+
+    // C99 6.8.6.4p3(136): The return statement is not an assignment. The
+    // overlap restriction of subclause 6.5.16.1 does not apply to the case of
+    // function return.
+
+    // In C++ the return statement is handled via a copy initialization.
+    // the C version of which boils down to CheckSingleAssignmentConstraints.
+    NRVOCandidate = getCopyElisionCandidate(FnRetType, RetValExp, false);
+    InitializedEntity Entity = InitializedEntity::InitializeResult(ReturnLoc,
+                                                                   FnRetType,
+                                                          NRVOCandidate != 0);
+    ExprResult Res = PerformMoveOrCopyInitialization(Entity, NRVOCandidate,
+                                                     FnRetType, RetValExp);
+    if (Res.isInvalid()) {
+      // FIXME: Cleanup temporaries here, anyway?
+      return StmtError();
+    }
+    RetValExp = Res.take();
+    CheckReturnStackAddr(RetValExp, FnRetType, ReturnLoc);
+  }
+
+  if (RetValExp) {
+    CheckImplicitConversions(RetValExp, ReturnLoc);
+    RetValExp = MaybeCreateExprWithCleanups(RetValExp);
+  }
+  ReturnStmt *Result = new (Context) ReturnStmt(ReturnLoc, RetValExp,
+                                                NRVOCandidate);
+
+  // If we need to check for the named return value optimization, save the
+  // return statement in our scope for later processing.
+  if (getLangOpts().CPlusPlus && FnRetType->isRecordType() && 
+      !CurContext->isDependentContext())
+    FunctionScopes.back()->Returns.push_back(Result);
+
+  return Owned(Result);
+}
+
+StmtResult
+Sema::ActOnReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) {
+  // Check for unexpanded parameter packs.
+  if (RetValExp && DiagnoseUnexpandedParameterPack(RetValExp))
+    return StmtError();
+  
+  if (isa<CapturingScopeInfo>(getCurFunction()))
+    return ActOnCapScopeReturnStmt(ReturnLoc, RetValExp);
+
+  QualType FnRetType;
+  QualType RelatedRetType;
+  if (const FunctionDecl *FD = getCurFunctionDecl()) {
+    FnRetType = FD->getResultType();
+    if (FD->hasAttr<NoReturnAttr>() ||
+        FD->getType()->getAs<FunctionType>()->getNoReturnAttr())
+      Diag(ReturnLoc, diag::warn_noreturn_function_has_return_expr)
+        << FD->getDeclName();
+  } else if (ObjCMethodDecl *MD = getCurMethodDecl()) {
+    FnRetType = MD->getResultType();
+    if (MD->hasRelatedResultType() && MD->getClassInterface()) {
+      // In the implementation of a method with a related return type, the
+      // type used to type-check the validity of return statements within the 
+      // method body is a pointer to the type of the class being implemented.
+      RelatedRetType = Context.getObjCInterfaceType(MD->getClassInterface());
+      RelatedRetType = Context.getObjCObjectPointerType(RelatedRetType);
+    }
+  } else // If we don't have a function/method context, bail.
+    return StmtError();
+
+  ReturnStmt *Result = 0;
+  if (FnRetType->isVoidType()) {
+    if (RetValExp) {
+      if (isa<InitListExpr>(RetValExp)) {
+        // We simply never allow init lists as the return value of void
+        // functions. This is compatible because this was never allowed before,
+        // so there's no legacy code to deal with.
+        NamedDecl *CurDecl = getCurFunctionOrMethodDecl();
+        int FunctionKind = 0;
+        if (isa<ObjCMethodDecl>(CurDecl))
+          FunctionKind = 1;
+        else if (isa<CXXConstructorDecl>(CurDecl))
+          FunctionKind = 2;
+        else if (isa<CXXDestructorDecl>(CurDecl))
+          FunctionKind = 3;
+
+        Diag(ReturnLoc, diag::err_return_init_list)
+          << CurDecl->getDeclName() << FunctionKind
+          << RetValExp->getSourceRange();
+
+        // Drop the expression.
+        RetValExp = 0;
+      } else if (!RetValExp->isTypeDependent()) {
+        // C99 6.8.6.4p1 (ext_ since GCC warns)
+        unsigned D = diag::ext_return_has_expr;
+        if (RetValExp->getType()->isVoidType())
+          D = diag::ext_return_has_void_expr;
+        else {
+          ExprResult Result = Owned(RetValExp);
+          Result = IgnoredValueConversions(Result.take());
+          if (Result.isInvalid())
+            return StmtError();
+          RetValExp = Result.take();
+          RetValExp = ImpCastExprToType(RetValExp,
+                                        Context.VoidTy, CK_ToVoid).take();
+        }
+
+        // return (some void expression); is legal in C++.
+        if (D != diag::ext_return_has_void_expr ||
+            !getLangOpts().CPlusPlus) {
+          NamedDecl *CurDecl = getCurFunctionOrMethodDecl();
+
+          int FunctionKind = 0;
+          if (isa<ObjCMethodDecl>(CurDecl))
+            FunctionKind = 1;
+          else if (isa<CXXConstructorDecl>(CurDecl))
+            FunctionKind = 2;
+          else if (isa<CXXDestructorDecl>(CurDecl))
+            FunctionKind = 3;
+
+          Diag(ReturnLoc, D)
+            << CurDecl->getDeclName() << FunctionKind
+            << RetValExp->getSourceRange();
+        }
+      }
+
+      if (RetValExp) {
+        CheckImplicitConversions(RetValExp, ReturnLoc);
+        RetValExp = MaybeCreateExprWithCleanups(RetValExp);
+      }
+    }
+
+    Result = new (Context) ReturnStmt(ReturnLoc, RetValExp, 0);
+  } else if (!RetValExp && !FnRetType->isDependentType()) {
+    unsigned DiagID = diag::warn_return_missing_expr;  // C90 6.6.6.4p4
+    // C99 6.8.6.4p1 (ext_ since GCC warns)
+    if (getLangOpts().C99) DiagID = diag::ext_return_missing_expr;
+
+    if (FunctionDecl *FD = getCurFunctionDecl())
+      Diag(ReturnLoc, DiagID) << FD->getIdentifier() << 0/*fn*/;
+    else
+      Diag(ReturnLoc, DiagID) << getCurMethodDecl()->getDeclName() << 1/*meth*/;
+    Result = new (Context) ReturnStmt(ReturnLoc);
+  } else {
+    const VarDecl *NRVOCandidate = 0;
+    if (!FnRetType->isDependentType() && !RetValExp->isTypeDependent()) {
+      // we have a non-void function with an expression, continue checking
+
+      if (!RelatedRetType.isNull()) {
+        // If we have a related result type, perform an extra conversion here.
+        // FIXME: The diagnostics here don't really describe what is happening.
+        InitializedEntity Entity =
+            InitializedEntity::InitializeTemporary(RelatedRetType);
+        
+        ExprResult Res = PerformCopyInitialization(Entity, SourceLocation(),
+                                                   RetValExp);
+        if (Res.isInvalid()) {
+          // FIXME: Cleanup temporaries here, anyway?
+          return StmtError();
+        }
+        RetValExp = Res.takeAs<Expr>();
+      }
+
+      // C99 6.8.6.4p3(136): The return statement is not an assignment. The
+      // overlap restriction of subclause 6.5.16.1 does not apply to the case of
+      // function return.
+
+      // In C++ the return statement is handled via a copy initialization,
+      // the C version of which boils down to CheckSingleAssignmentConstraints.
+      NRVOCandidate = getCopyElisionCandidate(FnRetType, RetValExp, false);
+      InitializedEntity Entity = InitializedEntity::InitializeResult(ReturnLoc,
+                                                                     FnRetType,
+                                                            NRVOCandidate != 0);
+      ExprResult Res = PerformMoveOrCopyInitialization(Entity, NRVOCandidate,
+                                                       FnRetType, RetValExp);
+      if (Res.isInvalid()) {
+        // FIXME: Cleanup temporaries here, anyway?
+        return StmtError();
+      }
+
+      RetValExp = Res.takeAs<Expr>();
+      if (RetValExp)
+        CheckReturnStackAddr(RetValExp, FnRetType, ReturnLoc);
+    }
+
+    if (RetValExp) {
+      CheckImplicitConversions(RetValExp, ReturnLoc);
+      RetValExp = MaybeCreateExprWithCleanups(RetValExp);
+    }
+    Result = new (Context) ReturnStmt(ReturnLoc, RetValExp, NRVOCandidate);
+  }
+
+  // If we need to check for the named return value optimization, save the
+  // return statement in our scope for later processing.
+  if (getLangOpts().CPlusPlus && FnRetType->isRecordType() &&
+      !CurContext->isDependentContext())
+    FunctionScopes.back()->Returns.push_back(Result);
+  
+  return Owned(Result);
+}
+
+/// CheckAsmLValue - GNU C has an extremely ugly extension whereby they silently
+/// ignore "noop" casts in places where an lvalue is required by an inline asm.
+/// We emulate this behavior when -fheinous-gnu-extensions is specified, but
+/// provide a strong guidance to not use it.
+///
+/// This method checks to see if the argument is an acceptable l-value and
+/// returns false if it is a case we can handle.
+static bool CheckAsmLValue(const Expr *E, Sema &S) {
+  // Type dependent expressions will be checked during instantiation.
+  if (E->isTypeDependent())
+    return false;
+
+  if (E->isLValue())
+    return false;  // Cool, this is an lvalue.
+
+  // Okay, this is not an lvalue, but perhaps it is the result of a cast that we
+  // are supposed to allow.
+  const Expr *E2 = E->IgnoreParenNoopCasts(S.Context);
+  if (E != E2 && E2->isLValue()) {
+    if (!S.getLangOpts().HeinousExtensions)
+      S.Diag(E2->getLocStart(), diag::err_invalid_asm_cast_lvalue)
+        << E->getSourceRange();
+    else
+      S.Diag(E2->getLocStart(), diag::warn_invalid_asm_cast_lvalue)
+        << E->getSourceRange();
+    // Accept, even if we emitted an error diagnostic.
+    return false;
+  }
+
+  // None of the above, just randomly invalid non-lvalue.
+  return true;
+}
+
+/// isOperandMentioned - Return true if the specified operand # is mentioned
+/// anywhere in the decomposed asm string.
+static bool isOperandMentioned(unsigned OpNo, 
+                         ArrayRef<AsmStmt::AsmStringPiece> AsmStrPieces) {
+  for (unsigned p = 0, e = AsmStrPieces.size(); p != e; ++p) {
+    const AsmStmt::AsmStringPiece &Piece = AsmStrPieces[p];
+    if (!Piece.isOperand()) continue;
+    
+    // If this is a reference to the input and if the input was the smaller
+    // one, then we have to reject this asm.
+    if (Piece.getOperandNo() == OpNo)
+      return true;
+  }
+ 
+  return false;
+}
+
+StmtResult Sema::ActOnAsmStmt(SourceLocation AsmLoc, bool IsSimple,
+                              bool IsVolatile, unsigned NumOutputs,
+                              unsigned NumInputs, IdentifierInfo **Names,
+                              MultiExprArg constraints, MultiExprArg exprs,
+                              Expr *asmString, MultiExprArg clobbers,
+                              SourceLocation RParenLoc, bool MSAsm) {
+  unsigned NumClobbers = clobbers.size();
+  StringLiteral **Constraints =
+    reinterpret_cast<StringLiteral**>(constraints.get());
+  Expr **Exprs = exprs.get();
+  StringLiteral *AsmString = cast<StringLiteral>(asmString);
+  StringLiteral **Clobbers = reinterpret_cast<StringLiteral**>(clobbers.get());
+
+  SmallVector<TargetInfo::ConstraintInfo, 4> OutputConstraintInfos;
+
+  // The parser verifies that there is a string literal here.
+  if (!AsmString->isAscii())
+    return StmtError(Diag(AsmString->getLocStart(),diag::err_asm_wide_character)
+      << AsmString->getSourceRange());
+
+  for (unsigned i = 0; i != NumOutputs; i++) {
+    StringLiteral *Literal = Constraints[i];
+    if (!Literal->isAscii())
+      return StmtError(Diag(Literal->getLocStart(),diag::err_asm_wide_character)
+        << Literal->getSourceRange());
+
+    StringRef OutputName;
+    if (Names[i])
+      OutputName = Names[i]->getName();
+
+    TargetInfo::ConstraintInfo Info(Literal->getString(), OutputName);
+    if (!Context.getTargetInfo().validateOutputConstraint(Info))
+      return StmtError(Diag(Literal->getLocStart(),
+                            diag::err_asm_invalid_output_constraint)
+                       << Info.getConstraintStr());
+
+    // Check that the output exprs are valid lvalues.
+    Expr *OutputExpr = Exprs[i];
+    if (CheckAsmLValue(OutputExpr, *this)) {
+      return StmtError(Diag(OutputExpr->getLocStart(),
+                  diag::err_asm_invalid_lvalue_in_output)
+        << OutputExpr->getSourceRange());
+    }
+
+    OutputConstraintInfos.push_back(Info);
+  }
+
+  SmallVector<TargetInfo::ConstraintInfo, 4> InputConstraintInfos;
+
+  for (unsigned i = NumOutputs, e = NumOutputs + NumInputs; i != e; i++) {
+    StringLiteral *Literal = Constraints[i];
+    if (!Literal->isAscii())
+      return StmtError(Diag(Literal->getLocStart(),diag::err_asm_wide_character)
+        << Literal->getSourceRange());
+
+    StringRef InputName;
+    if (Names[i])
+      InputName = Names[i]->getName();
+
+    TargetInfo::ConstraintInfo Info(Literal->getString(), InputName);
+    if (!Context.getTargetInfo().validateInputConstraint(OutputConstraintInfos.data(),
+                                                NumOutputs, Info)) {
+      return StmtError(Diag(Literal->getLocStart(),
+                            diag::err_asm_invalid_input_constraint)
+                       << Info.getConstraintStr());
+    }
+
+    Expr *InputExpr = Exprs[i];
+
+    // Only allow void types for memory constraints.
+    if (Info.allowsMemory() && !Info.allowsRegister()) {
+      if (CheckAsmLValue(InputExpr, *this))
+        return StmtError(Diag(InputExpr->getLocStart(),
+                              diag::err_asm_invalid_lvalue_in_input)
+                         << Info.getConstraintStr()
+                         << InputExpr->getSourceRange());
+    }
+
+    if (Info.allowsRegister()) {
+      if (InputExpr->getType()->isVoidType()) {
+        return StmtError(Diag(InputExpr->getLocStart(),
+                              diag::err_asm_invalid_type_in_input)
+          << InputExpr->getType() << Info.getConstraintStr()
+          << InputExpr->getSourceRange());
+      }
+    }
+
+    ExprResult Result = DefaultFunctionArrayLvalueConversion(Exprs[i]);
+    if (Result.isInvalid())
+      return StmtError();
+
+    Exprs[i] = Result.take();
+    InputConstraintInfos.push_back(Info);
+  }
+
+  // Check that the clobbers are valid.
+  for (unsigned i = 0; i != NumClobbers; i++) {
+    StringLiteral *Literal = Clobbers[i];
+    if (!Literal->isAscii())
+      return StmtError(Diag(Literal->getLocStart(),diag::err_asm_wide_character)
+        << Literal->getSourceRange());
+
+    StringRef Clobber = Literal->getString();
+
+    if (!Context.getTargetInfo().isValidClobber(Clobber))
+      return StmtError(Diag(Literal->getLocStart(),
+                  diag::err_asm_unknown_register_name) << Clobber);
+  }
+
+  AsmStmt *NS =
+    new (Context) AsmStmt(Context, AsmLoc, IsSimple, IsVolatile, MSAsm,
+                          NumOutputs, NumInputs, Names, Constraints, Exprs,
+                          AsmString, NumClobbers, Clobbers, RParenLoc);
+  // Validate the asm string, ensuring it makes sense given the operands we
+  // have.
+  SmallVector<AsmStmt::AsmStringPiece, 8> Pieces;
+  unsigned DiagOffs;
+  if (unsigned DiagID = NS->AnalyzeAsmString(Pieces, Context, DiagOffs)) {
+    Diag(getLocationOfStringLiteralByte(AsmString, DiagOffs), DiagID)
+           << AsmString->getSourceRange();
+    return StmtError();
+  }
+
+  // Validate tied input operands for type mismatches.
+  for (unsigned i = 0, e = InputConstraintInfos.size(); i != e; ++i) {
+    TargetInfo::ConstraintInfo &Info = InputConstraintInfos[i];
+
+    // If this is a tied constraint, verify that the output and input have
+    // either exactly the same type, or that they are int/ptr operands with the
+    // same size (int/long, int*/long, are ok etc).
+    if (!Info.hasTiedOperand()) continue;
+
+    unsigned TiedTo = Info.getTiedOperand();
+    unsigned InputOpNo = i+NumOutputs;
+    Expr *OutputExpr = Exprs[TiedTo];
+    Expr *InputExpr = Exprs[InputOpNo];
+
+    if (OutputExpr->isTypeDependent() || InputExpr->isTypeDependent())
+      continue;
+
+    QualType InTy = InputExpr->getType();
+    QualType OutTy = OutputExpr->getType();
+    if (Context.hasSameType(InTy, OutTy))
+      continue;  // All types can be tied to themselves.
+
+    // Decide if the input and output are in the same domain (integer/ptr or
+    // floating point.
+    enum AsmDomain {
+      AD_Int, AD_FP, AD_Other
+    } InputDomain, OutputDomain;
+
+    if (InTy->isIntegerType() || InTy->isPointerType())
+      InputDomain = AD_Int;
+    else if (InTy->isRealFloatingType())
+      InputDomain = AD_FP;
+    else
+      InputDomain = AD_Other;
+
+    if (OutTy->isIntegerType() || OutTy->isPointerType())
+      OutputDomain = AD_Int;
+    else if (OutTy->isRealFloatingType())
+      OutputDomain = AD_FP;
+    else
+      OutputDomain = AD_Other;
+
+    // They are ok if they are the same size and in the same domain.  This
+    // allows tying things like:
+    //   void* to int*
+    //   void* to int            if they are the same size.
+    //   double to long double   if they are the same size.
+    //
+    uint64_t OutSize = Context.getTypeSize(OutTy);
+    uint64_t InSize = Context.getTypeSize(InTy);
+    if (OutSize == InSize && InputDomain == OutputDomain &&
+        InputDomain != AD_Other)
+      continue;
+
+    // If the smaller input/output operand is not mentioned in the asm string,
+    // then we can promote the smaller one to a larger input and the asm string
+    // won't notice.
+    bool SmallerValueMentioned = false;
+    
+    // If this is a reference to the input and if the input was the smaller
+    // one, then we have to reject this asm.
+    if (isOperandMentioned(InputOpNo, Pieces)) {
+      // This is a use in the asm string of the smaller operand.  Since we
+      // codegen this by promoting to a wider value, the asm will get printed
+      // "wrong".
+      SmallerValueMentioned |= InSize < OutSize;
+    }
+    if (isOperandMentioned(TiedTo, Pieces)) {
+      // If this is a reference to the output, and if the output is the larger
+      // value, then it's ok because we'll promote the input to the larger type.
+      SmallerValueMentioned |= OutSize < InSize;
+    }
+
+    // If the smaller value wasn't mentioned in the asm string, and if the
+    // output was a register, just extend the shorter one to the size of the
+    // larger one.
+    if (!SmallerValueMentioned && InputDomain != AD_Other &&
+        OutputConstraintInfos[TiedTo].allowsRegister())
+      continue;
+    
+    // Either both of the operands were mentioned or the smaller one was
+    // mentioned.  One more special case that we'll allow: if the tied input is
+    // integer, unmentioned, and is a constant, then we'll allow truncating it
+    // down to the size of the destination.
+    if (InputDomain == AD_Int && OutputDomain == AD_Int &&
+        !isOperandMentioned(InputOpNo, Pieces) &&
+        InputExpr->isEvaluatable(Context)) {
+      CastKind castKind =
+        (OutTy->isBooleanType() ? CK_IntegralToBoolean : CK_IntegralCast);
+      InputExpr = ImpCastExprToType(InputExpr, OutTy, castKind).take();
+      Exprs[InputOpNo] = InputExpr;
+      NS->setInputExpr(i, InputExpr);
+      continue;
+    }
+    
+    Diag(InputExpr->getLocStart(),
+         diag::err_asm_tying_incompatible_types)
+      << InTy << OutTy << OutputExpr->getSourceRange()
+      << InputExpr->getSourceRange();
+    return StmtError();
+  }
+
+  return Owned(NS);
+}
+
+StmtResult
+Sema::ActOnObjCAtCatchStmt(SourceLocation AtLoc,
+                           SourceLocation RParen, Decl *Parm,
+                           Stmt *Body) {
+  VarDecl *Var = cast_or_null<VarDecl>(Parm);
+  if (Var && Var->isInvalidDecl())
+    return StmtError();
+
+  return Owned(new (Context) ObjCAtCatchStmt(AtLoc, RParen, Var, Body));
+}
+
+StmtResult
+Sema::ActOnObjCAtFinallyStmt(SourceLocation AtLoc, Stmt *Body) {
+  return Owned(new (Context) ObjCAtFinallyStmt(AtLoc, Body));
+}
+
+StmtResult
+Sema::ActOnObjCAtTryStmt(SourceLocation AtLoc, Stmt *Try,
+                         MultiStmtArg CatchStmts, Stmt *Finally) {
+  if (!getLangOpts().ObjCExceptions)
+    Diag(AtLoc, diag::err_objc_exceptions_disabled) << "@try";
+
+  getCurFunction()->setHasBranchProtectedScope();
+  unsigned NumCatchStmts = CatchStmts.size();
+  return Owned(ObjCAtTryStmt::Create(Context, AtLoc, Try,
+                                     CatchStmts.release(),
+                                     NumCatchStmts,
+                                     Finally));
+}
+
+StmtResult Sema::BuildObjCAtThrowStmt(SourceLocation AtLoc,
+                                                  Expr *Throw) {
+  if (Throw) {
+    Throw = MaybeCreateExprWithCleanups(Throw);
+    ExprResult Result = DefaultLvalueConversion(Throw);
+    if (Result.isInvalid())
+      return StmtError();
+
+    Throw = Result.take();
+    QualType ThrowType = Throw->getType();
+    // Make sure the expression type is an ObjC pointer or "void *".
+    if (!ThrowType->isDependentType() &&
+        !ThrowType->isObjCObjectPointerType()) {
+      const PointerType *PT = ThrowType->getAs<PointerType>();
+      if (!PT || !PT->getPointeeType()->isVoidType())
+        return StmtError(Diag(AtLoc, diag::error_objc_throw_expects_object)
+                         << Throw->getType() << Throw->getSourceRange());
+    }
+  }
+
+  return Owned(new (Context) ObjCAtThrowStmt(AtLoc, Throw));
+}
+
+StmtResult
+Sema::ActOnObjCAtThrowStmt(SourceLocation AtLoc, Expr *Throw,
+                           Scope *CurScope) {
+  if (!getLangOpts().ObjCExceptions)
+    Diag(AtLoc, diag::err_objc_exceptions_disabled) << "@throw";
+
+  if (!Throw) {
+    // @throw without an expression designates a rethrow (which much occur
+    // in the context of an @catch clause).
+    Scope *AtCatchParent = CurScope;
+    while (AtCatchParent && !AtCatchParent->isAtCatchScope())
+      AtCatchParent = AtCatchParent->getParent();
+    if (!AtCatchParent)
+      return StmtError(Diag(AtLoc, diag::error_rethrow_used_outside_catch));
+  }
+  
+  return BuildObjCAtThrowStmt(AtLoc, Throw);
+}
+
+ExprResult
+Sema::ActOnObjCAtSynchronizedOperand(SourceLocation atLoc, Expr *operand) {
+  ExprResult result = DefaultLvalueConversion(operand);
+  if (result.isInvalid())
+    return ExprError();
+  operand = result.take();
+
+  // Make sure the expression type is an ObjC pointer or "void *".
+  QualType type = operand->getType();
+  if (!type->isDependentType() &&
+      !type->isObjCObjectPointerType()) {
+    const PointerType *pointerType = type->getAs<PointerType>();
+    if (!pointerType || !pointerType->getPointeeType()->isVoidType())
+      return Diag(atLoc, diag::error_objc_synchronized_expects_object)
+               << type << operand->getSourceRange();
+  }
+
+  // The operand to @synchronized is a full-expression.
+  return MaybeCreateExprWithCleanups(operand);
+}
+
+StmtResult
+Sema::ActOnObjCAtSynchronizedStmt(SourceLocation AtLoc, Expr *SyncExpr,
+                                  Stmt *SyncBody) {
+  // We can't jump into or indirect-jump out of a @synchronized block.
+  getCurFunction()->setHasBranchProtectedScope();
+  return Owned(new (Context) ObjCAtSynchronizedStmt(AtLoc, SyncExpr, SyncBody));
+}
+
+/// ActOnCXXCatchBlock - Takes an exception declaration and a handler block
+/// and creates a proper catch handler from them.
+StmtResult
+Sema::ActOnCXXCatchBlock(SourceLocation CatchLoc, Decl *ExDecl,
+                         Stmt *HandlerBlock) {
+  // There's nothing to test that ActOnExceptionDecl didn't already test.
+  return Owned(new (Context) CXXCatchStmt(CatchLoc,
+                                          cast_or_null<VarDecl>(ExDecl),
+                                          HandlerBlock));
+}
+
+StmtResult
+Sema::ActOnObjCAutoreleasePoolStmt(SourceLocation AtLoc, Stmt *Body) {
+  getCurFunction()->setHasBranchProtectedScope();
+  return Owned(new (Context) ObjCAutoreleasePoolStmt(AtLoc, Body));
+}
+
+namespace {
+
+class TypeWithHandler {
+  QualType t;
+  CXXCatchStmt *stmt;
+public:
+  TypeWithHandler(const QualType &type, CXXCatchStmt *statement)
+  : t(type), stmt(statement) {}
+
+  // An arbitrary order is fine as long as it places identical
+  // types next to each other.
+  bool operator<(const TypeWithHandler &y) const {
+    if (t.getAsOpaquePtr() < y.t.getAsOpaquePtr())
+      return true;
+    if (t.getAsOpaquePtr() > y.t.getAsOpaquePtr())
+      return false;
+    else
+      return getTypeSpecStartLoc() < y.getTypeSpecStartLoc();
+  }
+
+  bool operator==(const TypeWithHandler& other) const {
+    return t == other.t;
+  }
+
+  CXXCatchStmt *getCatchStmt() const { return stmt; }
+  SourceLocation getTypeSpecStartLoc() const {
+    return stmt->getExceptionDecl()->getTypeSpecStartLoc();
+  }
+};
+
+}
+
+/// ActOnCXXTryBlock - Takes a try compound-statement and a number of
+/// handlers and creates a try statement from them.
+StmtResult
+Sema::ActOnCXXTryBlock(SourceLocation TryLoc, Stmt *TryBlock,
+                       MultiStmtArg RawHandlers) {
+  // Don't report an error if 'try' is used in system headers.
+  if (!getLangOpts().CXXExceptions &&
+      !getSourceManager().isInSystemHeader(TryLoc))
+      Diag(TryLoc, diag::err_exceptions_disabled) << "try";
+
+  unsigned NumHandlers = RawHandlers.size();
+  assert(NumHandlers > 0 &&
+         "The parser shouldn't call this if there are no handlers.");
+  Stmt **Handlers = RawHandlers.get();
+
+  SmallVector<TypeWithHandler, 8> TypesWithHandlers;
+
+  for (unsigned i = 0; i < NumHandlers; ++i) {
+    CXXCatchStmt *Handler = cast<CXXCatchStmt>(Handlers[i]);
+    if (!Handler->getExceptionDecl()) {
+      if (i < NumHandlers - 1)
+        return StmtError(Diag(Handler->getLocStart(),
+                              diag::err_early_catch_all));
+
+      continue;
+    }
+
+    const QualType CaughtType = Handler->getCaughtType();
+    const QualType CanonicalCaughtType = Context.getCanonicalType(CaughtType);
+    TypesWithHandlers.push_back(TypeWithHandler(CanonicalCaughtType, Handler));
+  }
+
+  // Detect handlers for the same type as an earlier one.
+  if (NumHandlers > 1) {
+    llvm::array_pod_sort(TypesWithHandlers.begin(), TypesWithHandlers.end());
+
+    TypeWithHandler prev = TypesWithHandlers[0];
+    for (unsigned i = 1; i < TypesWithHandlers.size(); ++i) {
+      TypeWithHandler curr = TypesWithHandlers[i];
+
+      if (curr == prev) {
+        Diag(curr.getTypeSpecStartLoc(),
+             diag::warn_exception_caught_by_earlier_handler)
+          << curr.getCatchStmt()->getCaughtType().getAsString();
+        Diag(prev.getTypeSpecStartLoc(),
+             diag::note_previous_exception_handler)
+          << prev.getCatchStmt()->getCaughtType().getAsString();
+      }
+
+      prev = curr;
+    }
+  }
+
+  getCurFunction()->setHasBranchProtectedScope();
+
+  // FIXME: We should detect handlers that cannot catch anything because an
+  // earlier handler catches a superclass. Need to find a method that is not
+  // quadratic for this.
+  // Neither of these are explicitly forbidden, but every compiler detects them
+  // and warns.
+
+  return Owned(CXXTryStmt::Create(Context, TryLoc, TryBlock,
+                                  Handlers, NumHandlers));
+}
+
+StmtResult
+Sema::ActOnSEHTryBlock(bool IsCXXTry,
+                       SourceLocation TryLoc,
+                       Stmt *TryBlock,
+                       Stmt *Handler) {
+  assert(TryBlock && Handler);
+
+  getCurFunction()->setHasBranchProtectedScope();
+
+  return Owned(SEHTryStmt::Create(Context,IsCXXTry,TryLoc,TryBlock,Handler));
+}
+
+StmtResult
+Sema::ActOnSEHExceptBlock(SourceLocation Loc,
+                          Expr *FilterExpr,
+                          Stmt *Block) {
+  assert(FilterExpr && Block);
+
+  if(!FilterExpr->getType()->isIntegerType()) {
+    return StmtError(Diag(FilterExpr->getExprLoc(),
+                     diag::err_filter_expression_integral)
+                     << FilterExpr->getType());
+  }
+
+  return Owned(SEHExceptStmt::Create(Context,Loc,FilterExpr,Block));
+}
+
+StmtResult
+Sema::ActOnSEHFinallyBlock(SourceLocation Loc,
+                           Stmt *Block) {
+  assert(Block);
+  return Owned(SEHFinallyStmt::Create(Context,Loc,Block));
+}
+
+StmtResult Sema::BuildMSDependentExistsStmt(SourceLocation KeywordLoc,
+                                            bool IsIfExists,
+                                            NestedNameSpecifierLoc QualifierLoc,
+                                            DeclarationNameInfo NameInfo,
+                                            Stmt *Nested)
+{
+  return new (Context) MSDependentExistsStmt(KeywordLoc, IsIfExists,
+                                             QualifierLoc, NameInfo, 
+                                             cast<CompoundStmt>(Nested));
+}
+
+
+StmtResult Sema::ActOnMSDependentExistsStmt(SourceLocation KeywordLoc, 
+                                            bool IsIfExists,
+                                            CXXScopeSpec &SS, 
+                                            UnqualifiedId &Name,
+                                            Stmt *Nested) {
+  return BuildMSDependentExistsStmt(KeywordLoc, IsIfExists, 
+                                    SS.getWithLocInContext(Context),
+                                    GetNameFromUnqualifiedId(Name),
+                                    Nested);
+}
diff --git a/clang/lib/Sema/SemaStmtAttr.cpp b/clang/lib/Sema/SemaStmtAttr.cpp
new file mode 100644
index 0000000..21c3297
--- /dev/null
+++ b/clang/lib/Sema/SemaStmtAttr.cpp
@@ -0,0 +1,48 @@
+//===--- SemaStmtAttr.cpp - Statement Attribute Handling ------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+//  This file implements stmt-related attribute processing.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Sema/SemaInternal.h"
+#include "TargetAttributesSema.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Sema/DelayedDiagnostic.h"
+#include "clang/Sema/Lookup.h"
+#include "llvm/ADT/StringExtras.h"
+using namespace clang;
+using namespace sema;
+
+
+static Attr *ProcessStmtAttribute(Sema &S, Stmt *St, const AttributeList &A) {
+  switch (A.getKind()) {
+  default:
+    // if we're here, then we parsed an attribute, but didn't recognize it as a
+    // statement attribute => it is declaration attribute
+    S.Diag(A.getRange().getBegin(), diag::warn_attribute_invalid_on_stmt) <<
+      A.getName()->getName();
+    return 0;
+  }
+}
+
+StmtResult Sema::ProcessStmtAttributes(Stmt *S, AttributeList *AttrList,
+                                       SourceRange Range) {
+  AttrVec Attrs;
+  for (const AttributeList* l = AttrList; l; l = l->getNext()) {
+    if (Attr *a = ProcessStmtAttribute(*this, S, *l))
+      Attrs.push_back(a);
+  }
+
+  if (Attrs.empty())
+    return S;
+
+  return ActOnAttributedStmt(Range.getBegin(), Attrs, S);
+}
diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp
new file mode 100644
index 0000000..51ce2a1
--- /dev/null
+++ b/clang/lib/Sema/SemaTemplate.cpp
@@ -0,0 +1,7192 @@
+//===------- SemaTemplate.cpp - Semantic Analysis for C++ Templates -------===/
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//===----------------------------------------------------------------------===/
+//
+//  This file implements semantic analysis for C++ templates.
+//===----------------------------------------------------------------------===/
+
+#include "clang/Sema/SemaInternal.h"
+#include "clang/Sema/Lookup.h"
+#include "clang/Sema/Scope.h"
+#include "clang/Sema/Template.h"
+#include "clang/Sema/TemplateDeduction.h"
+#include "TreeTransform.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/ExprCXX.h"
+#include "clang/AST/DeclFriend.h"
+#include "clang/AST/DeclTemplate.h"
+#include "clang/AST/RecursiveASTVisitor.h"
+#include "clang/AST/TypeVisitor.h"
+#include "clang/Sema/DeclSpec.h"
+#include "clang/Sema/ParsedTemplate.h"
+#include "clang/Basic/LangOptions.h"
+#include "clang/Basic/PartialDiagnostic.h"
+#include "llvm/ADT/SmallBitVector.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/StringExtras.h"
+using namespace clang;
+using namespace sema;
+
+// Exported for use by Parser.
+SourceRange
+clang::getTemplateParamsRange(TemplateParameterList const * const *Ps,
+                              unsigned N) {
+  if (!N) return SourceRange();
+  return SourceRange(Ps[0]->getTemplateLoc(), Ps[N-1]->getRAngleLoc());
+}
+
+/// \brief Determine whether the declaration found is acceptable as the name
+/// of a template and, if so, return that template declaration. Otherwise,
+/// returns NULL.
+static NamedDecl *isAcceptableTemplateName(ASTContext &Context,
+                                           NamedDecl *Orig,
+                                           bool AllowFunctionTemplates) {
+  NamedDecl *D = Orig->getUnderlyingDecl();
+
+  if (isa<TemplateDecl>(D)) {
+    if (!AllowFunctionTemplates && isa<FunctionTemplateDecl>(D))
+      return 0;
+    
+    return Orig;
+  }
+
+  if (CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(D)) {
+    // C++ [temp.local]p1:
+    //   Like normal (non-template) classes, class templates have an
+    //   injected-class-name (Clause 9). The injected-class-name
+    //   can be used with or without a template-argument-list. When
+    //   it is used without a template-argument-list, it is
+    //   equivalent to the injected-class-name followed by the
+    //   template-parameters of the class template enclosed in
+    //   <>. When it is used with a template-argument-list, it
+    //   refers to the specified class template specialization,
+    //   which could be the current specialization or another
+    //   specialization.
+    if (Record->isInjectedClassName()) {
+      Record = cast<CXXRecordDecl>(Record->getDeclContext());
+      if (Record->getDescribedClassTemplate())
+        return Record->getDescribedClassTemplate();
+
+      if (ClassTemplateSpecializationDecl *Spec
+            = dyn_cast<ClassTemplateSpecializationDecl>(Record))
+        return Spec->getSpecializedTemplate();
+    }
+
+    return 0;
+  }
+
+  return 0;
+}
+
+void Sema::FilterAcceptableTemplateNames(LookupResult &R, 
+                                         bool AllowFunctionTemplates) {
+  // The set of class templates we've already seen.
+  llvm::SmallPtrSet<ClassTemplateDecl *, 8> ClassTemplates;
+  LookupResult::Filter filter = R.makeFilter();
+  while (filter.hasNext()) {
+    NamedDecl *Orig = filter.next();
+    NamedDecl *Repl = isAcceptableTemplateName(Context, Orig, 
+                                               AllowFunctionTemplates);
+    if (!Repl)
+      filter.erase();
+    else if (Repl != Orig) {
+
+      // C++ [temp.local]p3:
+      //   A lookup that finds an injected-class-name (10.2) can result in an
+      //   ambiguity in certain cases (for example, if it is found in more than
+      //   one base class). If all of the injected-class-names that are found
+      //   refer to specializations of the same class template, and if the name
+      //   is used as a template-name, the reference refers to the class
+      //   template itself and not a specialization thereof, and is not
+      //   ambiguous.
+      if (ClassTemplateDecl *ClassTmpl = dyn_cast<ClassTemplateDecl>(Repl))
+        if (!ClassTemplates.insert(ClassTmpl)) {
+          filter.erase();
+          continue;
+        }
+
+      // FIXME: we promote access to public here as a workaround to
+      // the fact that LookupResult doesn't let us remember that we
+      // found this template through a particular injected class name,
+      // which means we end up doing nasty things to the invariants.
+      // Pretending that access is public is *much* safer.
+      filter.replace(Repl, AS_public);
+    }
+  }
+  filter.done();
+}
+
+bool Sema::hasAnyAcceptableTemplateNames(LookupResult &R,
+                                         bool AllowFunctionTemplates) {
+  for (LookupResult::iterator I = R.begin(), IEnd = R.end(); I != IEnd; ++I)
+    if (isAcceptableTemplateName(Context, *I, AllowFunctionTemplates))
+      return true;
+  
+  return false;
+}
+
+TemplateNameKind Sema::isTemplateName(Scope *S,
+                                      CXXScopeSpec &SS,
+                                      bool hasTemplateKeyword,
+                                      UnqualifiedId &Name,
+                                      ParsedType ObjectTypePtr,
+                                      bool EnteringContext,
+                                      TemplateTy &TemplateResult,
+                                      bool &MemberOfUnknownSpecialization) {
+  assert(getLangOpts().CPlusPlus && "No template names in C!");
+
+  DeclarationName TName;
+  MemberOfUnknownSpecialization = false;
+
+  switch (Name.getKind()) {
+  case UnqualifiedId::IK_Identifier:
+    TName = DeclarationName(Name.Identifier);
+    break;
+
+  case UnqualifiedId::IK_OperatorFunctionId:
+    TName = Context.DeclarationNames.getCXXOperatorName(
+                                              Name.OperatorFunctionId.Operator);
+    break;
+
+  case UnqualifiedId::IK_LiteralOperatorId:
+    TName = Context.DeclarationNames.getCXXLiteralOperatorName(Name.Identifier);
+    break;
+
+  default:
+    return TNK_Non_template;
+  }
+
+  QualType ObjectType = ObjectTypePtr.get();
+
+  LookupResult R(*this, TName, Name.getLocStart(), LookupOrdinaryName);
+  LookupTemplateName(R, S, SS, ObjectType, EnteringContext,
+                     MemberOfUnknownSpecialization);
+  if (R.empty()) return TNK_Non_template;
+  if (R.isAmbiguous()) {
+    // Suppress diagnostics;  we'll redo this lookup later.
+    R.suppressDiagnostics();
+
+    // FIXME: we might have ambiguous templates, in which case we
+    // should at least parse them properly!
+    return TNK_Non_template;
+  }
+
+  TemplateName Template;
+  TemplateNameKind TemplateKind;
+
+  unsigned ResultCount = R.end() - R.begin();
+  if (ResultCount > 1) {
+    // We assume that we'll preserve the qualifier from a function
+    // template name in other ways.
+    Template = Context.getOverloadedTemplateName(R.begin(), R.end());
+    TemplateKind = TNK_Function_template;
+
+    // We'll do this lookup again later.
+    R.suppressDiagnostics();
+  } else {
+    TemplateDecl *TD = cast<TemplateDecl>((*R.begin())->getUnderlyingDecl());
+
+    if (SS.isSet() && !SS.isInvalid()) {
+      NestedNameSpecifier *Qualifier
+        = static_cast<NestedNameSpecifier *>(SS.getScopeRep());
+      Template = Context.getQualifiedTemplateName(Qualifier,
+                                                  hasTemplateKeyword, TD);
+    } else {
+      Template = TemplateName(TD);
+    }
+
+    if (isa<FunctionTemplateDecl>(TD)) {
+      TemplateKind = TNK_Function_template;
+
+      // We'll do this lookup again later.
+      R.suppressDiagnostics();
+    } else {
+      assert(isa<ClassTemplateDecl>(TD) || isa<TemplateTemplateParmDecl>(TD) ||
+             isa<TypeAliasTemplateDecl>(TD));
+      TemplateKind = TNK_Type_template;
+    }
+  }
+
+  TemplateResult = TemplateTy::make(Template);
+  return TemplateKind;
+}
+
+bool Sema::DiagnoseUnknownTemplateName(const IdentifierInfo &II,
+                                       SourceLocation IILoc,
+                                       Scope *S,
+                                       const CXXScopeSpec *SS,
+                                       TemplateTy &SuggestedTemplate,
+                                       TemplateNameKind &SuggestedKind) {
+  // We can't recover unless there's a dependent scope specifier preceding the
+  // template name.
+  // FIXME: Typo correction?
+  if (!SS || !SS->isSet() || !isDependentScopeSpecifier(*SS) ||
+      computeDeclContext(*SS))
+    return false;
+
+  // The code is missing a 'template' keyword prior to the dependent template
+  // name.
+  NestedNameSpecifier *Qualifier = (NestedNameSpecifier*)SS->getScopeRep();
+  Diag(IILoc, diag::err_template_kw_missing)
+    << Qualifier << II.getName()
+    << FixItHint::CreateInsertion(IILoc, "template ");
+  SuggestedTemplate
+    = TemplateTy::make(Context.getDependentTemplateName(Qualifier, &II));
+  SuggestedKind = TNK_Dependent_template_name;
+  return true;
+}
+
+void Sema::LookupTemplateName(LookupResult &Found,
+                              Scope *S, CXXScopeSpec &SS,
+                              QualType ObjectType,
+                              bool EnteringContext,
+                              bool &MemberOfUnknownSpecialization) {
+  // Determine where to perform name lookup
+  MemberOfUnknownSpecialization = false;
+  DeclContext *LookupCtx = 0;
+  bool isDependent = false;
+  if (!ObjectType.isNull()) {
+    // This nested-name-specifier occurs in a member access expression, e.g.,
+    // x->B::f, and we are looking into the type of the object.
+    assert(!SS.isSet() && "ObjectType and scope specifier cannot coexist");
+    LookupCtx = computeDeclContext(ObjectType);
+    isDependent = ObjectType->isDependentType();
+    assert((isDependent || !ObjectType->isIncompleteType()) &&
+           "Caller should have completed object type");
+    
+    // Template names cannot appear inside an Objective-C class or object type.
+    if (ObjectType->isObjCObjectOrInterfaceType()) {
+      Found.clear();
+      return;
+    }
+  } else if (SS.isSet()) {
+    // This nested-name-specifier occurs after another nested-name-specifier,
+    // so long into the context associated with the prior nested-name-specifier.
+    LookupCtx = computeDeclContext(SS, EnteringContext);
+    isDependent = isDependentScopeSpecifier(SS);
+
+    // The declaration context must be complete.
+    if (LookupCtx && RequireCompleteDeclContext(SS, LookupCtx))
+      return;
+  }
+
+  bool ObjectTypeSearchedInScope = false;
+  bool AllowFunctionTemplatesInLookup = true;
+  if (LookupCtx) {
+    // Perform "qualified" name lookup into the declaration context we
+    // computed, which is either the type of the base of a member access
+    // expression or the declaration context associated with a prior
+    // nested-name-specifier.
+    LookupQualifiedName(Found, LookupCtx);
+    if (!ObjectType.isNull() && Found.empty()) {
+      // C++ [basic.lookup.classref]p1:
+      //   In a class member access expression (5.2.5), if the . or -> token is
+      //   immediately followed by an identifier followed by a <, the
+      //   identifier must be looked up to determine whether the < is the
+      //   beginning of a template argument list (14.2) or a less-than operator.
+      //   The identifier is first looked up in the class of the object
+      //   expression. If the identifier is not found, it is then looked up in
+      //   the context of the entire postfix-expression and shall name a class
+      //   or function template.
+      if (S) LookupName(Found, S);
+      ObjectTypeSearchedInScope = true;
+      AllowFunctionTemplatesInLookup = false;
+    }
+  } else if (isDependent && (!S || ObjectType.isNull())) {
+    // We cannot look into a dependent object type or nested nme
+    // specifier.
+    MemberOfUnknownSpecialization = true;
+    return;
+  } else {
+    // Perform unqualified name lookup in the current scope.
+    LookupName(Found, S);
+    
+    if (!ObjectType.isNull())
+      AllowFunctionTemplatesInLookup = false;
+  }
+
+  if (Found.empty() && !isDependent) {
+    // If we did not find any names, attempt to correct any typos.
+    DeclarationName Name = Found.getLookupName();
+    Found.clear();
+    // Simple filter callback that, for keywords, only accepts the C++ *_cast
+    CorrectionCandidateCallback FilterCCC;
+    FilterCCC.WantTypeSpecifiers = false;
+    FilterCCC.WantExpressionKeywords = false;
+    FilterCCC.WantRemainingKeywords = false;
+    FilterCCC.WantCXXNamedCasts = true;
+    if (TypoCorrection Corrected = CorrectTypo(Found.getLookupNameInfo(),
+                                               Found.getLookupKind(), S, &SS,
+                                               FilterCCC, LookupCtx)) {
+      Found.setLookupName(Corrected.getCorrection());
+      if (Corrected.getCorrectionDecl())
+        Found.addDecl(Corrected.getCorrectionDecl());
+      FilterAcceptableTemplateNames(Found);
+      if (!Found.empty()) {
+        std::string CorrectedStr(Corrected.getAsString(getLangOpts()));
+        std::string CorrectedQuotedStr(Corrected.getQuoted(getLangOpts()));
+        if (LookupCtx)
+          Diag(Found.getNameLoc(), diag::err_no_member_template_suggest)
+            << Name << LookupCtx << CorrectedQuotedStr << SS.getRange()
+            << FixItHint::CreateReplacement(Found.getNameLoc(), CorrectedStr);
+        else
+          Diag(Found.getNameLoc(), diag::err_no_template_suggest)
+            << Name << CorrectedQuotedStr
+            << FixItHint::CreateReplacement(Found.getNameLoc(), CorrectedStr);
+        if (TemplateDecl *Template = Found.getAsSingle<TemplateDecl>())
+          Diag(Template->getLocation(), diag::note_previous_decl)
+            << CorrectedQuotedStr;
+      }
+    } else {
+      Found.setLookupName(Name);
+    }
+  }
+
+  FilterAcceptableTemplateNames(Found, AllowFunctionTemplatesInLookup);
+  if (Found.empty()) {
+    if (isDependent)
+      MemberOfUnknownSpecialization = true;
+    return;
+  }
+
+  if (S && !ObjectType.isNull() && !ObjectTypeSearchedInScope) {
+    // C++ [basic.lookup.classref]p1:
+    //   [...] If the lookup in the class of the object expression finds a
+    //   template, the name is also looked up in the context of the entire
+    //   postfix-expression and [...]
+    //
+    LookupResult FoundOuter(*this, Found.getLookupName(), Found.getNameLoc(),
+                            LookupOrdinaryName);
+    LookupName(FoundOuter, S);
+    FilterAcceptableTemplateNames(FoundOuter, /*AllowFunctionTemplates=*/false);
+
+    if (FoundOuter.empty()) {
+      //   - if the name is not found, the name found in the class of the
+      //     object expression is used, otherwise
+    } else if (!FoundOuter.getAsSingle<ClassTemplateDecl>() ||
+               FoundOuter.isAmbiguous()) {
+      //   - if the name is found in the context of the entire
+      //     postfix-expression and does not name a class template, the name
+      //     found in the class of the object expression is used, otherwise
+      FoundOuter.clear();
+    } else if (!Found.isSuppressingDiagnostics()) {
+      //   - if the name found is a class template, it must refer to the same
+      //     entity as the one found in the class of the object expression,
+      //     otherwise the program is ill-formed.
+      if (!Found.isSingleResult() ||
+          Found.getFoundDecl()->getCanonicalDecl()
+            != FoundOuter.getFoundDecl()->getCanonicalDecl()) {
+        Diag(Found.getNameLoc(),
+             diag::ext_nested_name_member_ref_lookup_ambiguous)
+          << Found.getLookupName()
+          << ObjectType;
+        Diag(Found.getRepresentativeDecl()->getLocation(),
+             diag::note_ambig_member_ref_object_type)
+          << ObjectType;
+        Diag(FoundOuter.getFoundDecl()->getLocation(),
+             diag::note_ambig_member_ref_scope);
+
+        // Recover by taking the template that we found in the object
+        // expression's type.
+      }
+    }
+  }
+}
+
+/// ActOnDependentIdExpression - Handle a dependent id-expression that
+/// was just parsed.  This is only possible with an explicit scope
+/// specifier naming a dependent type.
+ExprResult
+Sema::ActOnDependentIdExpression(const CXXScopeSpec &SS,
+                                 SourceLocation TemplateKWLoc,
+                                 const DeclarationNameInfo &NameInfo,
+                                 bool isAddressOfOperand,
+                           const TemplateArgumentListInfo *TemplateArgs) {
+  DeclContext *DC = getFunctionLevelDeclContext();
+
+  if (!isAddressOfOperand &&
+      isa<CXXMethodDecl>(DC) &&
+      cast<CXXMethodDecl>(DC)->isInstance()) {
+    QualType ThisType = cast<CXXMethodDecl>(DC)->getThisType(Context);
+
+    // Since the 'this' expression is synthesized, we don't need to
+    // perform the double-lookup check.
+    NamedDecl *FirstQualifierInScope = 0;
+
+    return Owned(CXXDependentScopeMemberExpr::Create(Context,
+                                                     /*This*/ 0, ThisType,
+                                                     /*IsArrow*/ true,
+                                                     /*Op*/ SourceLocation(),
+                                               SS.getWithLocInContext(Context),
+                                                     TemplateKWLoc,
+                                                     FirstQualifierInScope,
+                                                     NameInfo,
+                                                     TemplateArgs));
+  }
+
+  return BuildDependentDeclRefExpr(SS, TemplateKWLoc, NameInfo, TemplateArgs);
+}
+
+ExprResult
+Sema::BuildDependentDeclRefExpr(const CXXScopeSpec &SS,
+                                SourceLocation TemplateKWLoc,
+                                const DeclarationNameInfo &NameInfo,
+                                const TemplateArgumentListInfo *TemplateArgs) {
+  return Owned(DependentScopeDeclRefExpr::Create(Context,
+                                               SS.getWithLocInContext(Context),
+                                                 TemplateKWLoc,
+                                                 NameInfo,
+                                                 TemplateArgs));
+}
+
+/// DiagnoseTemplateParameterShadow - Produce a diagnostic complaining
+/// that the template parameter 'PrevDecl' is being shadowed by a new
+/// declaration at location Loc. Returns true to indicate that this is
+/// an error, and false otherwise.
+void Sema::DiagnoseTemplateParameterShadow(SourceLocation Loc, Decl *PrevDecl) {
+  assert(PrevDecl->isTemplateParameter() && "Not a template parameter");
+
+  // Microsoft Visual C++ permits template parameters to be shadowed.
+  if (getLangOpts().MicrosoftExt)
+    return;
+
+  // C++ [temp.local]p4:
+  //   A template-parameter shall not be redeclared within its
+  //   scope (including nested scopes).
+  Diag(Loc, diag::err_template_param_shadow)
+    << cast<NamedDecl>(PrevDecl)->getDeclName();
+  Diag(PrevDecl->getLocation(), diag::note_template_param_here);
+  return;
+}
+
+/// AdjustDeclIfTemplate - If the given decl happens to be a template, reset
+/// the parameter D to reference the templated declaration and return a pointer
+/// to the template declaration. Otherwise, do nothing to D and return null.
+TemplateDecl *Sema::AdjustDeclIfTemplate(Decl *&D) {
+  if (TemplateDecl *Temp = dyn_cast_or_null<TemplateDecl>(D)) {
+    D = Temp->getTemplatedDecl();
+    return Temp;
+  }
+  return 0;
+}
+
+ParsedTemplateArgument ParsedTemplateArgument::getTemplatePackExpansion(
+                                             SourceLocation EllipsisLoc) const {
+  assert(Kind == Template &&
+         "Only template template arguments can be pack expansions here");
+  assert(getAsTemplate().get().containsUnexpandedParameterPack() &&
+         "Template template argument pack expansion without packs");
+  ParsedTemplateArgument Result(*this);
+  Result.EllipsisLoc = EllipsisLoc;
+  return Result;
+}
+
+static TemplateArgumentLoc translateTemplateArgument(Sema &SemaRef,
+                                            const ParsedTemplateArgument &Arg) {
+
+  switch (Arg.getKind()) {
+  case ParsedTemplateArgument::Type: {
+    TypeSourceInfo *DI;
+    QualType T = SemaRef.GetTypeFromParser(Arg.getAsType(), &DI);
+    if (!DI)
+      DI = SemaRef.Context.getTrivialTypeSourceInfo(T, Arg.getLocation());
+    return TemplateArgumentLoc(TemplateArgument(T), DI);
+  }
+
+  case ParsedTemplateArgument::NonType: {
+    Expr *E = static_cast<Expr *>(Arg.getAsExpr());
+    return TemplateArgumentLoc(TemplateArgument(E), E);
+  }
+
+  case ParsedTemplateArgument::Template: {
+    TemplateName Template = Arg.getAsTemplate().get();
+    TemplateArgument TArg;
+    if (Arg.getEllipsisLoc().isValid())
+      TArg = TemplateArgument(Template, llvm::Optional<unsigned int>());
+    else
+      TArg = Template;
+    return TemplateArgumentLoc(TArg,
+                               Arg.getScopeSpec().getWithLocInContext(
+                                                              SemaRef.Context),
+                               Arg.getLocation(),
+                               Arg.getEllipsisLoc());
+  }
+  }
+
+  llvm_unreachable("Unhandled parsed template argument");
+}
+
+/// \brief Translates template arguments as provided by the parser
+/// into template arguments used by semantic analysis.
+void Sema::translateTemplateArguments(const ASTTemplateArgsPtr &TemplateArgsIn,
+                                      TemplateArgumentListInfo &TemplateArgs) {
+ for (unsigned I = 0, Last = TemplateArgsIn.size(); I != Last; ++I)
+   TemplateArgs.addArgument(translateTemplateArgument(*this,
+                                                      TemplateArgsIn[I]));
+}
+
+/// ActOnTypeParameter - Called when a C++ template type parameter
+/// (e.g., "typename T") has been parsed. Typename specifies whether
+/// the keyword "typename" was used to declare the type parameter
+/// (otherwise, "class" was used), and KeyLoc is the location of the
+/// "class" or "typename" keyword. ParamName is the name of the
+/// parameter (NULL indicates an unnamed template parameter) and
+/// ParamNameLoc is the location of the parameter name (if any).
+/// If the type parameter has a default argument, it will be added
+/// later via ActOnTypeParameterDefault.
+Decl *Sema::ActOnTypeParameter(Scope *S, bool Typename, bool Ellipsis,
+                               SourceLocation EllipsisLoc,
+                               SourceLocation KeyLoc,
+                               IdentifierInfo *ParamName,
+                               SourceLocation ParamNameLoc,
+                               unsigned Depth, unsigned Position,
+                               SourceLocation EqualLoc,
+                               ParsedType DefaultArg) {
+  assert(S->isTemplateParamScope() &&
+         "Template type parameter not in template parameter scope!");
+  bool Invalid = false;
+
+  if (ParamName) {
+    NamedDecl *PrevDecl = LookupSingleName(S, ParamName, ParamNameLoc,
+                                           LookupOrdinaryName,
+                                           ForRedeclaration);
+    if (PrevDecl && PrevDecl->isTemplateParameter()) {
+      DiagnoseTemplateParameterShadow(ParamNameLoc, PrevDecl);
+      PrevDecl = 0;
+    }
+  }
+
+  SourceLocation Loc = ParamNameLoc;
+  if (!ParamName)
+    Loc = KeyLoc;
+
+  TemplateTypeParmDecl *Param
+    = TemplateTypeParmDecl::Create(Context, Context.getTranslationUnitDecl(),
+                                   KeyLoc, Loc, Depth, Position, ParamName,
+                                   Typename, Ellipsis);
+  Param->setAccess(AS_public);
+  if (Invalid)
+    Param->setInvalidDecl();
+
+  if (ParamName) {
+    // Add the template parameter into the current scope.
+    S->AddDecl(Param);
+    IdResolver.AddDecl(Param);
+  }
+
+  // C++0x [temp.param]p9:
+  //   A default template-argument may be specified for any kind of
+  //   template-parameter that is not a template parameter pack.
+  if (DefaultArg && Ellipsis) {
+    Diag(EqualLoc, diag::err_template_param_pack_default_arg);
+    DefaultArg = ParsedType();
+  }
+
+  // Handle the default argument, if provided.
+  if (DefaultArg) {
+    TypeSourceInfo *DefaultTInfo;
+    GetTypeFromParser(DefaultArg, &DefaultTInfo);
+
+    assert(DefaultTInfo && "expected source information for type");
+
+    // Check for unexpanded parameter packs.
+    if (DiagnoseUnexpandedParameterPack(Loc, DefaultTInfo,
+                                        UPPC_DefaultArgument))
+      return Param;
+
+    // Check the template argument itself.
+    if (CheckTemplateArgument(Param, DefaultTInfo)) {
+      Param->setInvalidDecl();
+      return Param;
+    }
+
+    Param->setDefaultArgument(DefaultTInfo, false);
+  }
+
+  return Param;
+}
+
+/// \brief Check that the type of a non-type template parameter is
+/// well-formed.
+///
+/// \returns the (possibly-promoted) parameter type if valid;
+/// otherwise, produces a diagnostic and returns a NULL type.
+QualType
+Sema::CheckNonTypeTemplateParameterType(QualType T, SourceLocation Loc) {
+  // We don't allow variably-modified types as the type of non-type template
+  // parameters.
+  if (T->isVariablyModifiedType()) {
+    Diag(Loc, diag::err_variably_modified_nontype_template_param)
+      << T;
+    return QualType();
+  }
+
+  // C++ [temp.param]p4:
+  //
+  // A non-type template-parameter shall have one of the following
+  // (optionally cv-qualified) types:
+  //
+  //       -- integral or enumeration type,
+  if (T->isIntegralOrEnumerationType() ||
+      //   -- pointer to object or pointer to function,
+      T->isPointerType() ||
+      //   -- reference to object or reference to function,
+      T->isReferenceType() ||
+      //   -- pointer to member,
+      T->isMemberPointerType() ||
+      //   -- std::nullptr_t.
+      T->isNullPtrType() ||
+      // If T is a dependent type, we can't do the check now, so we
+      // assume that it is well-formed.
+      T->isDependentType()) {
+    // C++ [temp.param]p5: The top-level cv-qualifiers on the template-parameter
+    // are ignored when determining its type.
+    return T.getUnqualifiedType();
+  }
+
+  // C++ [temp.param]p8:
+  //
+  //   A non-type template-parameter of type "array of T" or
+  //   "function returning T" is adjusted to be of type "pointer to
+  //   T" or "pointer to function returning T", respectively.
+  else if (T->isArrayType())
+    // FIXME: Keep the type prior to promotion?
+    return Context.getArrayDecayedType(T);
+  else if (T->isFunctionType())
+    // FIXME: Keep the type prior to promotion?
+    return Context.getPointerType(T);
+
+  Diag(Loc, diag::err_template_nontype_parm_bad_type)
+    << T;
+
+  return QualType();
+}
+
+Decl *Sema::ActOnNonTypeTemplateParameter(Scope *S, Declarator &D,
+                                          unsigned Depth,
+                                          unsigned Position,
+                                          SourceLocation EqualLoc,
+                                          Expr *Default) {
+  TypeSourceInfo *TInfo = GetTypeForDeclarator(D, S);
+  QualType T = TInfo->getType();
+
+  assert(S->isTemplateParamScope() &&
+         "Non-type template parameter not in template parameter scope!");
+  bool Invalid = false;
+
+  IdentifierInfo *ParamName = D.getIdentifier();
+  if (ParamName) {
+    NamedDecl *PrevDecl = LookupSingleName(S, ParamName, D.getIdentifierLoc(),
+                                           LookupOrdinaryName,
+                                           ForRedeclaration);
+    if (PrevDecl && PrevDecl->isTemplateParameter()) {
+      DiagnoseTemplateParameterShadow(D.getIdentifierLoc(), PrevDecl);
+      PrevDecl = 0;
+    }
+  }
+
+  T = CheckNonTypeTemplateParameterType(T, D.getIdentifierLoc());
+  if (T.isNull()) {
+    T = Context.IntTy; // Recover with an 'int' type.
+    Invalid = true;
+  }
+
+  bool IsParameterPack = D.hasEllipsis();
+  NonTypeTemplateParmDecl *Param
+    = NonTypeTemplateParmDecl::Create(Context, Context.getTranslationUnitDecl(),
+                                      D.getLocStart(),
+                                      D.getIdentifierLoc(),
+                                      Depth, Position, ParamName, T,
+                                      IsParameterPack, TInfo);
+  Param->setAccess(AS_public);
+  
+  if (Invalid)
+    Param->setInvalidDecl();
+
+  if (D.getIdentifier()) {
+    // Add the template parameter into the current scope.
+    S->AddDecl(Param);
+    IdResolver.AddDecl(Param);
+  }
+
+  // C++0x [temp.param]p9:
+  //   A default template-argument may be specified for any kind of
+  //   template-parameter that is not a template parameter pack.
+  if (Default && IsParameterPack) {
+    Diag(EqualLoc, diag::err_template_param_pack_default_arg);
+    Default = 0;
+  }
+
+  // Check the well-formedness of the default template argument, if provided.
+  if (Default) {
+    // Check for unexpanded parameter packs.
+    if (DiagnoseUnexpandedParameterPack(Default, UPPC_DefaultArgument))
+      return Param;
+
+    TemplateArgument Converted;
+    ExprResult DefaultRes = CheckTemplateArgument(Param, Param->getType(), Default, Converted);
+    if (DefaultRes.isInvalid()) {
+      Param->setInvalidDecl();
+      return Param;
+    }
+    Default = DefaultRes.take();
+
+    Param->setDefaultArgument(Default, false);
+  }
+
+  return Param;
+}
+
+/// ActOnTemplateTemplateParameter - Called when a C++ template template
+/// parameter (e.g. T in template <template <typename> class T> class array)
+/// has been parsed. S is the current scope.
+Decl *Sema::ActOnTemplateTemplateParameter(Scope* S,
+                                           SourceLocation TmpLoc,
+                                           TemplateParameterList *Params,
+                                           SourceLocation EllipsisLoc,
+                                           IdentifierInfo *Name,
+                                           SourceLocation NameLoc,
+                                           unsigned Depth,
+                                           unsigned Position,
+                                           SourceLocation EqualLoc,
+                                           ParsedTemplateArgument Default) {
+  assert(S->isTemplateParamScope() &&
+         "Template template parameter not in template parameter scope!");
+
+  // Construct the parameter object.
+  bool IsParameterPack = EllipsisLoc.isValid();
+  TemplateTemplateParmDecl *Param =
+    TemplateTemplateParmDecl::Create(Context, Context.getTranslationUnitDecl(),
+                                     NameLoc.isInvalid()? TmpLoc : NameLoc,
+                                     Depth, Position, IsParameterPack,
+                                     Name, Params);
+  Param->setAccess(AS_public);
+  
+  // If the template template parameter has a name, then link the identifier
+  // into the scope and lookup mechanisms.
+  if (Name) {
+    S->AddDecl(Param);
+    IdResolver.AddDecl(Param);
+  }
+
+  if (Params->size() == 0) {
+    Diag(Param->getLocation(), diag::err_template_template_parm_no_parms)
+    << SourceRange(Params->getLAngleLoc(), Params->getRAngleLoc());
+    Param->setInvalidDecl();
+  }
+
+  // C++0x [temp.param]p9:
+  //   A default template-argument may be specified for any kind of
+  //   template-parameter that is not a template parameter pack.
+  if (IsParameterPack && !Default.isInvalid()) {
+    Diag(EqualLoc, diag::err_template_param_pack_default_arg);
+    Default = ParsedTemplateArgument();
+  }
+
+  if (!Default.isInvalid()) {
+    // Check only that we have a template template argument. We don't want to
+    // try to check well-formedness now, because our template template parameter
+    // might have dependent types in its template parameters, which we wouldn't
+    // be able to match now.
+    //
+    // If none of the template template parameter's template arguments mention
+    // other template parameters, we could actually perform more checking here.
+    // However, it isn't worth doing.
+    TemplateArgumentLoc DefaultArg = translateTemplateArgument(*this, Default);
+    if (DefaultArg.getArgument().getAsTemplate().isNull()) {
+      Diag(DefaultArg.getLocation(), diag::err_template_arg_not_class_template)
+        << DefaultArg.getSourceRange();
+      return Param;
+    }
+
+    // Check for unexpanded parameter packs.
+    if (DiagnoseUnexpandedParameterPack(DefaultArg.getLocation(),
+                                        DefaultArg.getArgument().getAsTemplate(),
+                                        UPPC_DefaultArgument))
+      return Param;
+
+    Param->setDefaultArgument(DefaultArg, false);
+  }
+
+  return Param;
+}
+
+/// ActOnTemplateParameterList - Builds a TemplateParameterList that
+/// contains the template parameters in Params/NumParams.
+TemplateParameterList *
+Sema::ActOnTemplateParameterList(unsigned Depth,
+                                 SourceLocation ExportLoc,
+                                 SourceLocation TemplateLoc,
+                                 SourceLocation LAngleLoc,
+                                 Decl **Params, unsigned NumParams,
+                                 SourceLocation RAngleLoc) {
+  if (ExportLoc.isValid())
+    Diag(ExportLoc, diag::warn_template_export_unsupported);
+
+  return TemplateParameterList::Create(Context, TemplateLoc, LAngleLoc,
+                                       (NamedDecl**)Params, NumParams,
+                                       RAngleLoc);
+}
+
+static void SetNestedNameSpecifier(TagDecl *T, const CXXScopeSpec &SS) {
+  if (SS.isSet())
+    T->setQualifierInfo(SS.getWithLocInContext(T->getASTContext()));
+}
+
+DeclResult
+Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK,
+                         SourceLocation KWLoc, CXXScopeSpec &SS,
+                         IdentifierInfo *Name, SourceLocation NameLoc,
+                         AttributeList *Attr,
+                         TemplateParameterList *TemplateParams,
+                         AccessSpecifier AS, SourceLocation ModulePrivateLoc,
+                         unsigned NumOuterTemplateParamLists,
+                         TemplateParameterList** OuterTemplateParamLists) {
+  assert(TemplateParams && TemplateParams->size() > 0 &&
+         "No template parameters");
+  assert(TUK != TUK_Reference && "Can only declare or define class templates");
+  bool Invalid = false;
+
+  // Check that we can declare a template here.
+  if (CheckTemplateDeclScope(S, TemplateParams))
+    return true;
+
+  TagTypeKind Kind = TypeWithKeyword::getTagTypeKindForTypeSpec(TagSpec);
+  assert(Kind != TTK_Enum && "can't build template of enumerated type");
+
+  // There is no such thing as an unnamed class template.
+  if (!Name) {
+    Diag(KWLoc, diag::err_template_unnamed_class);
+    return true;
+  }
+
+  // Find any previous declaration with this name.
+  DeclContext *SemanticContext;
+  LookupResult Previous(*this, Name, NameLoc, LookupOrdinaryName,
+                        ForRedeclaration);
+  if (SS.isNotEmpty() && !SS.isInvalid()) {
+    SemanticContext = computeDeclContext(SS, true);
+    if (!SemanticContext) {
+      // FIXME: Horrible, horrible hack! We can't currently represent this
+      // in the AST, and historically we have just ignored such friend
+      // class templates, so don't complain here.
+      if (TUK != TUK_Friend)
+        Diag(NameLoc, diag::err_template_qualified_declarator_no_match)
+          << SS.getScopeRep() << SS.getRange();
+      return true;
+    }
+
+    if (RequireCompleteDeclContext(SS, SemanticContext))
+      return true;
+
+    // If we're adding a template to a dependent context, we may need to 
+    // rebuilding some of the types used within the template parameter list, 
+    // now that we know what the current instantiation is.
+    if (SemanticContext->isDependentContext()) {
+      ContextRAII SavedContext(*this, SemanticContext);
+      if (RebuildTemplateParamsInCurrentInstantiation(TemplateParams))
+        Invalid = true;
+    } else if (TUK != TUK_Friend && TUK != TUK_Reference)
+      diagnoseQualifiedDeclaration(SS, SemanticContext, Name, NameLoc);
+        
+    LookupQualifiedName(Previous, SemanticContext);
+  } else {
+    SemanticContext = CurContext;
+    LookupName(Previous, S);
+  }
+
+  if (Previous.isAmbiguous())
+    return true;
+
+  NamedDecl *PrevDecl = 0;
+  if (Previous.begin() != Previous.end())
+    PrevDecl = (*Previous.begin())->getUnderlyingDecl();
+
+  // If there is a previous declaration with the same name, check
+  // whether this is a valid redeclaration.
+  ClassTemplateDecl *PrevClassTemplate
+    = dyn_cast_or_null<ClassTemplateDecl>(PrevDecl);
+
+  // We may have found the injected-class-name of a class template,
+  // class template partial specialization, or class template specialization.
+  // In these cases, grab the template that is being defined or specialized.
+  if (!PrevClassTemplate && PrevDecl && isa<CXXRecordDecl>(PrevDecl) &&
+      cast<CXXRecordDecl>(PrevDecl)->isInjectedClassName()) {
+    PrevDecl = cast<CXXRecordDecl>(PrevDecl->getDeclContext());
+    PrevClassTemplate
+      = cast<CXXRecordDecl>(PrevDecl)->getDescribedClassTemplate();
+    if (!PrevClassTemplate && isa<ClassTemplateSpecializationDecl>(PrevDecl)) {
+      PrevClassTemplate
+        = cast<ClassTemplateSpecializationDecl>(PrevDecl)
+            ->getSpecializedTemplate();
+    }
+  }
+
+  if (TUK == TUK_Friend) {
+    // C++ [namespace.memdef]p3:
+    //   [...] When looking for a prior declaration of a class or a function
+    //   declared as a friend, and when the name of the friend class or
+    //   function is neither a qualified name nor a template-id, scopes outside
+    //   the innermost enclosing namespace scope are not considered.
+    if (!SS.isSet()) {
+      DeclContext *OutermostContext = CurContext;
+      while (!OutermostContext->isFileContext())
+        OutermostContext = OutermostContext->getLookupParent();
+
+      if (PrevDecl &&
+          (OutermostContext->Equals(PrevDecl->getDeclContext()) ||
+           OutermostContext->Encloses(PrevDecl->getDeclContext()))) {
+        SemanticContext = PrevDecl->getDeclContext();
+      } else {
+        // Declarations in outer scopes don't matter. However, the outermost
+        // context we computed is the semantic context for our new
+        // declaration.
+        PrevDecl = PrevClassTemplate = 0;
+        SemanticContext = OutermostContext;
+      }
+    }
+
+    if (CurContext->isDependentContext()) {
+      // If this is a dependent context, we don't want to link the friend
+      // class template to the template in scope, because that would perform
+      // checking of the template parameter lists that can't be performed
+      // until the outer context is instantiated.
+      PrevDecl = PrevClassTemplate = 0;
+    }
+  } else if (PrevDecl && !isDeclInScope(PrevDecl, SemanticContext, S))
+    PrevDecl = PrevClassTemplate = 0;
+
+  if (PrevClassTemplate) {
+    // Ensure that the template parameter lists are compatible.
+    if (!TemplateParameterListsAreEqual(TemplateParams,
+                                   PrevClassTemplate->getTemplateParameters(),
+                                        /*Complain=*/true,
+                                        TPL_TemplateMatch))
+      return true;
+
+    // C++ [temp.class]p4:
+    //   In a redeclaration, partial specialization, explicit
+    //   specialization or explicit instantiation of a class template,
+    //   the class-key shall agree in kind with the original class
+    //   template declaration (7.1.5.3).
+    RecordDecl *PrevRecordDecl = PrevClassTemplate->getTemplatedDecl();
+    if (!isAcceptableTagRedeclaration(PrevRecordDecl, Kind,
+                                      TUK == TUK_Definition,  KWLoc, *Name)) {
+      Diag(KWLoc, diag::err_use_with_wrong_tag)
+        << Name
+        << FixItHint::CreateReplacement(KWLoc, PrevRecordDecl->getKindName());
+      Diag(PrevRecordDecl->getLocation(), diag::note_previous_use);
+      Kind = PrevRecordDecl->getTagKind();
+    }
+
+    // Check for redefinition of this class template.
+    if (TUK == TUK_Definition) {
+      if (TagDecl *Def = PrevRecordDecl->getDefinition()) {
+        Diag(NameLoc, diag::err_redefinition) << Name;
+        Diag(Def->getLocation(), diag::note_previous_definition);
+        // FIXME: Would it make sense to try to "forget" the previous
+        // definition, as part of error recovery?
+        return true;
+      }
+    }    
+  } else if (PrevDecl && PrevDecl->isTemplateParameter()) {
+    // Maybe we will complain about the shadowed template parameter.
+    DiagnoseTemplateParameterShadow(NameLoc, PrevDecl);
+    // Just pretend that we didn't see the previous declaration.
+    PrevDecl = 0;
+  } else if (PrevDecl) {
+    // C++ [temp]p5:
+    //   A class template shall not have the same name as any other
+    //   template, class, function, object, enumeration, enumerator,
+    //   namespace, or type in the same scope (3.3), except as specified
+    //   in (14.5.4).
+    Diag(NameLoc, diag::err_redefinition_different_kind) << Name;
+    Diag(PrevDecl->getLocation(), diag::note_previous_definition);
+    return true;
+  }
+
+  // Check the template parameter list of this declaration, possibly
+  // merging in the template parameter list from the previous class
+  // template declaration.
+  if (CheckTemplateParameterList(TemplateParams,
+            PrevClassTemplate? PrevClassTemplate->getTemplateParameters() : 0,
+                                 (SS.isSet() && SemanticContext &&
+                                  SemanticContext->isRecord() &&
+                                  SemanticContext->isDependentContext())
+                                   ? TPC_ClassTemplateMember
+                                   : TPC_ClassTemplate))
+    Invalid = true;
+
+  if (SS.isSet()) {
+    // If the name of the template was qualified, we must be defining the
+    // template out-of-line.
+    if (!SS.isInvalid() && !Invalid && !PrevClassTemplate &&
+        !(TUK == TUK_Friend && CurContext->isDependentContext())) {
+      Diag(NameLoc, diag::err_member_def_does_not_match)
+        << Name << SemanticContext << SS.getRange();
+      Invalid = true;
+    }
+  }
+
+  CXXRecordDecl *NewClass =
+    CXXRecordDecl::Create(Context, Kind, SemanticContext, KWLoc, NameLoc, Name,
+                          PrevClassTemplate?
+                            PrevClassTemplate->getTemplatedDecl() : 0,
+                          /*DelayTypeCreation=*/true);
+  SetNestedNameSpecifier(NewClass, SS);
+  if (NumOuterTemplateParamLists > 0)
+    NewClass->setTemplateParameterListsInfo(Context,
+                                            NumOuterTemplateParamLists,
+                                            OuterTemplateParamLists);
+
+  // Add alignment attributes if necessary; these attributes are checked when
+  // the ASTContext lays out the structure.
+  AddAlignmentAttributesForRecord(NewClass);
+  AddMsStructLayoutForRecord(NewClass);
+
+  ClassTemplateDecl *NewTemplate
+    = ClassTemplateDecl::Create(Context, SemanticContext, NameLoc,
+                                DeclarationName(Name), TemplateParams,
+                                NewClass, PrevClassTemplate);
+  NewClass->setDescribedClassTemplate(NewTemplate);
+  
+  if (ModulePrivateLoc.isValid())
+    NewTemplate->setModulePrivate();
+  
+  // Build the type for the class template declaration now.
+  QualType T = NewTemplate->getInjectedClassNameSpecialization();
+  T = Context.getInjectedClassNameType(NewClass, T);
+  assert(T->isDependentType() && "Class template type is not dependent?");
+  (void)T;
+
+  // If we are providing an explicit specialization of a member that is a
+  // class template, make a note of that.
+  if (PrevClassTemplate &&
+      PrevClassTemplate->getInstantiatedFromMemberTemplate())
+    PrevClassTemplate->setMemberSpecialization();
+
+  // Set the access specifier.
+  if (!Invalid && TUK != TUK_Friend && NewTemplate->getDeclContext()->isRecord())
+    SetMemberAccessSpecifier(NewTemplate, PrevClassTemplate, AS);
+
+  // Set the lexical context of these templates
+  NewClass->setLexicalDeclContext(CurContext);
+  NewTemplate->setLexicalDeclContext(CurContext);
+
+  if (TUK == TUK_Definition)
+    NewClass->startDefinition();
+
+  if (Attr)
+    ProcessDeclAttributeList(S, NewClass, Attr);
+
+  if (TUK != TUK_Friend)
+    PushOnScopeChains(NewTemplate, S);
+  else {
+    if (PrevClassTemplate && PrevClassTemplate->getAccess() != AS_none) {
+      NewTemplate->setAccess(PrevClassTemplate->getAccess());
+      NewClass->setAccess(PrevClassTemplate->getAccess());
+    }
+
+    NewTemplate->setObjectOfFriendDecl(/* PreviouslyDeclared = */
+                                       PrevClassTemplate != NULL);
+
+    // Friend templates are visible in fairly strange ways.
+    if (!CurContext->isDependentContext()) {
+      DeclContext *DC = SemanticContext->getRedeclContext();
+      DC->makeDeclVisibleInContext(NewTemplate);
+      if (Scope *EnclosingScope = getScopeForDeclContext(S, DC))
+        PushOnScopeChains(NewTemplate, EnclosingScope,
+                          /* AddToContext = */ false);
+    }
+
+    FriendDecl *Friend = FriendDecl::Create(Context, CurContext,
+                                            NewClass->getLocation(),
+                                            NewTemplate,
+                                    /*FIXME:*/NewClass->getLocation());
+    Friend->setAccess(AS_public);
+    CurContext->addDecl(Friend);
+  }
+
+  if (Invalid) {
+    NewTemplate->setInvalidDecl();
+    NewClass->setInvalidDecl();
+  }
+  return NewTemplate;
+}
+
+/// \brief Diagnose the presence of a default template argument on a
+/// template parameter, which is ill-formed in certain contexts.
+///
+/// \returns true if the default template argument should be dropped.
+static bool DiagnoseDefaultTemplateArgument(Sema &S,
+                                            Sema::TemplateParamListContext TPC,
+                                            SourceLocation ParamLoc,
+                                            SourceRange DefArgRange) {
+  switch (TPC) {
+  case Sema::TPC_ClassTemplate:
+  case Sema::TPC_TypeAliasTemplate:
+    return false;
+
+  case Sema::TPC_FunctionTemplate:
+  case Sema::TPC_FriendFunctionTemplateDefinition:
+    // C++ [temp.param]p9:
+    //   A default template-argument shall not be specified in a
+    //   function template declaration or a function template
+    //   definition [...]
+    //   If a friend function template declaration specifies a default 
+    //   template-argument, that declaration shall be a definition and shall be
+    //   the only declaration of the function template in the translation unit.
+    // (C++98/03 doesn't have this wording; see DR226).
+    S.Diag(ParamLoc, S.getLangOpts().CPlusPlus0x ?
+         diag::warn_cxx98_compat_template_parameter_default_in_function_template
+           : diag::ext_template_parameter_default_in_function_template)
+      << DefArgRange;
+    return false;
+
+  case Sema::TPC_ClassTemplateMember:
+    // C++0x [temp.param]p9:
+    //   A default template-argument shall not be specified in the
+    //   template-parameter-lists of the definition of a member of a
+    //   class template that appears outside of the member's class.
+    S.Diag(ParamLoc, diag::err_template_parameter_default_template_member)
+      << DefArgRange;
+    return true;
+
+  case Sema::TPC_FriendFunctionTemplate:
+    // C++ [temp.param]p9:
+    //   A default template-argument shall not be specified in a
+    //   friend template declaration.
+    S.Diag(ParamLoc, diag::err_template_parameter_default_friend_template)
+      << DefArgRange;
+    return true;
+
+    // FIXME: C++0x [temp.param]p9 allows default template-arguments
+    // for friend function templates if there is only a single
+    // declaration (and it is a definition). Strange!
+  }
+
+  llvm_unreachable("Invalid TemplateParamListContext!");
+}
+
+/// \brief Check for unexpanded parameter packs within the template parameters
+/// of a template template parameter, recursively.
+static bool DiagnoseUnexpandedParameterPacks(Sema &S,
+                                             TemplateTemplateParmDecl *TTP) {
+  TemplateParameterList *Params = TTP->getTemplateParameters();
+  for (unsigned I = 0, N = Params->size(); I != N; ++I) {
+    NamedDecl *P = Params->getParam(I);
+    if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(P)) {
+      if (S.DiagnoseUnexpandedParameterPack(NTTP->getLocation(),
+                                            NTTP->getTypeSourceInfo(),
+                                      Sema::UPPC_NonTypeTemplateParameterType))
+        return true;
+
+      continue;
+    }
+
+    if (TemplateTemplateParmDecl *InnerTTP
+                                        = dyn_cast<TemplateTemplateParmDecl>(P))
+      if (DiagnoseUnexpandedParameterPacks(S, InnerTTP))
+        return true;
+  }
+
+  return false;
+}
+
+/// \brief Checks the validity of a template parameter list, possibly
+/// considering the template parameter list from a previous
+/// declaration.
+///
+/// If an "old" template parameter list is provided, it must be
+/// equivalent (per TemplateParameterListsAreEqual) to the "new"
+/// template parameter list.
+///
+/// \param NewParams Template parameter list for a new template
+/// declaration. This template parameter list will be updated with any
+/// default arguments that are carried through from the previous
+/// template parameter list.
+///
+/// \param OldParams If provided, template parameter list from a
+/// previous declaration of the same template. Default template
+/// arguments will be merged from the old template parameter list to
+/// the new template parameter list.
+///
+/// \param TPC Describes the context in which we are checking the given
+/// template parameter list.
+///
+/// \returns true if an error occurred, false otherwise.
+bool Sema::CheckTemplateParameterList(TemplateParameterList *NewParams,
+                                      TemplateParameterList *OldParams,
+                                      TemplateParamListContext TPC) {
+  bool Invalid = false;
+
+  // C++ [temp.param]p10:
+  //   The set of default template-arguments available for use with a
+  //   template declaration or definition is obtained by merging the
+  //   default arguments from the definition (if in scope) and all
+  //   declarations in scope in the same way default function
+  //   arguments are (8.3.6).
+  bool SawDefaultArgument = false;
+  SourceLocation PreviousDefaultArgLoc;
+
+  // Dummy initialization to avoid warnings.
+  TemplateParameterList::iterator OldParam = NewParams->end();
+  if (OldParams)
+    OldParam = OldParams->begin();
+
+  bool RemoveDefaultArguments = false;
+  for (TemplateParameterList::iterator NewParam = NewParams->begin(),
+                                    NewParamEnd = NewParams->end();
+       NewParam != NewParamEnd; ++NewParam) {
+    // Variables used to diagnose redundant default arguments
+    bool RedundantDefaultArg = false;
+    SourceLocation OldDefaultLoc;
+    SourceLocation NewDefaultLoc;
+
+    // Variable used to diagnose missing default arguments
+    bool MissingDefaultArg = false;
+
+    // Variable used to diagnose non-final parameter packs
+    bool SawParameterPack = false;
+
+    if (TemplateTypeParmDecl *NewTypeParm
+          = dyn_cast<TemplateTypeParmDecl>(*NewParam)) {
+      // Check the presence of a default argument here.
+      if (NewTypeParm->hasDefaultArgument() &&
+          DiagnoseDefaultTemplateArgument(*this, TPC,
+                                          NewTypeParm->getLocation(),
+               NewTypeParm->getDefaultArgumentInfo()->getTypeLoc()
+                                                       .getSourceRange()))
+        NewTypeParm->removeDefaultArgument();
+
+      // Merge default arguments for template type parameters.
+      TemplateTypeParmDecl *OldTypeParm
+          = OldParams? cast<TemplateTypeParmDecl>(*OldParam) : 0;
+
+      if (NewTypeParm->isParameterPack()) {
+        assert(!NewTypeParm->hasDefaultArgument() &&
+               "Parameter packs can't have a default argument!");
+        SawParameterPack = true;
+      } else if (OldTypeParm && OldTypeParm->hasDefaultArgument() &&
+                 NewTypeParm->hasDefaultArgument()) {
+        OldDefaultLoc = OldTypeParm->getDefaultArgumentLoc();
+        NewDefaultLoc = NewTypeParm->getDefaultArgumentLoc();
+        SawDefaultArgument = true;
+        RedundantDefaultArg = true;
+        PreviousDefaultArgLoc = NewDefaultLoc;
+      } else if (OldTypeParm && OldTypeParm->hasDefaultArgument()) {
+        // Merge the default argument from the old declaration to the
+        // new declaration.
+        SawDefaultArgument = true;
+        NewTypeParm->setDefaultArgument(OldTypeParm->getDefaultArgumentInfo(),
+                                        true);
+        PreviousDefaultArgLoc = OldTypeParm->getDefaultArgumentLoc();
+      } else if (NewTypeParm->hasDefaultArgument()) {
+        SawDefaultArgument = true;
+        PreviousDefaultArgLoc = NewTypeParm->getDefaultArgumentLoc();
+      } else if (SawDefaultArgument)
+        MissingDefaultArg = true;
+    } else if (NonTypeTemplateParmDecl *NewNonTypeParm
+               = dyn_cast<NonTypeTemplateParmDecl>(*NewParam)) {
+      // Check for unexpanded parameter packs.
+      if (DiagnoseUnexpandedParameterPack(NewNonTypeParm->getLocation(),
+                                          NewNonTypeParm->getTypeSourceInfo(),
+                                          UPPC_NonTypeTemplateParameterType)) {
+        Invalid = true;
+        continue;
+      }
+
+      // Check the presence of a default argument here.
+      if (NewNonTypeParm->hasDefaultArgument() &&
+          DiagnoseDefaultTemplateArgument(*this, TPC,
+                                          NewNonTypeParm->getLocation(),
+                    NewNonTypeParm->getDefaultArgument()->getSourceRange())) {
+        NewNonTypeParm->removeDefaultArgument();
+      }
+
+      // Merge default arguments for non-type template parameters
+      NonTypeTemplateParmDecl *OldNonTypeParm
+        = OldParams? cast<NonTypeTemplateParmDecl>(*OldParam) : 0;
+      if (NewNonTypeParm->isParameterPack()) {
+        assert(!NewNonTypeParm->hasDefaultArgument() &&
+               "Parameter packs can't have a default argument!");
+        SawParameterPack = true;
+      } else if (OldNonTypeParm && OldNonTypeParm->hasDefaultArgument() &&
+          NewNonTypeParm->hasDefaultArgument()) {
+        OldDefaultLoc = OldNonTypeParm->getDefaultArgumentLoc();
+        NewDefaultLoc = NewNonTypeParm->getDefaultArgumentLoc();
+        SawDefaultArgument = true;
+        RedundantDefaultArg = true;
+        PreviousDefaultArgLoc = NewDefaultLoc;
+      } else if (OldNonTypeParm && OldNonTypeParm->hasDefaultArgument()) {
+        // Merge the default argument from the old declaration to the
+        // new declaration.
+        SawDefaultArgument = true;
+        // FIXME: We need to create a new kind of "default argument"
+        // expression that points to a previous non-type template
+        // parameter.
+        NewNonTypeParm->setDefaultArgument(
+                                         OldNonTypeParm->getDefaultArgument(),
+                                         /*Inherited=*/ true);
+        PreviousDefaultArgLoc = OldNonTypeParm->getDefaultArgumentLoc();
+      } else if (NewNonTypeParm->hasDefaultArgument()) {
+        SawDefaultArgument = true;
+        PreviousDefaultArgLoc = NewNonTypeParm->getDefaultArgumentLoc();
+      } else if (SawDefaultArgument)
+        MissingDefaultArg = true;
+    } else {
+      TemplateTemplateParmDecl *NewTemplateParm
+        = cast<TemplateTemplateParmDecl>(*NewParam);
+
+      // Check for unexpanded parameter packs, recursively.
+      if (::DiagnoseUnexpandedParameterPacks(*this, NewTemplateParm)) {
+        Invalid = true;
+        continue;
+      }
+
+      // Check the presence of a default argument here.
+      if (NewTemplateParm->hasDefaultArgument() &&
+          DiagnoseDefaultTemplateArgument(*this, TPC,
+                                          NewTemplateParm->getLocation(),
+                     NewTemplateParm->getDefaultArgument().getSourceRange()))
+        NewTemplateParm->removeDefaultArgument();
+
+      // Merge default arguments for template template parameters
+      TemplateTemplateParmDecl *OldTemplateParm
+        = OldParams? cast<TemplateTemplateParmDecl>(*OldParam) : 0;
+      if (NewTemplateParm->isParameterPack()) {
+        assert(!NewTemplateParm->hasDefaultArgument() &&
+               "Parameter packs can't have a default argument!");
+        SawParameterPack = true;
+      } else if (OldTemplateParm && OldTemplateParm->hasDefaultArgument() &&
+          NewTemplateParm->hasDefaultArgument()) {
+        OldDefaultLoc = OldTemplateParm->getDefaultArgument().getLocation();
+        NewDefaultLoc = NewTemplateParm->getDefaultArgument().getLocation();
+        SawDefaultArgument = true;
+        RedundantDefaultArg = true;
+        PreviousDefaultArgLoc = NewDefaultLoc;
+      } else if (OldTemplateParm && OldTemplateParm->hasDefaultArgument()) {
+        // Merge the default argument from the old declaration to the
+        // new declaration.
+        SawDefaultArgument = true;
+        // FIXME: We need to create a new kind of "default argument" expression
+        // that points to a previous template template parameter.
+        NewTemplateParm->setDefaultArgument(
+                                          OldTemplateParm->getDefaultArgument(),
+                                          /*Inherited=*/ true);
+        PreviousDefaultArgLoc
+          = OldTemplateParm->getDefaultArgument().getLocation();
+      } else if (NewTemplateParm->hasDefaultArgument()) {
+        SawDefaultArgument = true;
+        PreviousDefaultArgLoc
+          = NewTemplateParm->getDefaultArgument().getLocation();
+      } else if (SawDefaultArgument)
+        MissingDefaultArg = true;
+    }
+
+    // C++0x [temp.param]p11:
+    //   If a template parameter of a primary class template or alias template
+    //   is a template parameter pack, it shall be the last template parameter.
+    if (SawParameterPack && (NewParam + 1) != NewParamEnd && 
+        (TPC == TPC_ClassTemplate || TPC == TPC_TypeAliasTemplate)) {
+      Diag((*NewParam)->getLocation(),
+           diag::err_template_param_pack_must_be_last_template_parameter);
+      Invalid = true;
+    }
+
+    if (RedundantDefaultArg) {
+      // C++ [temp.param]p12:
+      //   A template-parameter shall not be given default arguments
+      //   by two different declarations in the same scope.
+      Diag(NewDefaultLoc, diag::err_template_param_default_arg_redefinition);
+      Diag(OldDefaultLoc, diag::note_template_param_prev_default_arg);
+      Invalid = true;
+    } else if (MissingDefaultArg && TPC != TPC_FunctionTemplate) {
+      // C++ [temp.param]p11:
+      //   If a template-parameter of a class template has a default
+      //   template-argument, each subsequent template-parameter shall either
+      //   have a default template-argument supplied or be a template parameter
+      //   pack.
+      Diag((*NewParam)->getLocation(),
+           diag::err_template_param_default_arg_missing);
+      Diag(PreviousDefaultArgLoc, diag::note_template_param_prev_default_arg);
+      Invalid = true;
+      RemoveDefaultArguments = true;
+    }
+
+    // If we have an old template parameter list that we're merging
+    // in, move on to the next parameter.
+    if (OldParams)
+      ++OldParam;
+  }
+
+  // We were missing some default arguments at the end of the list, so remove
+  // all of the default arguments.
+  if (RemoveDefaultArguments) {
+    for (TemplateParameterList::iterator NewParam = NewParams->begin(),
+                                      NewParamEnd = NewParams->end();
+         NewParam != NewParamEnd; ++NewParam) {
+      if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(*NewParam))
+        TTP->removeDefaultArgument();
+      else if (NonTypeTemplateParmDecl *NTTP
+                                = dyn_cast<NonTypeTemplateParmDecl>(*NewParam))
+        NTTP->removeDefaultArgument();
+      else
+        cast<TemplateTemplateParmDecl>(*NewParam)->removeDefaultArgument();
+    }
+  }
+
+  return Invalid;
+}
+
+namespace {
+
+/// A class which looks for a use of a certain level of template
+/// parameter.
+struct DependencyChecker : RecursiveASTVisitor<DependencyChecker> {
+  typedef RecursiveASTVisitor<DependencyChecker> super;
+
+  unsigned Depth;
+  bool Match;
+
+  DependencyChecker(TemplateParameterList *Params) : Match(false) {
+    NamedDecl *ND = Params->getParam(0);
+    if (TemplateTypeParmDecl *PD = dyn_cast<TemplateTypeParmDecl>(ND)) {
+      Depth = PD->getDepth();
+    } else if (NonTypeTemplateParmDecl *PD =
+                 dyn_cast<NonTypeTemplateParmDecl>(ND)) {
+      Depth = PD->getDepth();
+    } else {
+      Depth = cast<TemplateTemplateParmDecl>(ND)->getDepth();
+    }
+  }
+
+  bool Matches(unsigned ParmDepth) {
+    if (ParmDepth >= Depth) {
+      Match = true;
+      return true;
+    }
+    return false;
+  }
+
+  bool VisitTemplateTypeParmType(const TemplateTypeParmType *T) {
+    return !Matches(T->getDepth());
+  }
+
+  bool TraverseTemplateName(TemplateName N) {
+    if (TemplateTemplateParmDecl *PD =
+          dyn_cast_or_null<TemplateTemplateParmDecl>(N.getAsTemplateDecl()))
+      if (Matches(PD->getDepth())) return false;
+    return super::TraverseTemplateName(N);
+  }
+
+  bool VisitDeclRefExpr(DeclRefExpr *E) {
+    if (NonTypeTemplateParmDecl *PD =
+          dyn_cast<NonTypeTemplateParmDecl>(E->getDecl())) {
+      if (PD->getDepth() == Depth) {
+        Match = true;
+        return false;
+      }
+    }
+    return super::VisitDeclRefExpr(E);
+  }
+  
+  bool TraverseInjectedClassNameType(const InjectedClassNameType *T) {
+    return TraverseType(T->getInjectedSpecializationType());
+  }
+};
+}
+
+/// Determines whether a given type depends on the given parameter
+/// list.
+static bool
+DependsOnTemplateParameters(QualType T, TemplateParameterList *Params) {
+  DependencyChecker Checker(Params);
+  Checker.TraverseType(T);
+  return Checker.Match;
+}
+
+// Find the source range corresponding to the named type in the given
+// nested-name-specifier, if any.
+static SourceRange getRangeOfTypeInNestedNameSpecifier(ASTContext &Context,
+                                                       QualType T,
+                                                       const CXXScopeSpec &SS) {
+  NestedNameSpecifierLoc NNSLoc(SS.getScopeRep(), SS.location_data());
+  while (NestedNameSpecifier *NNS = NNSLoc.getNestedNameSpecifier()) {
+    if (const Type *CurType = NNS->getAsType()) {
+      if (Context.hasSameUnqualifiedType(T, QualType(CurType, 0)))
+        return NNSLoc.getTypeLoc().getSourceRange();
+    } else
+      break;
+    
+    NNSLoc = NNSLoc.getPrefix();
+  }
+  
+  return SourceRange();
+}
+
+/// \brief Match the given template parameter lists to the given scope
+/// specifier, returning the template parameter list that applies to the
+/// name.
+///
+/// \param DeclStartLoc the start of the declaration that has a scope
+/// specifier or a template parameter list.
+///
+/// \param DeclLoc The location of the declaration itself.
+///
+/// \param SS the scope specifier that will be matched to the given template
+/// parameter lists. This scope specifier precedes a qualified name that is
+/// being declared.
+///
+/// \param ParamLists the template parameter lists, from the outermost to the
+/// innermost template parameter lists.
+///
+/// \param NumParamLists the number of template parameter lists in ParamLists.
+///
+/// \param IsFriend Whether to apply the slightly different rules for
+/// matching template parameters to scope specifiers in friend
+/// declarations.
+///
+/// \param IsExplicitSpecialization will be set true if the entity being
+/// declared is an explicit specialization, false otherwise.
+///
+/// \returns the template parameter list, if any, that corresponds to the
+/// name that is preceded by the scope specifier @p SS. This template
+/// parameter list may have template parameters (if we're declaring a
+/// template) or may have no template parameters (if we're declaring a
+/// template specialization), or may be NULL (if what we're declaring isn't
+/// itself a template).
+TemplateParameterList *
+Sema::MatchTemplateParametersToScopeSpecifier(SourceLocation DeclStartLoc,
+                                              SourceLocation DeclLoc,
+                                              const CXXScopeSpec &SS,
+                                          TemplateParameterList **ParamLists,
+                                              unsigned NumParamLists,
+                                              bool IsFriend,
+                                              bool &IsExplicitSpecialization,
+                                              bool &Invalid) {
+  IsExplicitSpecialization = false;
+  Invalid = false;
+  
+  // The sequence of nested types to which we will match up the template
+  // parameter lists. We first build this list by starting with the type named
+  // by the nested-name-specifier and walking out until we run out of types.
+  SmallVector<QualType, 4> NestedTypes;
+  QualType T;
+  if (SS.getScopeRep()) {
+    if (CXXRecordDecl *Record 
+              = dyn_cast_or_null<CXXRecordDecl>(computeDeclContext(SS, true)))
+      T = Context.getTypeDeclType(Record);
+    else
+      T = QualType(SS.getScopeRep()->getAsType(), 0);
+  }
+  
+  // If we found an explicit specialization that prevents us from needing
+  // 'template<>' headers, this will be set to the location of that
+  // explicit specialization.
+  SourceLocation ExplicitSpecLoc;
+  
+  while (!T.isNull()) {
+    NestedTypes.push_back(T);
+    
+    // Retrieve the parent of a record type.
+    if (CXXRecordDecl *Record = T->getAsCXXRecordDecl()) {
+      // If this type is an explicit specialization, we're done.
+      if (ClassTemplateSpecializationDecl *Spec
+          = dyn_cast<ClassTemplateSpecializationDecl>(Record)) {
+        if (!isa<ClassTemplatePartialSpecializationDecl>(Spec) && 
+            Spec->getSpecializationKind() == TSK_ExplicitSpecialization) {
+          ExplicitSpecLoc = Spec->getLocation();
+          break;
+        }
+      } else if (Record->getTemplateSpecializationKind()
+                                                == TSK_ExplicitSpecialization) {
+        ExplicitSpecLoc = Record->getLocation();
+        break;
+      }
+      
+      if (TypeDecl *Parent = dyn_cast<TypeDecl>(Record->getParent()))
+        T = Context.getTypeDeclType(Parent);
+      else
+        T = QualType();
+      continue;
+    } 
+    
+    if (const TemplateSpecializationType *TST
+                                     = T->getAs<TemplateSpecializationType>()) {
+      if (TemplateDecl *Template = TST->getTemplateName().getAsTemplateDecl()) {
+        if (TypeDecl *Parent = dyn_cast<TypeDecl>(Template->getDeclContext()))
+          T = Context.getTypeDeclType(Parent);
+        else
+          T = QualType();
+        continue;        
+      }
+    }
+    
+    // Look one step prior in a dependent template specialization type.
+    if (const DependentTemplateSpecializationType *DependentTST
+                          = T->getAs<DependentTemplateSpecializationType>()) {
+      if (NestedNameSpecifier *NNS = DependentTST->getQualifier())
+        T = QualType(NNS->getAsType(), 0);
+      else
+        T = QualType();
+      continue;
+    }
+    
+    // Look one step prior in a dependent name type.
+    if (const DependentNameType *DependentName = T->getAs<DependentNameType>()){
+      if (NestedNameSpecifier *NNS = DependentName->getQualifier())
+        T = QualType(NNS->getAsType(), 0);
+      else
+        T = QualType();
+      continue;
+    }
+    
+    // Retrieve the parent of an enumeration type.
+    if (const EnumType *EnumT = T->getAs<EnumType>()) {
+      // FIXME: Forward-declared enums require a TSK_ExplicitSpecialization
+      // check here.
+      EnumDecl *Enum = EnumT->getDecl();
+      
+      // Get to the parent type.
+      if (TypeDecl *Parent = dyn_cast<TypeDecl>(Enum->getParent()))
+        T = Context.getTypeDeclType(Parent);
+      else
+        T = QualType();      
+      continue;
+    }
+
+    T = QualType();
+  }
+  // Reverse the nested types list, since we want to traverse from the outermost
+  // to the innermost while checking template-parameter-lists.
+  std::reverse(NestedTypes.begin(), NestedTypes.end());
+
+  // C++0x [temp.expl.spec]p17:
+  //   A member or a member template may be nested within many
+  //   enclosing class templates. In an explicit specialization for
+  //   such a member, the member declaration shall be preceded by a
+  //   template<> for each enclosing class template that is
+  //   explicitly specialized.
+  bool SawNonEmptyTemplateParameterList = false;
+  unsigned ParamIdx = 0;
+  for (unsigned TypeIdx = 0, NumTypes = NestedTypes.size(); TypeIdx != NumTypes;
+       ++TypeIdx) {
+    T = NestedTypes[TypeIdx];
+    
+    // Whether we expect a 'template<>' header.
+    bool NeedEmptyTemplateHeader = false;
+
+    // Whether we expect a template header with parameters.
+    bool NeedNonemptyTemplateHeader = false;
+    
+    // For a dependent type, the set of template parameters that we
+    // expect to see.
+    TemplateParameterList *ExpectedTemplateParams = 0;
+
+    // C++0x [temp.expl.spec]p15:
+    //   A member or a member template may be nested within many enclosing 
+    //   class templates. In an explicit specialization for such a member, the 
+    //   member declaration shall be preceded by a template<> for each 
+    //   enclosing class template that is explicitly specialized.
+    if (CXXRecordDecl *Record = T->getAsCXXRecordDecl()) {
+      if (ClassTemplatePartialSpecializationDecl *Partial
+            = dyn_cast<ClassTemplatePartialSpecializationDecl>(Record)) {
+        ExpectedTemplateParams = Partial->getTemplateParameters();
+        NeedNonemptyTemplateHeader = true;
+      } else if (Record->isDependentType()) {
+        if (Record->getDescribedClassTemplate()) {
+          ExpectedTemplateParams = Record->getDescribedClassTemplate()
+                                                      ->getTemplateParameters();
+          NeedNonemptyTemplateHeader = true;
+        }
+      } else if (ClassTemplateSpecializationDecl *Spec
+                     = dyn_cast<ClassTemplateSpecializationDecl>(Record)) {
+        // C++0x [temp.expl.spec]p4:
+        //   Members of an explicitly specialized class template are defined
+        //   in the same manner as members of normal classes, and not using 
+        //   the template<> syntax. 
+        if (Spec->getSpecializationKind() != TSK_ExplicitSpecialization)
+          NeedEmptyTemplateHeader = true;
+        else
+          continue;
+      } else if (Record->getTemplateSpecializationKind()) {
+        if (Record->getTemplateSpecializationKind() 
+                                                != TSK_ExplicitSpecialization &&
+            TypeIdx == NumTypes - 1)
+          IsExplicitSpecialization = true;
+        
+        continue;
+      }
+    } else if (const TemplateSpecializationType *TST
+                                     = T->getAs<TemplateSpecializationType>()) {
+      if (TemplateDecl *Template = TST->getTemplateName().getAsTemplateDecl()) {        
+        ExpectedTemplateParams = Template->getTemplateParameters();
+        NeedNonemptyTemplateHeader = true;        
+      }
+    } else if (T->getAs<DependentTemplateSpecializationType>()) {
+      // FIXME:  We actually could/should check the template arguments here
+      // against the corresponding template parameter list.
+      NeedNonemptyTemplateHeader = false;
+    } 
+    
+    // C++ [temp.expl.spec]p16:
+    //   In an explicit specialization declaration for a member of a class 
+    //   template or a member template that ap- pears in namespace scope, the 
+    //   member template and some of its enclosing class templates may remain 
+    //   unspecialized, except that the declaration shall not explicitly 
+    //   specialize a class member template if its en- closing class templates 
+    //   are not explicitly specialized as well.
+    if (ParamIdx < NumParamLists) {
+      if (ParamLists[ParamIdx]->size() == 0) {
+        if (SawNonEmptyTemplateParameterList) {
+          Diag(DeclLoc, diag::err_specialize_member_of_template)
+            << ParamLists[ParamIdx]->getSourceRange();
+          Invalid = true;
+          IsExplicitSpecialization = false;
+          return 0;
+        }
+      } else
+        SawNonEmptyTemplateParameterList = true;
+    }
+    
+    if (NeedEmptyTemplateHeader) {
+      // If we're on the last of the types, and we need a 'template<>' header
+      // here, then it's an explicit specialization.
+      if (TypeIdx == NumTypes - 1)
+        IsExplicitSpecialization = true;
+      
+      if (ParamIdx < NumParamLists) {
+        if (ParamLists[ParamIdx]->size() > 0) {
+          // The header has template parameters when it shouldn't. Complain.
+          Diag(ParamLists[ParamIdx]->getTemplateLoc(), 
+               diag::err_template_param_list_matches_nontemplate)
+            << T
+            << SourceRange(ParamLists[ParamIdx]->getLAngleLoc(),
+                           ParamLists[ParamIdx]->getRAngleLoc())
+            << getRangeOfTypeInNestedNameSpecifier(Context, T, SS);
+          Invalid = true;
+          return 0;
+        }
+        
+        // Consume this template header.
+        ++ParamIdx;
+        continue;
+      } 
+      
+      if (!IsFriend) {
+        // We don't have a template header, but we should.
+        SourceLocation ExpectedTemplateLoc;
+        if (NumParamLists > 0)
+          ExpectedTemplateLoc = ParamLists[0]->getTemplateLoc();
+        else
+          ExpectedTemplateLoc = DeclStartLoc;
+
+        Diag(DeclLoc, diag::err_template_spec_needs_header)
+          << getRangeOfTypeInNestedNameSpecifier(Context, T, SS)
+          << FixItHint::CreateInsertion(ExpectedTemplateLoc, "template<> ");
+      }
+      
+      continue;
+    }
+    
+    if (NeedNonemptyTemplateHeader) {
+      // In friend declarations we can have template-ids which don't
+      // depend on the corresponding template parameter lists.  But
+      // assume that empty parameter lists are supposed to match this
+      // template-id.
+      if (IsFriend && T->isDependentType()) {
+        if (ParamIdx < NumParamLists &&
+            DependsOnTemplateParameters(T, ParamLists[ParamIdx]))
+          ExpectedTemplateParams = 0;
+        else 
+          continue;
+      }
+
+      if (ParamIdx < NumParamLists) {
+        // Check the template parameter list, if we can.        
+        if (ExpectedTemplateParams &&
+            !TemplateParameterListsAreEqual(ParamLists[ParamIdx],
+                                            ExpectedTemplateParams,
+                                            true, TPL_TemplateMatch))
+          Invalid = true;
+        
+        if (!Invalid &&
+            CheckTemplateParameterList(ParamLists[ParamIdx], 0,
+                                       TPC_ClassTemplateMember))
+          Invalid = true;
+        
+        ++ParamIdx;
+        continue;
+      }
+      
+      Diag(DeclLoc, diag::err_template_spec_needs_template_parameters)
+        << T
+        << getRangeOfTypeInNestedNameSpecifier(Context, T, SS);
+      Invalid = true;
+      continue;
+    }
+  }
+    
+  // If there were at least as many template-ids as there were template
+  // parameter lists, then there are no template parameter lists remaining for
+  // the declaration itself.
+  if (ParamIdx >= NumParamLists)
+    return 0;
+
+  // If there were too many template parameter lists, complain about that now.
+  if (ParamIdx < NumParamLists - 1) {
+    bool HasAnyExplicitSpecHeader = false;
+    bool AllExplicitSpecHeaders = true;
+    for (unsigned I = ParamIdx; I != NumParamLists - 1; ++I) {
+      if (ParamLists[I]->size() == 0)
+        HasAnyExplicitSpecHeader = true;
+      else
+        AllExplicitSpecHeaders = false;
+    }
+    
+    Diag(ParamLists[ParamIdx]->getTemplateLoc(),
+         AllExplicitSpecHeaders? diag::warn_template_spec_extra_headers
+                               : diag::err_template_spec_extra_headers)
+      << SourceRange(ParamLists[ParamIdx]->getTemplateLoc(),
+                     ParamLists[NumParamLists - 2]->getRAngleLoc());
+
+    // If there was a specialization somewhere, such that 'template<>' is
+    // not required, and there were any 'template<>' headers, note where the
+    // specialization occurred.
+    if (ExplicitSpecLoc.isValid() && HasAnyExplicitSpecHeader)
+      Diag(ExplicitSpecLoc, 
+           diag::note_explicit_template_spec_does_not_need_header)
+        << NestedTypes.back();
+    
+    // We have a template parameter list with no corresponding scope, which
+    // means that the resulting template declaration can't be instantiated
+    // properly (we'll end up with dependent nodes when we shouldn't).
+    if (!AllExplicitSpecHeaders)
+      Invalid = true;
+  }
+
+  // C++ [temp.expl.spec]p16:
+  //   In an explicit specialization declaration for a member of a class 
+  //   template or a member template that ap- pears in namespace scope, the 
+  //   member template and some of its enclosing class templates may remain 
+  //   unspecialized, except that the declaration shall not explicitly 
+  //   specialize a class member template if its en- closing class templates 
+  //   are not explicitly specialized as well.
+  if (ParamLists[NumParamLists - 1]->size() == 0 && 
+      SawNonEmptyTemplateParameterList) {
+    Diag(DeclLoc, diag::err_specialize_member_of_template)
+      << ParamLists[ParamIdx]->getSourceRange();
+    Invalid = true;
+    IsExplicitSpecialization = false;
+    return 0;
+  }
+  
+  // Return the last template parameter list, which corresponds to the
+  // entity being declared.
+  return ParamLists[NumParamLists - 1];
+}
+
+void Sema::NoteAllFoundTemplates(TemplateName Name) {
+  if (TemplateDecl *Template = Name.getAsTemplateDecl()) {
+    Diag(Template->getLocation(), diag::note_template_declared_here)
+      << (isa<FunctionTemplateDecl>(Template)? 0
+          : isa<ClassTemplateDecl>(Template)? 1
+          : isa<TypeAliasTemplateDecl>(Template)? 2
+          : 3)
+      << Template->getDeclName();
+    return;
+  }
+  
+  if (OverloadedTemplateStorage *OST = Name.getAsOverloadedTemplate()) {
+    for (OverloadedTemplateStorage::iterator I = OST->begin(), 
+                                          IEnd = OST->end();
+         I != IEnd; ++I)
+      Diag((*I)->getLocation(), diag::note_template_declared_here)
+        << 0 << (*I)->getDeclName();
+    
+    return;
+  }
+}
+
+QualType Sema::CheckTemplateIdType(TemplateName Name,
+                                   SourceLocation TemplateLoc,
+                                   TemplateArgumentListInfo &TemplateArgs) {
+  DependentTemplateName *DTN
+    = Name.getUnderlying().getAsDependentTemplateName();
+  if (DTN && DTN->isIdentifier())
+    // When building a template-id where the template-name is dependent,
+    // assume the template is a type template. Either our assumption is
+    // correct, or the code is ill-formed and will be diagnosed when the
+    // dependent name is substituted.
+    return Context.getDependentTemplateSpecializationType(ETK_None,
+                                                          DTN->getQualifier(),
+                                                          DTN->getIdentifier(),
+                                                          TemplateArgs);
+
+  TemplateDecl *Template = Name.getAsTemplateDecl();
+  if (!Template || isa<FunctionTemplateDecl>(Template)) {
+    // We might have a substituted template template parameter pack. If so,
+    // build a template specialization type for it.
+    if (Name.getAsSubstTemplateTemplateParmPack())
+      return Context.getTemplateSpecializationType(Name, TemplateArgs);
+
+    Diag(TemplateLoc, diag::err_template_id_not_a_type)
+      << Name;
+    NoteAllFoundTemplates(Name);
+    return QualType();
+  }
+
+  // Check that the template argument list is well-formed for this
+  // template.
+  SmallVector<TemplateArgument, 4> Converted;
+  bool ExpansionIntoFixedList = false;
+  if (CheckTemplateArgumentList(Template, TemplateLoc, TemplateArgs,
+                                false, Converted, &ExpansionIntoFixedList))
+    return QualType();
+
+  QualType CanonType;
+
+  bool InstantiationDependent = false;
+  TypeAliasTemplateDecl *AliasTemplate = 0;
+  if (!ExpansionIntoFixedList &&
+      (AliasTemplate = dyn_cast<TypeAliasTemplateDecl>(Template))) {
+    // Find the canonical type for this type alias template specialization.
+    TypeAliasDecl *Pattern = AliasTemplate->getTemplatedDecl();
+    if (Pattern->isInvalidDecl())
+      return QualType();
+
+    TemplateArgumentList TemplateArgs(TemplateArgumentList::OnStack,
+                                      Converted.data(), Converted.size());
+
+    // Only substitute for the innermost template argument list.
+    MultiLevelTemplateArgumentList TemplateArgLists;
+    TemplateArgLists.addOuterTemplateArguments(&TemplateArgs);
+    unsigned Depth = AliasTemplate->getTemplateParameters()->getDepth();
+    for (unsigned I = 0; I < Depth; ++I)
+      TemplateArgLists.addOuterTemplateArguments(0, 0);
+
+    InstantiatingTemplate Inst(*this, TemplateLoc, Template);
+    CanonType = SubstType(Pattern->getUnderlyingType(),
+                          TemplateArgLists, AliasTemplate->getLocation(),
+                          AliasTemplate->getDeclName());
+    if (CanonType.isNull())
+      return QualType();
+  } else if (Name.isDependent() ||
+             TemplateSpecializationType::anyDependentTemplateArguments(
+               TemplateArgs, InstantiationDependent)) {
+    // This class template specialization is a dependent
+    // type. Therefore, its canonical type is another class template
+    // specialization type that contains all of the converted
+    // arguments in canonical form. This ensures that, e.g., A<T> and
+    // A<T, T> have identical types when A is declared as:
+    //
+    //   template<typename T, typename U = T> struct A;
+    TemplateName CanonName = Context.getCanonicalTemplateName(Name);
+    CanonType = Context.getTemplateSpecializationType(CanonName,
+                                                      Converted.data(),
+                                                      Converted.size());
+
+    // FIXME: CanonType is not actually the canonical type, and unfortunately
+    // it is a TemplateSpecializationType that we will never use again.
+    // In the future, we need to teach getTemplateSpecializationType to only
+    // build the canonical type and return that to us.
+    CanonType = Context.getCanonicalType(CanonType);
+
+    // This might work out to be a current instantiation, in which
+    // case the canonical type needs to be the InjectedClassNameType.
+    //
+    // TODO: in theory this could be a simple hashtable lookup; most
+    // changes to CurContext don't change the set of current
+    // instantiations.
+    if (isa<ClassTemplateDecl>(Template)) {
+      for (DeclContext *Ctx = CurContext; Ctx; Ctx = Ctx->getLookupParent()) {
+        // If we get out to a namespace, we're done.
+        if (Ctx->isFileContext()) break;
+
+        // If this isn't a record, keep looking.
+        CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(Ctx);
+        if (!Record) continue;
+
+        // Look for one of the two cases with InjectedClassNameTypes
+        // and check whether it's the same template.
+        if (!isa<ClassTemplatePartialSpecializationDecl>(Record) &&
+            !Record->getDescribedClassTemplate())
+          continue;
+
+        // Fetch the injected class name type and check whether its
+        // injected type is equal to the type we just built.
+        QualType ICNT = Context.getTypeDeclType(Record);
+        QualType Injected = cast<InjectedClassNameType>(ICNT)
+          ->getInjectedSpecializationType();
+
+        if (CanonType != Injected->getCanonicalTypeInternal())
+          continue;
+
+        // If so, the canonical type of this TST is the injected
+        // class name type of the record we just found.
+        assert(ICNT.isCanonical());
+        CanonType = ICNT;
+        break;
+      }
+    }
+  } else if (ClassTemplateDecl *ClassTemplate
+               = dyn_cast<ClassTemplateDecl>(Template)) {
+    // Find the class template specialization declaration that
+    // corresponds to these arguments.
+    void *InsertPos = 0;
+    ClassTemplateSpecializationDecl *Decl
+      = ClassTemplate->findSpecialization(Converted.data(), Converted.size(),
+                                          InsertPos);
+    if (!Decl) {
+      // This is the first time we have referenced this class template
+      // specialization. Create the canonical declaration and add it to
+      // the set of specializations.
+      Decl = ClassTemplateSpecializationDecl::Create(Context,
+                            ClassTemplate->getTemplatedDecl()->getTagKind(),
+                                                ClassTemplate->getDeclContext(),
+                            ClassTemplate->getTemplatedDecl()->getLocStart(),
+                                                ClassTemplate->getLocation(),
+                                                     ClassTemplate,
+                                                     Converted.data(),
+                                                     Converted.size(), 0);
+      ClassTemplate->AddSpecialization(Decl, InsertPos);
+      Decl->setLexicalDeclContext(CurContext);
+    }
+
+    CanonType = Context.getTypeDeclType(Decl);
+    assert(isa<RecordType>(CanonType) &&
+           "type of non-dependent specialization is not a RecordType");
+  }
+
+  // Build the fully-sugared type for this class template
+  // specialization, which refers back to the class template
+  // specialization we created or found.
+  return Context.getTemplateSpecializationType(Name, TemplateArgs, CanonType);
+}
+
+TypeResult
+Sema::ActOnTemplateIdType(CXXScopeSpec &SS, SourceLocation TemplateKWLoc,
+                          TemplateTy TemplateD, SourceLocation TemplateLoc,
+                          SourceLocation LAngleLoc,
+                          ASTTemplateArgsPtr TemplateArgsIn,
+                          SourceLocation RAngleLoc,
+                          bool IsCtorOrDtorName) {
+  if (SS.isInvalid())
+    return true;
+
+  TemplateName Template = TemplateD.getAsVal<TemplateName>();
+
+  // Translate the parser's template argument list in our AST format.
+  TemplateArgumentListInfo TemplateArgs(LAngleLoc, RAngleLoc);
+  translateTemplateArguments(TemplateArgsIn, TemplateArgs);
+
+  if (DependentTemplateName *DTN = Template.getAsDependentTemplateName()) {
+    QualType T
+      = Context.getDependentTemplateSpecializationType(ETK_None,
+                                                       DTN->getQualifier(),
+                                                       DTN->getIdentifier(),
+                                                       TemplateArgs);
+    // Build type-source information.
+    TypeLocBuilder TLB;
+    DependentTemplateSpecializationTypeLoc SpecTL
+      = TLB.push<DependentTemplateSpecializationTypeLoc>(T);
+    SpecTL.setElaboratedKeywordLoc(SourceLocation());
+    SpecTL.setQualifierLoc(SS.getWithLocInContext(Context));
+    SpecTL.setTemplateKeywordLoc(TemplateKWLoc);
+    SpecTL.setTemplateNameLoc(TemplateLoc);
+    SpecTL.setLAngleLoc(LAngleLoc);
+    SpecTL.setRAngleLoc(RAngleLoc);
+    for (unsigned I = 0, N = SpecTL.getNumArgs(); I != N; ++I)
+      SpecTL.setArgLocInfo(I, TemplateArgs[I].getLocInfo());
+    return CreateParsedType(T, TLB.getTypeSourceInfo(Context, T));
+  }
+  
+  QualType Result = CheckTemplateIdType(Template, TemplateLoc, TemplateArgs);
+  TemplateArgsIn.release();
+
+  if (Result.isNull())
+    return true;
+
+  // Build type-source information.
+  TypeLocBuilder TLB;
+  TemplateSpecializationTypeLoc SpecTL
+    = TLB.push<TemplateSpecializationTypeLoc>(Result);
+  SpecTL.setTemplateKeywordLoc(TemplateKWLoc);
+  SpecTL.setTemplateNameLoc(TemplateLoc);
+  SpecTL.setLAngleLoc(LAngleLoc);
+  SpecTL.setRAngleLoc(RAngleLoc);
+  for (unsigned i = 0, e = SpecTL.getNumArgs(); i != e; ++i)
+    SpecTL.setArgLocInfo(i, TemplateArgs[i].getLocInfo());
+
+  // NOTE: avoid constructing an ElaboratedTypeLoc if this is a
+  // constructor or destructor name (in such a case, the scope specifier
+  // will be attached to the enclosing Decl or Expr node).
+  if (SS.isNotEmpty() && !IsCtorOrDtorName) {
+    // Create an elaborated-type-specifier containing the nested-name-specifier.
+    Result = Context.getElaboratedType(ETK_None, SS.getScopeRep(), Result);
+    ElaboratedTypeLoc ElabTL = TLB.push<ElaboratedTypeLoc>(Result);
+    ElabTL.setElaboratedKeywordLoc(SourceLocation());
+    ElabTL.setQualifierLoc(SS.getWithLocInContext(Context));
+  }
+  
+  return CreateParsedType(Result, TLB.getTypeSourceInfo(Context, Result));
+}
+
+TypeResult Sema::ActOnTagTemplateIdType(TagUseKind TUK,
+                                        TypeSpecifierType TagSpec,
+                                        SourceLocation TagLoc,
+                                        CXXScopeSpec &SS,
+                                        SourceLocation TemplateKWLoc,
+                                        TemplateTy TemplateD,
+                                        SourceLocation TemplateLoc,
+                                        SourceLocation LAngleLoc,
+                                        ASTTemplateArgsPtr TemplateArgsIn,
+                                        SourceLocation RAngleLoc) {
+  TemplateName Template = TemplateD.getAsVal<TemplateName>();
+  
+  // Translate the parser's template argument list in our AST format.
+  TemplateArgumentListInfo TemplateArgs(LAngleLoc, RAngleLoc);
+  translateTemplateArguments(TemplateArgsIn, TemplateArgs);
+  
+  // Determine the tag kind
+  TagTypeKind TagKind = TypeWithKeyword::getTagTypeKindForTypeSpec(TagSpec);
+  ElaboratedTypeKeyword Keyword
+    = TypeWithKeyword::getKeywordForTagTypeKind(TagKind);
+
+  if (DependentTemplateName *DTN = Template.getAsDependentTemplateName()) {
+    QualType T = Context.getDependentTemplateSpecializationType(Keyword,
+                                                          DTN->getQualifier(), 
+                                                          DTN->getIdentifier(), 
+                                                                TemplateArgs);
+    
+    // Build type-source information.    
+    TypeLocBuilder TLB;
+    DependentTemplateSpecializationTypeLoc SpecTL
+      = TLB.push<DependentTemplateSpecializationTypeLoc>(T);
+    SpecTL.setElaboratedKeywordLoc(TagLoc);
+    SpecTL.setQualifierLoc(SS.getWithLocInContext(Context));
+    SpecTL.setTemplateKeywordLoc(TemplateKWLoc);
+    SpecTL.setTemplateNameLoc(TemplateLoc);
+    SpecTL.setLAngleLoc(LAngleLoc);
+    SpecTL.setRAngleLoc(RAngleLoc);
+    for (unsigned I = 0, N = SpecTL.getNumArgs(); I != N; ++I)
+      SpecTL.setArgLocInfo(I, TemplateArgs[I].getLocInfo());
+    return CreateParsedType(T, TLB.getTypeSourceInfo(Context, T));
+  }
+
+  if (TypeAliasTemplateDecl *TAT =
+        dyn_cast_or_null<TypeAliasTemplateDecl>(Template.getAsTemplateDecl())) {
+    // C++0x [dcl.type.elab]p2:
+    //   If the identifier resolves to a typedef-name or the simple-template-id
+    //   resolves to an alias template specialization, the
+    //   elaborated-type-specifier is ill-formed.
+    Diag(TemplateLoc, diag::err_tag_reference_non_tag) << 4;
+    Diag(TAT->getLocation(), diag::note_declared_at);
+  }
+  
+  QualType Result = CheckTemplateIdType(Template, TemplateLoc, TemplateArgs);
+  if (Result.isNull())
+    return TypeResult(true);
+  
+  // Check the tag kind
+  if (const RecordType *RT = Result->getAs<RecordType>()) {
+    RecordDecl *D = RT->getDecl();
+    
+    IdentifierInfo *Id = D->getIdentifier();
+    assert(Id && "templated class must have an identifier");
+    
+    if (!isAcceptableTagRedeclaration(D, TagKind, TUK == TUK_Definition,
+                                      TagLoc, *Id)) {
+      Diag(TagLoc, diag::err_use_with_wrong_tag)
+        << Result
+        << FixItHint::CreateReplacement(SourceRange(TagLoc), D->getKindName());
+      Diag(D->getLocation(), diag::note_previous_use);
+    }
+  }
+
+  // Provide source-location information for the template specialization.
+  TypeLocBuilder TLB;
+  TemplateSpecializationTypeLoc SpecTL
+    = TLB.push<TemplateSpecializationTypeLoc>(Result);
+  SpecTL.setTemplateKeywordLoc(TemplateKWLoc);
+  SpecTL.setTemplateNameLoc(TemplateLoc);
+  SpecTL.setLAngleLoc(LAngleLoc);
+  SpecTL.setRAngleLoc(RAngleLoc);
+  for (unsigned i = 0, e = SpecTL.getNumArgs(); i != e; ++i)
+    SpecTL.setArgLocInfo(i, TemplateArgs[i].getLocInfo());
+
+  // Construct an elaborated type containing the nested-name-specifier (if any)
+  // and tag keyword.
+  Result = Context.getElaboratedType(Keyword, SS.getScopeRep(), Result);
+  ElaboratedTypeLoc ElabTL = TLB.push<ElaboratedTypeLoc>(Result);
+  ElabTL.setElaboratedKeywordLoc(TagLoc);
+  ElabTL.setQualifierLoc(SS.getWithLocInContext(Context));
+  return CreateParsedType(Result, TLB.getTypeSourceInfo(Context, Result));
+}
+
+ExprResult Sema::BuildTemplateIdExpr(const CXXScopeSpec &SS,
+                                     SourceLocation TemplateKWLoc,
+                                     LookupResult &R,
+                                     bool RequiresADL,
+                                 const TemplateArgumentListInfo *TemplateArgs) {
+  // FIXME: Can we do any checking at this point? I guess we could check the
+  // template arguments that we have against the template name, if the template
+  // name refers to a single template. That's not a terribly common case,
+  // though.
+  // foo<int> could identify a single function unambiguously
+  // This approach does NOT work, since f<int>(1);
+  // gets resolved prior to resorting to overload resolution
+  // i.e., template<class T> void f(double);
+  //       vs template<class T, class U> void f(U);
+
+  // These should be filtered out by our callers.
+  assert(!R.empty() && "empty lookup results when building templateid");
+  assert(!R.isAmbiguous() && "ambiguous lookup when building templateid");
+
+  // We don't want lookup warnings at this point.
+  R.suppressDiagnostics();
+
+  UnresolvedLookupExpr *ULE
+    = UnresolvedLookupExpr::Create(Context, R.getNamingClass(),
+                                   SS.getWithLocInContext(Context),
+                                   TemplateKWLoc,
+                                   R.getLookupNameInfo(),
+                                   RequiresADL, TemplateArgs,
+                                   R.begin(), R.end());
+
+  return Owned(ULE);
+}
+
+// We actually only call this from template instantiation.
+ExprResult
+Sema::BuildQualifiedTemplateIdExpr(CXXScopeSpec &SS,
+                                   SourceLocation TemplateKWLoc,
+                                   const DeclarationNameInfo &NameInfo,
+                             const TemplateArgumentListInfo *TemplateArgs) {
+  assert(TemplateArgs || TemplateKWLoc.isValid());
+  DeclContext *DC;
+  if (!(DC = computeDeclContext(SS, false)) ||
+      DC->isDependentContext() ||
+      RequireCompleteDeclContext(SS, DC))
+    return BuildDependentDeclRefExpr(SS, TemplateKWLoc, NameInfo, TemplateArgs);
+
+  bool MemberOfUnknownSpecialization;
+  LookupResult R(*this, NameInfo, LookupOrdinaryName);
+  LookupTemplateName(R, (Scope*) 0, SS, QualType(), /*Entering*/ false,
+                     MemberOfUnknownSpecialization);
+
+  if (R.isAmbiguous())
+    return ExprError();
+
+  if (R.empty()) {
+    Diag(NameInfo.getLoc(), diag::err_template_kw_refers_to_non_template)
+      << NameInfo.getName() << SS.getRange();
+    return ExprError();
+  }
+
+  if (ClassTemplateDecl *Temp = R.getAsSingle<ClassTemplateDecl>()) {
+    Diag(NameInfo.getLoc(), diag::err_template_kw_refers_to_class_template)
+      << (NestedNameSpecifier*) SS.getScopeRep()
+      << NameInfo.getName() << SS.getRange();
+    Diag(Temp->getLocation(), diag::note_referenced_class_template);
+    return ExprError();
+  }
+
+  return BuildTemplateIdExpr(SS, TemplateKWLoc, R, /*ADL*/ false, TemplateArgs);
+}
+
+/// \brief Form a dependent template name.
+///
+/// This action forms a dependent template name given the template
+/// name and its (presumably dependent) scope specifier. For
+/// example, given "MetaFun::template apply", the scope specifier \p
+/// SS will be "MetaFun::", \p TemplateKWLoc contains the location
+/// of the "template" keyword, and "apply" is the \p Name.
+TemplateNameKind Sema::ActOnDependentTemplateName(Scope *S,
+                                                  CXXScopeSpec &SS,
+                                                  SourceLocation TemplateKWLoc,
+                                                  UnqualifiedId &Name,
+                                                  ParsedType ObjectType,
+                                                  bool EnteringContext,
+                                                  TemplateTy &Result) {
+  if (TemplateKWLoc.isValid() && S && !S->getTemplateParamParent())
+    Diag(TemplateKWLoc,
+         getLangOpts().CPlusPlus0x ?
+           diag::warn_cxx98_compat_template_outside_of_template :
+           diag::ext_template_outside_of_template)
+      << FixItHint::CreateRemoval(TemplateKWLoc);
+
+  DeclContext *LookupCtx = 0;
+  if (SS.isSet())
+    LookupCtx = computeDeclContext(SS, EnteringContext);
+  if (!LookupCtx && ObjectType)
+    LookupCtx = computeDeclContext(ObjectType.get());
+  if (LookupCtx) {
+    // C++0x [temp.names]p5:
+    //   If a name prefixed by the keyword template is not the name of
+    //   a template, the program is ill-formed. [Note: the keyword
+    //   template may not be applied to non-template members of class
+    //   templates. -end note ] [ Note: as is the case with the
+    //   typename prefix, the template prefix is allowed in cases
+    //   where it is not strictly necessary; i.e., when the
+    //   nested-name-specifier or the expression on the left of the ->
+    //   or . is not dependent on a template-parameter, or the use
+    //   does not appear in the scope of a template. -end note]
+    //
+    // Note: C++03 was more strict here, because it banned the use of
+    // the "template" keyword prior to a template-name that was not a
+    // dependent name. C++ DR468 relaxed this requirement (the
+    // "template" keyword is now permitted). We follow the C++0x
+    // rules, even in C++03 mode with a warning, retroactively applying the DR.
+    bool MemberOfUnknownSpecialization;
+    TemplateNameKind TNK = isTemplateName(0, SS, TemplateKWLoc.isValid(), Name,
+                                          ObjectType, EnteringContext, Result,
+                                          MemberOfUnknownSpecialization);
+    if (TNK == TNK_Non_template && LookupCtx->isDependentContext() &&
+        isa<CXXRecordDecl>(LookupCtx) &&
+        (!cast<CXXRecordDecl>(LookupCtx)->hasDefinition() ||
+         cast<CXXRecordDecl>(LookupCtx)->hasAnyDependentBases())) {
+      // This is a dependent template. Handle it below.
+    } else if (TNK == TNK_Non_template) {
+      Diag(Name.getLocStart(),
+           diag::err_template_kw_refers_to_non_template)
+        << GetNameFromUnqualifiedId(Name).getName()
+        << Name.getSourceRange()
+        << TemplateKWLoc;
+      return TNK_Non_template;
+    } else {
+      // We found something; return it.
+      return TNK;
+    }
+  }
+
+  NestedNameSpecifier *Qualifier
+    = static_cast<NestedNameSpecifier *>(SS.getScopeRep());
+
+  switch (Name.getKind()) {
+  case UnqualifiedId::IK_Identifier:
+    Result = TemplateTy::make(Context.getDependentTemplateName(Qualifier,
+                                                              Name.Identifier));
+    return TNK_Dependent_template_name;
+
+  case UnqualifiedId::IK_OperatorFunctionId:
+    Result = TemplateTy::make(Context.getDependentTemplateName(Qualifier,
+                                             Name.OperatorFunctionId.Operator));
+    return TNK_Dependent_template_name;
+
+  case UnqualifiedId::IK_LiteralOperatorId:
+    llvm_unreachable(
+            "We don't support these; Parse shouldn't have allowed propagation");
+
+  default:
+    break;
+  }
+
+  Diag(Name.getLocStart(),
+       diag::err_template_kw_refers_to_non_template)
+    << GetNameFromUnqualifiedId(Name).getName()
+    << Name.getSourceRange()
+    << TemplateKWLoc;
+  return TNK_Non_template;
+}
+
+bool Sema::CheckTemplateTypeArgument(TemplateTypeParmDecl *Param,
+                                     const TemplateArgumentLoc &AL,
+                          SmallVectorImpl<TemplateArgument> &Converted) {
+  const TemplateArgument &Arg = AL.getArgument();
+
+  // Check template type parameter.
+  switch(Arg.getKind()) {
+  case TemplateArgument::Type:
+    // C++ [temp.arg.type]p1:
+    //   A template-argument for a template-parameter which is a
+    //   type shall be a type-id.
+    break;
+  case TemplateArgument::Template: {
+    // We have a template type parameter but the template argument
+    // is a template without any arguments.
+    SourceRange SR = AL.getSourceRange();
+    TemplateName Name = Arg.getAsTemplate();
+    Diag(SR.getBegin(), diag::err_template_missing_args)
+      << Name << SR;
+    if (TemplateDecl *Decl = Name.getAsTemplateDecl())
+      Diag(Decl->getLocation(), diag::note_template_decl_here);
+
+    return true;
+  }
+  default: {
+    // We have a template type parameter but the template argument
+    // is not a type.
+    SourceRange SR = AL.getSourceRange();
+    Diag(SR.getBegin(), diag::err_template_arg_must_be_type) << SR;
+    Diag(Param->getLocation(), diag::note_template_param_here);
+
+    return true;
+  }
+  }
+
+  if (CheckTemplateArgument(Param, AL.getTypeSourceInfo()))
+    return true;
+
+  // Add the converted template type argument.
+  QualType ArgType = Context.getCanonicalType(Arg.getAsType());
+  
+  // Objective-C ARC:
+  //   If an explicitly-specified template argument type is a lifetime type
+  //   with no lifetime qualifier, the __strong lifetime qualifier is inferred.
+  if (getLangOpts().ObjCAutoRefCount &&
+      ArgType->isObjCLifetimeType() &&
+      !ArgType.getObjCLifetime()) {
+    Qualifiers Qs;
+    Qs.setObjCLifetime(Qualifiers::OCL_Strong);
+    ArgType = Context.getQualifiedType(ArgType, Qs);
+  }
+  
+  Converted.push_back(TemplateArgument(ArgType));
+  return false;
+}
+
+/// \brief Substitute template arguments into the default template argument for
+/// the given template type parameter.
+///
+/// \param SemaRef the semantic analysis object for which we are performing
+/// the substitution.
+///
+/// \param Template the template that we are synthesizing template arguments
+/// for.
+///
+/// \param TemplateLoc the location of the template name that started the
+/// template-id we are checking.
+///
+/// \param RAngleLoc the location of the right angle bracket ('>') that
+/// terminates the template-id.
+///
+/// \param Param the template template parameter whose default we are
+/// substituting into.
+///
+/// \param Converted the list of template arguments provided for template
+/// parameters that precede \p Param in the template parameter list.
+/// \returns the substituted template argument, or NULL if an error occurred.
+static TypeSourceInfo *
+SubstDefaultTemplateArgument(Sema &SemaRef,
+                             TemplateDecl *Template,
+                             SourceLocation TemplateLoc,
+                             SourceLocation RAngleLoc,
+                             TemplateTypeParmDecl *Param,
+                         SmallVectorImpl<TemplateArgument> &Converted) {
+  TypeSourceInfo *ArgType = Param->getDefaultArgumentInfo();
+
+  // If the argument type is dependent, instantiate it now based
+  // on the previously-computed template arguments.
+  if (ArgType->getType()->isDependentType()) {
+    TemplateArgumentList TemplateArgs(TemplateArgumentList::OnStack,
+                                      Converted.data(), Converted.size());
+
+    MultiLevelTemplateArgumentList AllTemplateArgs
+      = SemaRef.getTemplateInstantiationArgs(Template, &TemplateArgs);
+
+    Sema::InstantiatingTemplate Inst(SemaRef, TemplateLoc,
+                                     Template, Converted.data(),
+                                     Converted.size(),
+                                     SourceRange(TemplateLoc, RAngleLoc));
+
+    Sema::ContextRAII SavedContext(SemaRef, Template->getDeclContext());
+    ArgType = SemaRef.SubstType(ArgType, AllTemplateArgs,
+                                Param->getDefaultArgumentLoc(),
+                                Param->getDeclName());
+  }
+
+  return ArgType;
+}
+
+/// \brief Substitute template arguments into the default template argument for
+/// the given non-type template parameter.
+///
+/// \param SemaRef the semantic analysis object for which we are performing
+/// the substitution.
+///
+/// \param Template the template that we are synthesizing template arguments
+/// for.
+///
+/// \param TemplateLoc the location of the template name that started the
+/// template-id we are checking.
+///
+/// \param RAngleLoc the location of the right angle bracket ('>') that
+/// terminates the template-id.
+///
+/// \param Param the non-type template parameter whose default we are
+/// substituting into.
+///
+/// \param Converted the list of template arguments provided for template
+/// parameters that precede \p Param in the template parameter list.
+///
+/// \returns the substituted template argument, or NULL if an error occurred.
+static ExprResult
+SubstDefaultTemplateArgument(Sema &SemaRef,
+                             TemplateDecl *Template,
+                             SourceLocation TemplateLoc,
+                             SourceLocation RAngleLoc,
+                             NonTypeTemplateParmDecl *Param,
+                        SmallVectorImpl<TemplateArgument> &Converted) {
+  TemplateArgumentList TemplateArgs(TemplateArgumentList::OnStack,
+                                    Converted.data(), Converted.size());
+
+  MultiLevelTemplateArgumentList AllTemplateArgs
+    = SemaRef.getTemplateInstantiationArgs(Template, &TemplateArgs);
+
+  Sema::InstantiatingTemplate Inst(SemaRef, TemplateLoc,
+                                   Template, Converted.data(),
+                                   Converted.size(),
+                                   SourceRange(TemplateLoc, RAngleLoc));
+
+  Sema::ContextRAII SavedContext(SemaRef, Template->getDeclContext());
+  EnterExpressionEvaluationContext Unevaluated(SemaRef, Sema::Unevaluated);
+  return SemaRef.SubstExpr(Param->getDefaultArgument(), AllTemplateArgs);
+}
+
+/// \brief Substitute template arguments into the default template argument for
+/// the given template template parameter.
+///
+/// \param SemaRef the semantic analysis object for which we are performing
+/// the substitution.
+///
+/// \param Template the template that we are synthesizing template arguments
+/// for.
+///
+/// \param TemplateLoc the location of the template name that started the
+/// template-id we are checking.
+///
+/// \param RAngleLoc the location of the right angle bracket ('>') that
+/// terminates the template-id.
+///
+/// \param Param the template template parameter whose default we are
+/// substituting into.
+///
+/// \param Converted the list of template arguments provided for template
+/// parameters that precede \p Param in the template parameter list.
+///
+/// \param QualifierLoc Will be set to the nested-name-specifier (with 
+/// source-location information) that precedes the template name.
+///
+/// \returns the substituted template argument, or NULL if an error occurred.
+static TemplateName
+SubstDefaultTemplateArgument(Sema &SemaRef,
+                             TemplateDecl *Template,
+                             SourceLocation TemplateLoc,
+                             SourceLocation RAngleLoc,
+                             TemplateTemplateParmDecl *Param,
+                       SmallVectorImpl<TemplateArgument> &Converted,
+                             NestedNameSpecifierLoc &QualifierLoc) {
+  TemplateArgumentList TemplateArgs(TemplateArgumentList::OnStack,
+                                    Converted.data(), Converted.size());
+
+  MultiLevelTemplateArgumentList AllTemplateArgs
+    = SemaRef.getTemplateInstantiationArgs(Template, &TemplateArgs);
+
+  Sema::InstantiatingTemplate Inst(SemaRef, TemplateLoc,
+                                   Template, Converted.data(),
+                                   Converted.size(),
+                                   SourceRange(TemplateLoc, RAngleLoc));
+
+  Sema::ContextRAII SavedContext(SemaRef, Template->getDeclContext());
+  // Substitute into the nested-name-specifier first, 
+  QualifierLoc = Param->getDefaultArgument().getTemplateQualifierLoc();
+  if (QualifierLoc) {
+    QualifierLoc = SemaRef.SubstNestedNameSpecifierLoc(QualifierLoc, 
+                                                       AllTemplateArgs);
+    if (!QualifierLoc)
+      return TemplateName();
+  }
+  
+  return SemaRef.SubstTemplateName(QualifierLoc,
+                      Param->getDefaultArgument().getArgument().getAsTemplate(),
+                              Param->getDefaultArgument().getTemplateNameLoc(),
+                                   AllTemplateArgs);
+}
+
+/// \brief If the given template parameter has a default template
+/// argument, substitute into that default template argument and
+/// return the corresponding template argument.
+TemplateArgumentLoc
+Sema::SubstDefaultTemplateArgumentIfAvailable(TemplateDecl *Template,
+                                              SourceLocation TemplateLoc,
+                                              SourceLocation RAngleLoc,
+                                              Decl *Param,
+                      SmallVectorImpl<TemplateArgument> &Converted) {
+   if (TemplateTypeParmDecl *TypeParm = dyn_cast<TemplateTypeParmDecl>(Param)) {
+    if (!TypeParm->hasDefaultArgument())
+      return TemplateArgumentLoc();
+
+    TypeSourceInfo *DI = SubstDefaultTemplateArgument(*this, Template,
+                                                      TemplateLoc,
+                                                      RAngleLoc,
+                                                      TypeParm,
+                                                      Converted);
+    if (DI)
+      return TemplateArgumentLoc(TemplateArgument(DI->getType()), DI);
+
+    return TemplateArgumentLoc();
+  }
+
+  if (NonTypeTemplateParmDecl *NonTypeParm
+        = dyn_cast<NonTypeTemplateParmDecl>(Param)) {
+    if (!NonTypeParm->hasDefaultArgument())
+      return TemplateArgumentLoc();
+
+    ExprResult Arg = SubstDefaultTemplateArgument(*this, Template,
+                                                  TemplateLoc,
+                                                  RAngleLoc,
+                                                  NonTypeParm,
+                                                  Converted);
+    if (Arg.isInvalid())
+      return TemplateArgumentLoc();
+
+    Expr *ArgE = Arg.takeAs<Expr>();
+    return TemplateArgumentLoc(TemplateArgument(ArgE), ArgE);
+  }
+
+  TemplateTemplateParmDecl *TempTempParm
+    = cast<TemplateTemplateParmDecl>(Param);
+  if (!TempTempParm->hasDefaultArgument())
+    return TemplateArgumentLoc();
+
+
+  NestedNameSpecifierLoc QualifierLoc;
+  TemplateName TName = SubstDefaultTemplateArgument(*this, Template,
+                                                    TemplateLoc,
+                                                    RAngleLoc,
+                                                    TempTempParm,
+                                                    Converted,
+                                                    QualifierLoc);
+  if (TName.isNull())
+    return TemplateArgumentLoc();
+
+  return TemplateArgumentLoc(TemplateArgument(TName),
+                TempTempParm->getDefaultArgument().getTemplateQualifierLoc(),
+                TempTempParm->getDefaultArgument().getTemplateNameLoc());
+}
+
+/// \brief Check that the given template argument corresponds to the given
+/// template parameter.
+///
+/// \param Param The template parameter against which the argument will be
+/// checked.
+///
+/// \param Arg The template argument.
+///
+/// \param Template The template in which the template argument resides.
+///
+/// \param TemplateLoc The location of the template name for the template
+/// whose argument list we're matching.
+///
+/// \param RAngleLoc The location of the right angle bracket ('>') that closes
+/// the template argument list.
+///
+/// \param ArgumentPackIndex The index into the argument pack where this
+/// argument will be placed. Only valid if the parameter is a parameter pack.
+///
+/// \param Converted The checked, converted argument will be added to the
+/// end of this small vector.
+///
+/// \param CTAK Describes how we arrived at this particular template argument:
+/// explicitly written, deduced, etc.
+///
+/// \returns true on error, false otherwise.
+bool Sema::CheckTemplateArgument(NamedDecl *Param,
+                                 const TemplateArgumentLoc &Arg,
+                                 NamedDecl *Template,
+                                 SourceLocation TemplateLoc,
+                                 SourceLocation RAngleLoc,
+                                 unsigned ArgumentPackIndex,
+                            SmallVectorImpl<TemplateArgument> &Converted,
+                                 CheckTemplateArgumentKind CTAK) {
+  // Check template type parameters.
+  if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(Param))
+    return CheckTemplateTypeArgument(TTP, Arg, Converted);
+
+  // Check non-type template parameters.
+  if (NonTypeTemplateParmDecl *NTTP =dyn_cast<NonTypeTemplateParmDecl>(Param)) {
+    // Do substitution on the type of the non-type template parameter
+    // with the template arguments we've seen thus far.  But if the
+    // template has a dependent context then we cannot substitute yet.
+    QualType NTTPType = NTTP->getType();
+    if (NTTP->isParameterPack() && NTTP->isExpandedParameterPack())
+      NTTPType = NTTP->getExpansionType(ArgumentPackIndex);
+
+    if (NTTPType->isDependentType() &&
+        !isa<TemplateTemplateParmDecl>(Template) &&
+        !Template->getDeclContext()->isDependentContext()) {
+      // Do substitution on the type of the non-type template parameter.
+      InstantiatingTemplate Inst(*this, TemplateLoc, Template,
+                                 NTTP, Converted.data(), Converted.size(),
+                                 SourceRange(TemplateLoc, RAngleLoc));
+
+      TemplateArgumentList TemplateArgs(TemplateArgumentList::OnStack,
+                                        Converted.data(), Converted.size());
+      NTTPType = SubstType(NTTPType,
+                           MultiLevelTemplateArgumentList(TemplateArgs),
+                           NTTP->getLocation(),
+                           NTTP->getDeclName());
+      // If that worked, check the non-type template parameter type
+      // for validity.
+      if (!NTTPType.isNull())
+        NTTPType = CheckNonTypeTemplateParameterType(NTTPType,
+                                                     NTTP->getLocation());
+      if (NTTPType.isNull())
+        return true;
+    }
+
+    switch (Arg.getArgument().getKind()) {
+    case TemplateArgument::Null:
+      llvm_unreachable("Should never see a NULL template argument here");
+
+    case TemplateArgument::Expression: {
+      TemplateArgument Result;
+      ExprResult Res =
+        CheckTemplateArgument(NTTP, NTTPType, Arg.getArgument().getAsExpr(),
+                              Result, CTAK);
+      if (Res.isInvalid())
+        return true;
+
+      Converted.push_back(Result);
+      break;
+    }
+
+    case TemplateArgument::Declaration:
+    case TemplateArgument::Integral:
+      // We've already checked this template argument, so just copy
+      // it to the list of converted arguments.
+      Converted.push_back(Arg.getArgument());
+      break;
+
+    case TemplateArgument::Template:
+    case TemplateArgument::TemplateExpansion:
+      // We were given a template template argument. It may not be ill-formed;
+      // see below.
+      if (DependentTemplateName *DTN
+            = Arg.getArgument().getAsTemplateOrTemplatePattern()
+                                              .getAsDependentTemplateName()) {
+        // We have a template argument such as \c T::template X, which we
+        // parsed as a template template argument. However, since we now
+        // know that we need a non-type template argument, convert this
+        // template name into an expression.
+
+        DeclarationNameInfo NameInfo(DTN->getIdentifier(),
+                                     Arg.getTemplateNameLoc());
+
+        CXXScopeSpec SS;
+        SS.Adopt(Arg.getTemplateQualifierLoc());
+        // FIXME: the template-template arg was a DependentTemplateName,
+        // so it was provided with a template keyword. However, its source
+        // location is not stored in the template argument structure.
+        SourceLocation TemplateKWLoc;
+        ExprResult E = Owned(DependentScopeDeclRefExpr::Create(Context,
+                                                SS.getWithLocInContext(Context),
+                                                               TemplateKWLoc,
+                                                               NameInfo, 0));
+
+        // If we parsed the template argument as a pack expansion, create a
+        // pack expansion expression.
+        if (Arg.getArgument().getKind() == TemplateArgument::TemplateExpansion){
+          E = ActOnPackExpansion(E.take(), Arg.getTemplateEllipsisLoc());
+          if (E.isInvalid())
+            return true;
+        }
+
+        TemplateArgument Result;
+        E = CheckTemplateArgument(NTTP, NTTPType, E.take(), Result);
+        if (E.isInvalid())
+          return true;
+
+        Converted.push_back(Result);
+        break;
+      }
+
+      // We have a template argument that actually does refer to a class
+      // template, alias template, or template template parameter, and
+      // therefore cannot be a non-type template argument.
+      Diag(Arg.getLocation(), diag::err_template_arg_must_be_expr)
+        << Arg.getSourceRange();
+
+      Diag(Param->getLocation(), diag::note_template_param_here);
+      return true;
+
+    case TemplateArgument::Type: {
+      // We have a non-type template parameter but the template
+      // argument is a type.
+
+      // C++ [temp.arg]p2:
+      //   In a template-argument, an ambiguity between a type-id and
+      //   an expression is resolved to a type-id, regardless of the
+      //   form of the corresponding template-parameter.
+      //
+      // We warn specifically about this case, since it can be rather
+      // confusing for users.
+      QualType T = Arg.getArgument().getAsType();
+      SourceRange SR = Arg.getSourceRange();
+      if (T->isFunctionType())
+        Diag(SR.getBegin(), diag::err_template_arg_nontype_ambig) << SR << T;
+      else
+        Diag(SR.getBegin(), diag::err_template_arg_must_be_expr) << SR;
+      Diag(Param->getLocation(), diag::note_template_param_here);
+      return true;
+    }
+
+    case TemplateArgument::Pack:
+      llvm_unreachable("Caller must expand template argument packs");
+    }
+
+    return false;
+  }
+
+
+  // Check template template parameters.
+  TemplateTemplateParmDecl *TempParm = cast<TemplateTemplateParmDecl>(Param);
+
+  // Substitute into the template parameter list of the template
+  // template parameter, since previously-supplied template arguments
+  // may appear within the template template parameter.
+  {
+    // Set up a template instantiation context.
+    LocalInstantiationScope Scope(*this);
+    InstantiatingTemplate Inst(*this, TemplateLoc, Template,
+                               TempParm, Converted.data(), Converted.size(),
+                               SourceRange(TemplateLoc, RAngleLoc));
+
+    TemplateArgumentList TemplateArgs(TemplateArgumentList::OnStack,
+                                      Converted.data(), Converted.size());
+    TempParm = cast_or_null<TemplateTemplateParmDecl>(
+                      SubstDecl(TempParm, CurContext,
+                                MultiLevelTemplateArgumentList(TemplateArgs)));
+    if (!TempParm)
+      return true;
+  }
+
+  switch (Arg.getArgument().getKind()) {
+  case TemplateArgument::Null:
+    llvm_unreachable("Should never see a NULL template argument here");
+
+  case TemplateArgument::Template:
+  case TemplateArgument::TemplateExpansion:
+    if (CheckTemplateArgument(TempParm, Arg))
+      return true;
+
+    Converted.push_back(Arg.getArgument());
+    break;
+
+  case TemplateArgument::Expression:
+  case TemplateArgument::Type:
+    // We have a template template parameter but the template
+    // argument does not refer to a template.
+    Diag(Arg.getLocation(), diag::err_template_arg_must_be_template)
+      << getLangOpts().CPlusPlus0x;
+    return true;
+
+  case TemplateArgument::Declaration:
+    llvm_unreachable("Declaration argument with template template parameter");
+  case TemplateArgument::Integral:
+    llvm_unreachable("Integral argument with template template parameter");
+
+  case TemplateArgument::Pack:
+    llvm_unreachable("Caller must expand template argument packs");
+  }
+
+  return false;
+}
+
+/// \brief Diagnose an arity mismatch in the 
+static bool diagnoseArityMismatch(Sema &S, TemplateDecl *Template,
+                                  SourceLocation TemplateLoc,
+                                  TemplateArgumentListInfo &TemplateArgs) {
+  TemplateParameterList *Params = Template->getTemplateParameters();
+  unsigned NumParams = Params->size();
+  unsigned NumArgs = TemplateArgs.size();
+
+  SourceRange Range;
+  if (NumArgs > NumParams)
+    Range = SourceRange(TemplateArgs[NumParams].getLocation(), 
+                        TemplateArgs.getRAngleLoc());
+  S.Diag(TemplateLoc, diag::err_template_arg_list_different_arity)
+    << (NumArgs > NumParams)
+    << (isa<ClassTemplateDecl>(Template)? 0 :
+        isa<FunctionTemplateDecl>(Template)? 1 :
+        isa<TemplateTemplateParmDecl>(Template)? 2 : 3)
+    << Template << Range;
+  S.Diag(Template->getLocation(), diag::note_template_decl_here)
+    << Params->getSourceRange();
+  return true;
+}
+
+/// \brief Check that the given template argument list is well-formed
+/// for specializing the given template.
+bool Sema::CheckTemplateArgumentList(TemplateDecl *Template,
+                                     SourceLocation TemplateLoc,
+                                     TemplateArgumentListInfo &TemplateArgs,
+                                     bool PartialTemplateArgs,
+                          SmallVectorImpl<TemplateArgument> &Converted,
+                                     bool *ExpansionIntoFixedList) {
+  if (ExpansionIntoFixedList)
+    *ExpansionIntoFixedList = false;
+
+  TemplateParameterList *Params = Template->getTemplateParameters();
+  unsigned NumParams = Params->size();
+  unsigned NumArgs = TemplateArgs.size();
+  bool Invalid = false;
+
+  SourceLocation RAngleLoc = TemplateArgs.getRAngleLoc();
+
+  bool HasParameterPack =
+    NumParams > 0 && Params->getParam(NumParams - 1)->isTemplateParameterPack();
+  
+  // C++ [temp.arg]p1:
+  //   [...] The type and form of each template-argument specified in
+  //   a template-id shall match the type and form specified for the
+  //   corresponding parameter declared by the template in its
+  //   template-parameter-list.
+  bool isTemplateTemplateParameter = isa<TemplateTemplateParmDecl>(Template);
+  SmallVector<TemplateArgument, 2> ArgumentPack;
+  TemplateParameterList::iterator Param = Params->begin(),
+                               ParamEnd = Params->end();
+  unsigned ArgIdx = 0;
+  LocalInstantiationScope InstScope(*this, true);
+  bool SawPackExpansion = false;
+  while (Param != ParamEnd) {
+    if (ArgIdx < NumArgs) {
+      // If we have an expanded parameter pack, make sure we don't have too
+      // many arguments.
+      // FIXME: This really should fall out from the normal arity checking.
+      if (NonTypeTemplateParmDecl *NTTP
+                                = dyn_cast<NonTypeTemplateParmDecl>(*Param)) {
+        if (NTTP->isExpandedParameterPack() &&
+            ArgumentPack.size() >= NTTP->getNumExpansionTypes()) {
+          Diag(TemplateLoc, diag::err_template_arg_list_different_arity)
+            << true
+            << (isa<ClassTemplateDecl>(Template)? 0 :
+                isa<FunctionTemplateDecl>(Template)? 1 :
+                isa<TemplateTemplateParmDecl>(Template)? 2 : 3)
+            << Template;
+          Diag(Template->getLocation(), diag::note_template_decl_here)
+            << Params->getSourceRange();
+          return true;
+        }
+      }
+
+      // Check the template argument we were given.
+      if (CheckTemplateArgument(*Param, TemplateArgs[ArgIdx], Template,
+                                TemplateLoc, RAngleLoc,
+                                ArgumentPack.size(), Converted))
+        return true;
+
+      if ((*Param)->isTemplateParameterPack()) {
+        // The template parameter was a template parameter pack, so take the
+        // deduced argument and place it on the argument pack. Note that we
+        // stay on the same template parameter so that we can deduce more
+        // arguments.
+        ArgumentPack.push_back(Converted.back());
+        Converted.pop_back();
+      } else {
+        // Move to the next template parameter.
+        ++Param;
+      }
+      
+      // If this template argument is a pack expansion, record that fact
+      // and break out; we can't actually check any more.
+      if (TemplateArgs[ArgIdx].getArgument().isPackExpansion()) {
+        SawPackExpansion = true;
+        ++ArgIdx;
+        break;
+      }
+      
+      ++ArgIdx;
+      continue;
+    }
+
+    // If we're checking a partial template argument list, we're done.
+    if (PartialTemplateArgs) {
+      if ((*Param)->isTemplateParameterPack() && !ArgumentPack.empty())
+        Converted.push_back(TemplateArgument::CreatePackCopy(Context,
+                                                         ArgumentPack.data(),
+                                                         ArgumentPack.size()));
+        
+      return Invalid;
+    }
+
+    // If we have a template parameter pack with no more corresponding
+    // arguments, just break out now and we'll fill in the argument pack below.
+    if ((*Param)->isTemplateParameterPack())
+      break;
+    
+    // Check whether we have a default argument.
+    TemplateArgumentLoc Arg;
+
+    // Retrieve the default template argument from the template
+    // parameter. For each kind of template parameter, we substitute the
+    // template arguments provided thus far and any "outer" template arguments
+    // (when the template parameter was part of a nested template) into
+    // the default argument.
+    if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(*Param)) {
+      if (!TTP->hasDefaultArgument())
+        return diagnoseArityMismatch(*this, Template, TemplateLoc, 
+                                     TemplateArgs);
+
+      TypeSourceInfo *ArgType = SubstDefaultTemplateArgument(*this,
+                                                             Template,
+                                                             TemplateLoc,
+                                                             RAngleLoc,
+                                                             TTP,
+                                                             Converted);
+      if (!ArgType)
+        return true;
+
+      Arg = TemplateArgumentLoc(TemplateArgument(ArgType->getType()),
+                                ArgType);
+    } else if (NonTypeTemplateParmDecl *NTTP
+                 = dyn_cast<NonTypeTemplateParmDecl>(*Param)) {
+      if (!NTTP->hasDefaultArgument())
+        return diagnoseArityMismatch(*this, Template, TemplateLoc, 
+                                     TemplateArgs);
+
+      ExprResult E = SubstDefaultTemplateArgument(*this, Template,
+                                                              TemplateLoc,
+                                                              RAngleLoc,
+                                                              NTTP,
+                                                              Converted);
+      if (E.isInvalid())
+        return true;
+
+      Expr *Ex = E.takeAs<Expr>();
+      Arg = TemplateArgumentLoc(TemplateArgument(Ex), Ex);
+    } else {
+      TemplateTemplateParmDecl *TempParm
+        = cast<TemplateTemplateParmDecl>(*Param);
+
+      if (!TempParm->hasDefaultArgument())
+        return diagnoseArityMismatch(*this, Template, TemplateLoc, 
+                                     TemplateArgs);
+
+      NestedNameSpecifierLoc QualifierLoc;
+      TemplateName Name = SubstDefaultTemplateArgument(*this, Template,
+                                                       TemplateLoc,
+                                                       RAngleLoc,
+                                                       TempParm,
+                                                       Converted,
+                                                       QualifierLoc);
+      if (Name.isNull())
+        return true;
+
+      Arg = TemplateArgumentLoc(TemplateArgument(Name), QualifierLoc,
+                           TempParm->getDefaultArgument().getTemplateNameLoc());
+    }
+
+    // Introduce an instantiation record that describes where we are using
+    // the default template argument.
+    InstantiatingTemplate Instantiating(*this, RAngleLoc, Template, *Param,
+                                        Converted.data(), Converted.size(),
+                                        SourceRange(TemplateLoc, RAngleLoc));
+
+    // Check the default template argument.
+    if (CheckTemplateArgument(*Param, Arg, Template, TemplateLoc,
+                              RAngleLoc, 0, Converted))
+      return true;
+
+    // Core issue 150 (assumed resolution): if this is a template template 
+    // parameter, keep track of the default template arguments from the 
+    // template definition.
+    if (isTemplateTemplateParameter)
+      TemplateArgs.addArgument(Arg);
+    
+    // Move to the next template parameter and argument.
+    ++Param;
+    ++ArgIdx;
+  }
+
+  // If we saw a pack expansion, then directly convert the remaining arguments,
+  // because we don't know what parameters they'll match up with.
+  if (SawPackExpansion) {
+    bool AddToArgumentPack
+      = Param != ParamEnd && (*Param)->isTemplateParameterPack();
+    while (ArgIdx < NumArgs) {
+      if (AddToArgumentPack)
+        ArgumentPack.push_back(TemplateArgs[ArgIdx].getArgument());
+      else
+        Converted.push_back(TemplateArgs[ArgIdx].getArgument());
+      ++ArgIdx;
+    }
+
+    // Push the argument pack onto the list of converted arguments.
+    if (AddToArgumentPack) {
+      if (ArgumentPack.empty())
+        Converted.push_back(TemplateArgument(0, 0));
+      else {
+        Converted.push_back(
+          TemplateArgument::CreatePackCopy(Context,
+                                           ArgumentPack.data(),
+                                           ArgumentPack.size()));
+        ArgumentPack.clear();
+      }      
+    } else if (ExpansionIntoFixedList) {
+      // We have expanded a pack into a fixed list.
+      *ExpansionIntoFixedList = true;
+    }
+
+    return Invalid;
+  }
+
+  // If we have any leftover arguments, then there were too many arguments.
+  // Complain and fail.
+  if (ArgIdx < NumArgs)
+    return diagnoseArityMismatch(*this, Template, TemplateLoc, TemplateArgs);
+  
+  // If we have an expanded parameter pack, make sure we don't have too
+  // many arguments.
+  // FIXME: This really should fall out from the normal arity checking.
+  if (Param != ParamEnd) {
+    if (NonTypeTemplateParmDecl *NTTP
+          = dyn_cast<NonTypeTemplateParmDecl>(*Param)) {
+      if (NTTP->isExpandedParameterPack() &&
+          ArgumentPack.size() < NTTP->getNumExpansionTypes()) {
+        Diag(TemplateLoc, diag::err_template_arg_list_different_arity)
+          << false
+          << (isa<ClassTemplateDecl>(Template)? 0 :
+              isa<FunctionTemplateDecl>(Template)? 1 :
+              isa<TemplateTemplateParmDecl>(Template)? 2 : 3)
+          << Template;
+        Diag(Template->getLocation(), diag::note_template_decl_here)
+          << Params->getSourceRange();
+        return true;
+      }
+    }
+  }
+  
+  // Form argument packs for each of the parameter packs remaining.
+  while (Param != ParamEnd) {
+    // If we're checking a partial list of template arguments, don't fill
+    // in arguments for non-template parameter packs.
+    if ((*Param)->isTemplateParameterPack()) {
+      if (!HasParameterPack)
+        return true;
+      if (ArgumentPack.empty())
+        Converted.push_back(TemplateArgument(0, 0));
+      else {
+        Converted.push_back(TemplateArgument::CreatePackCopy(Context,
+                                                          ArgumentPack.data(),
+                                                         ArgumentPack.size()));
+        ArgumentPack.clear();
+      }
+    } else if (!PartialTemplateArgs)
+      return diagnoseArityMismatch(*this, Template, TemplateLoc, TemplateArgs);
+
+    ++Param;
+  }
+
+  return Invalid;
+}
+
+namespace {
+  class UnnamedLocalNoLinkageFinder
+    : public TypeVisitor<UnnamedLocalNoLinkageFinder, bool>
+  {
+    Sema &S;
+    SourceRange SR;
+
+    typedef TypeVisitor<UnnamedLocalNoLinkageFinder, bool> inherited;
+
+  public:
+    UnnamedLocalNoLinkageFinder(Sema &S, SourceRange SR) : S(S), SR(SR) { }
+
+    bool Visit(QualType T) {
+      return inherited::Visit(T.getTypePtr());
+    }
+
+#define TYPE(Class, Parent) \
+    bool Visit##Class##Type(const Class##Type *);
+#define ABSTRACT_TYPE(Class, Parent) \
+    bool Visit##Class##Type(const Class##Type *) { return false; }
+#define NON_CANONICAL_TYPE(Class, Parent) \
+    bool Visit##Class##Type(const Class##Type *) { return false; }
+#include "clang/AST/TypeNodes.def"
+
+    bool VisitTagDecl(const TagDecl *Tag);
+    bool VisitNestedNameSpecifier(NestedNameSpecifier *NNS);
+  };
+}
+
+bool UnnamedLocalNoLinkageFinder::VisitBuiltinType(const BuiltinType*) {
+  return false;
+}
+
+bool UnnamedLocalNoLinkageFinder::VisitComplexType(const ComplexType* T) {
+  return Visit(T->getElementType());
+}
+
+bool UnnamedLocalNoLinkageFinder::VisitPointerType(const PointerType* T) {
+  return Visit(T->getPointeeType());
+}
+
+bool UnnamedLocalNoLinkageFinder::VisitBlockPointerType(
+                                                    const BlockPointerType* T) {
+  return Visit(T->getPointeeType());
+}
+
+bool UnnamedLocalNoLinkageFinder::VisitLValueReferenceType(
+                                                const LValueReferenceType* T) {
+  return Visit(T->getPointeeType());
+}
+
+bool UnnamedLocalNoLinkageFinder::VisitRValueReferenceType(
+                                                const RValueReferenceType* T) {
+  return Visit(T->getPointeeType());
+}
+
+bool UnnamedLocalNoLinkageFinder::VisitMemberPointerType(
+                                                  const MemberPointerType* T) {
+  return Visit(T->getPointeeType()) || Visit(QualType(T->getClass(), 0));
+}
+
+bool UnnamedLocalNoLinkageFinder::VisitConstantArrayType(
+                                                  const ConstantArrayType* T) {
+  return Visit(T->getElementType());
+}
+
+bool UnnamedLocalNoLinkageFinder::VisitIncompleteArrayType(
+                                                 const IncompleteArrayType* T) {
+  return Visit(T->getElementType());
+}
+
+bool UnnamedLocalNoLinkageFinder::VisitVariableArrayType(
+                                                   const VariableArrayType* T) {
+  return Visit(T->getElementType());
+}
+
+bool UnnamedLocalNoLinkageFinder::VisitDependentSizedArrayType(
+                                            const DependentSizedArrayType* T) {
+  return Visit(T->getElementType());
+}
+
+bool UnnamedLocalNoLinkageFinder::VisitDependentSizedExtVectorType(
+                                         const DependentSizedExtVectorType* T) {
+  return Visit(T->getElementType());
+}
+
+bool UnnamedLocalNoLinkageFinder::VisitVectorType(const VectorType* T) {
+  return Visit(T->getElementType());
+}
+
+bool UnnamedLocalNoLinkageFinder::VisitExtVectorType(const ExtVectorType* T) {
+  return Visit(T->getElementType());
+}
+
+bool UnnamedLocalNoLinkageFinder::VisitFunctionProtoType(
+                                                  const FunctionProtoType* T) {
+  for (FunctionProtoType::arg_type_iterator A = T->arg_type_begin(),
+                                         AEnd = T->arg_type_end();
+       A != AEnd; ++A) {
+    if (Visit(*A))
+      return true;
+  }
+
+  return Visit(T->getResultType());
+}
+
+bool UnnamedLocalNoLinkageFinder::VisitFunctionNoProtoType(
+                                               const FunctionNoProtoType* T) {
+  return Visit(T->getResultType());
+}
+
+bool UnnamedLocalNoLinkageFinder::VisitUnresolvedUsingType(
+                                                  const UnresolvedUsingType*) {
+  return false;
+}
+
+bool UnnamedLocalNoLinkageFinder::VisitTypeOfExprType(const TypeOfExprType*) {
+  return false;
+}
+
+bool UnnamedLocalNoLinkageFinder::VisitTypeOfType(const TypeOfType* T) {
+  return Visit(T->getUnderlyingType());
+}
+
+bool UnnamedLocalNoLinkageFinder::VisitDecltypeType(const DecltypeType*) {
+  return false;
+}
+
+bool UnnamedLocalNoLinkageFinder::VisitUnaryTransformType(
+                                                    const UnaryTransformType*) {
+  return false;
+}
+
+bool UnnamedLocalNoLinkageFinder::VisitAutoType(const AutoType *T) {
+  return Visit(T->getDeducedType());
+}
+
+bool UnnamedLocalNoLinkageFinder::VisitRecordType(const RecordType* T) {
+  return VisitTagDecl(T->getDecl());
+}
+
+bool UnnamedLocalNoLinkageFinder::VisitEnumType(const EnumType* T) {
+  return VisitTagDecl(T->getDecl());
+}
+
+bool UnnamedLocalNoLinkageFinder::VisitTemplateTypeParmType(
+                                                 const TemplateTypeParmType*) {
+  return false;
+}
+
+bool UnnamedLocalNoLinkageFinder::VisitSubstTemplateTypeParmPackType(
+                                        const SubstTemplateTypeParmPackType *) {
+  return false;
+}
+
+bool UnnamedLocalNoLinkageFinder::VisitTemplateSpecializationType(
+                                            const TemplateSpecializationType*) {
+  return false;
+}
+
+bool UnnamedLocalNoLinkageFinder::VisitInjectedClassNameType(
+                                              const InjectedClassNameType* T) {
+  return VisitTagDecl(T->getDecl());
+}
+
+bool UnnamedLocalNoLinkageFinder::VisitDependentNameType(
+                                                   const DependentNameType* T) {
+  return VisitNestedNameSpecifier(T->getQualifier());
+}
+
+bool UnnamedLocalNoLinkageFinder::VisitDependentTemplateSpecializationType(
+                                 const DependentTemplateSpecializationType* T) {
+  return VisitNestedNameSpecifier(T->getQualifier());
+}
+
+bool UnnamedLocalNoLinkageFinder::VisitPackExpansionType(
+                                                   const PackExpansionType* T) {
+  return Visit(T->getPattern());
+}
+
+bool UnnamedLocalNoLinkageFinder::VisitObjCObjectType(const ObjCObjectType *) {
+  return false;
+}
+
+bool UnnamedLocalNoLinkageFinder::VisitObjCInterfaceType(
+                                                   const ObjCInterfaceType *) {
+  return false;
+}
+
+bool UnnamedLocalNoLinkageFinder::VisitObjCObjectPointerType(
+                                                const ObjCObjectPointerType *) {
+  return false;
+}
+
+bool UnnamedLocalNoLinkageFinder::VisitAtomicType(const AtomicType* T) {
+  return Visit(T->getValueType());
+}
+
+bool UnnamedLocalNoLinkageFinder::VisitTagDecl(const TagDecl *Tag) {
+  if (Tag->getDeclContext()->isFunctionOrMethod()) {
+    S.Diag(SR.getBegin(),
+           S.getLangOpts().CPlusPlus0x ?
+             diag::warn_cxx98_compat_template_arg_local_type :
+             diag::ext_template_arg_local_type)
+      << S.Context.getTypeDeclType(Tag) << SR;
+    return true;
+  }
+
+  if (!Tag->getDeclName() && !Tag->getTypedefNameForAnonDecl()) {
+    S.Diag(SR.getBegin(),
+           S.getLangOpts().CPlusPlus0x ?
+             diag::warn_cxx98_compat_template_arg_unnamed_type :
+             diag::ext_template_arg_unnamed_type) << SR;
+    S.Diag(Tag->getLocation(), diag::note_template_unnamed_type_here);
+    return true;
+  }
+
+  return false;
+}
+
+bool UnnamedLocalNoLinkageFinder::VisitNestedNameSpecifier(
+                                                    NestedNameSpecifier *NNS) {
+  if (NNS->getPrefix() && VisitNestedNameSpecifier(NNS->getPrefix()))
+    return true;
+
+  switch (NNS->getKind()) {
+  case NestedNameSpecifier::Identifier:
+  case NestedNameSpecifier::Namespace:
+  case NestedNameSpecifier::NamespaceAlias:
+  case NestedNameSpecifier::Global:
+    return false;
+
+  case NestedNameSpecifier::TypeSpec:
+  case NestedNameSpecifier::TypeSpecWithTemplate:
+    return Visit(QualType(NNS->getAsType(), 0));
+  }
+  llvm_unreachable("Invalid NestedNameSpecifier::Kind!");
+}
+
+
+/// \brief Check a template argument against its corresponding
+/// template type parameter.
+///
+/// This routine implements the semantics of C++ [temp.arg.type]. It
+/// returns true if an error occurred, and false otherwise.
+bool Sema::CheckTemplateArgument(TemplateTypeParmDecl *Param,
+                                 TypeSourceInfo *ArgInfo) {
+  assert(ArgInfo && "invalid TypeSourceInfo");
+  QualType Arg = ArgInfo->getType();
+  SourceRange SR = ArgInfo->getTypeLoc().getSourceRange();
+
+  if (Arg->isVariablyModifiedType()) {
+    return Diag(SR.getBegin(), diag::err_variably_modified_template_arg) << Arg;
+  } else if (Context.hasSameUnqualifiedType(Arg, Context.OverloadTy)) {
+    return Diag(SR.getBegin(), diag::err_template_arg_overload_type) << SR;
+  }
+
+  // C++03 [temp.arg.type]p2:
+  //   A local type, a type with no linkage, an unnamed type or a type
+  //   compounded from any of these types shall not be used as a
+  //   template-argument for a template type-parameter.
+  //
+  // C++11 allows these, and even in C++03 we allow them as an extension with
+  // a warning.
+  if (LangOpts.CPlusPlus0x ?
+     Diags.getDiagnosticLevel(diag::warn_cxx98_compat_template_arg_unnamed_type,
+                              SR.getBegin()) != DiagnosticsEngine::Ignored ||
+      Diags.getDiagnosticLevel(diag::warn_cxx98_compat_template_arg_local_type,
+                               SR.getBegin()) != DiagnosticsEngine::Ignored :
+      Arg->hasUnnamedOrLocalType()) {
+    UnnamedLocalNoLinkageFinder Finder(*this, SR);
+    (void)Finder.Visit(Context.getCanonicalType(Arg));
+  }
+
+  return false;
+}
+
+enum NullPointerValueKind {
+  NPV_NotNullPointer,
+  NPV_NullPointer,
+  NPV_Error
+};
+
+/// \brief Determine whether the given template argument is a null pointer
+/// value of the appropriate type.
+static NullPointerValueKind
+isNullPointerValueTemplateArgument(Sema &S, NonTypeTemplateParmDecl *Param,
+                                   QualType ParamType, Expr *Arg) {
+  if (Arg->isValueDependent() || Arg->isTypeDependent())
+    return NPV_NotNullPointer;
+  
+  if (!S.getLangOpts().CPlusPlus0x)
+    return NPV_NotNullPointer;
+  
+  // Determine whether we have a constant expression.
+  ExprResult ArgRV = S.DefaultFunctionArrayConversion(Arg);
+  if (ArgRV.isInvalid())
+    return NPV_Error;
+  Arg = ArgRV.take();
+  
+  Expr::EvalResult EvalResult;
+  llvm::SmallVector<PartialDiagnosticAt, 8> Notes;
+  EvalResult.Diag = &Notes;
+  if (!Arg->EvaluateAsRValue(EvalResult, S.Context) ||
+      EvalResult.HasSideEffects) {
+    SourceLocation DiagLoc = Arg->getExprLoc();
+    
+    // If our only note is the usual "invalid subexpression" note, just point
+    // the caret at its location rather than producing an essentially
+    // redundant note.
+    if (Notes.size() == 1 && Notes[0].second.getDiagID() ==
+        diag::note_invalid_subexpr_in_const_expr) {
+      DiagLoc = Notes[0].first;
+      Notes.clear();
+    }
+    
+    S.Diag(DiagLoc, diag::err_template_arg_not_address_constant)
+      << Arg->getType() << Arg->getSourceRange();
+    for (unsigned I = 0, N = Notes.size(); I != N; ++I)
+      S.Diag(Notes[I].first, Notes[I].second);
+    
+    S.Diag(Param->getLocation(), diag::note_template_param_here);
+    return NPV_Error;
+  }
+  
+  // C++11 [temp.arg.nontype]p1:
+  //   - an address constant expression of type std::nullptr_t
+  if (Arg->getType()->isNullPtrType())
+    return NPV_NullPointer;
+  
+  //   - a constant expression that evaluates to a null pointer value (4.10); or
+  //   - a constant expression that evaluates to a null member pointer value
+  //     (4.11); or
+  if ((EvalResult.Val.isLValue() && !EvalResult.Val.getLValueBase()) ||
+      (EvalResult.Val.isMemberPointer() &&
+       !EvalResult.Val.getMemberPointerDecl())) {
+    // If our expression has an appropriate type, we've succeeded.
+    bool ObjCLifetimeConversion;
+    if (S.Context.hasSameUnqualifiedType(Arg->getType(), ParamType) ||
+        S.IsQualificationConversion(Arg->getType(), ParamType, false,
+                                     ObjCLifetimeConversion))
+      return NPV_NullPointer;
+    
+    // The types didn't match, but we know we got a null pointer; complain,
+    // then recover as if the types were correct.
+    S.Diag(Arg->getExprLoc(), diag::err_template_arg_wrongtype_null_constant)
+      << Arg->getType() << ParamType << Arg->getSourceRange();
+    S.Diag(Param->getLocation(), diag::note_template_param_here);
+    return NPV_NullPointer;
+  }
+
+  // If we don't have a null pointer value, but we do have a NULL pointer
+  // constant, suggest a cast to the appropriate type.
+  if (Arg->isNullPointerConstant(S.Context, Expr::NPC_NeverValueDependent)) {
+    std::string Code = "static_cast<" + ParamType.getAsString() + ">(";
+    S.Diag(Arg->getExprLoc(), diag::err_template_arg_untyped_null_constant)
+      << ParamType
+      << FixItHint::CreateInsertion(Arg->getLocStart(), Code)
+      << FixItHint::CreateInsertion(S.PP.getLocForEndOfToken(Arg->getLocEnd()),
+                                    ")");
+    S.Diag(Param->getLocation(), diag::note_template_param_here);
+    return NPV_NullPointer;
+  }
+  
+  // FIXME: If we ever want to support general, address-constant expressions
+  // as non-type template arguments, we should return the ExprResult here to
+  // be interpreted by the caller.
+  return NPV_NotNullPointer;
+}
+
+/// \brief Checks whether the given template argument is the address
+/// of an object or function according to C++ [temp.arg.nontype]p1.
+static bool
+CheckTemplateArgumentAddressOfObjectOrFunction(Sema &S,
+                                               NonTypeTemplateParmDecl *Param,
+                                               QualType ParamType,
+                                               Expr *ArgIn,
+                                               TemplateArgument &Converted) {
+  bool Invalid = false;
+  Expr *Arg = ArgIn;
+  QualType ArgType = Arg->getType();
+
+  // If our parameter has pointer type, check for a null template value.
+  if (ParamType->isPointerType() || ParamType->isNullPtrType()) {
+    switch (isNullPointerValueTemplateArgument(S, Param, ParamType, Arg)) {
+    case NPV_NullPointer:
+      Converted = TemplateArgument((Decl *)0);
+      return false;
+
+    case NPV_Error:
+      return true;
+        
+    case NPV_NotNullPointer:
+      break;
+    }
+  }
+  
+  // See through any implicit casts we added to fix the type.
+  Arg = Arg->IgnoreImpCasts();
+
+  // C++ [temp.arg.nontype]p1:
+  //
+  //   A template-argument for a non-type, non-template
+  //   template-parameter shall be one of: [...]
+  //
+  //     -- the address of an object or function with external
+  //        linkage, including function templates and function
+  //        template-ids but excluding non-static class members,
+  //        expressed as & id-expression where the & is optional if
+  //        the name refers to a function or array, or if the
+  //        corresponding template-parameter is a reference; or
+
+  // In C++98/03 mode, give an extension warning on any extra parentheses.
+  // See http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#773
+  bool ExtraParens = false;
+  while (ParenExpr *Parens = dyn_cast<ParenExpr>(Arg)) {
+    if (!Invalid && !ExtraParens) {
+      S.Diag(Arg->getLocStart(),
+             S.getLangOpts().CPlusPlus0x ?
+               diag::warn_cxx98_compat_template_arg_extra_parens :
+               diag::ext_template_arg_extra_parens)
+        << Arg->getSourceRange();
+      ExtraParens = true;
+    }
+
+    Arg = Parens->getSubExpr();
+  }
+
+  while (SubstNonTypeTemplateParmExpr *subst =
+           dyn_cast<SubstNonTypeTemplateParmExpr>(Arg))
+    Arg = subst->getReplacement()->IgnoreImpCasts();
+
+  bool AddressTaken = false;
+  SourceLocation AddrOpLoc;
+  if (UnaryOperator *UnOp = dyn_cast<UnaryOperator>(Arg)) {
+    if (UnOp->getOpcode() == UO_AddrOf) {
+      Arg = UnOp->getSubExpr();
+      AddressTaken = true;
+      AddrOpLoc = UnOp->getOperatorLoc();
+    }
+  }
+
+  if (S.getLangOpts().MicrosoftExt && isa<CXXUuidofExpr>(Arg)) {
+    Converted = TemplateArgument(ArgIn);
+    return false;
+  }
+
+  while (SubstNonTypeTemplateParmExpr *subst =
+           dyn_cast<SubstNonTypeTemplateParmExpr>(Arg))
+    Arg = subst->getReplacement()->IgnoreImpCasts();
+
+  // Stop checking the precise nature of the argument if it is value dependent,
+  // it should be checked when instantiated.
+  if (Arg->isValueDependent()) {
+    Converted = TemplateArgument(ArgIn);
+    return false;
+  }
+  
+  DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(Arg);
+  if (!DRE) {
+    S.Diag(Arg->getLocStart(), diag::err_template_arg_not_decl_ref)
+    << Arg->getSourceRange();
+    S.Diag(Param->getLocation(), diag::note_template_param_here);
+    return true;
+  }
+
+  if (!isa<ValueDecl>(DRE->getDecl())) {
+    S.Diag(Arg->getLocStart(),
+           diag::err_template_arg_not_object_or_func_form)
+      << Arg->getSourceRange();
+    S.Diag(Param->getLocation(), diag::note_template_param_here);
+    return true;
+  }
+
+  NamedDecl *Entity = DRE->getDecl();
+
+  // Cannot refer to non-static data members
+  if (FieldDecl *Field = dyn_cast<FieldDecl>(Entity)) {
+    S.Diag(Arg->getLocStart(), diag::err_template_arg_field)
+      << Field << Arg->getSourceRange();
+    S.Diag(Param->getLocation(), diag::note_template_param_here);
+    return true;
+  }
+
+  // Cannot refer to non-static member functions
+  if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(Entity)) {
+    if (!Method->isStatic()) {
+      S.Diag(Arg->getLocStart(), diag::err_template_arg_method)
+        << Method << Arg->getSourceRange();
+      S.Diag(Param->getLocation(), diag::note_template_param_here);
+      return true;
+    }
+  }
+
+  FunctionDecl *Func = dyn_cast<FunctionDecl>(Entity);
+  VarDecl *Var = dyn_cast<VarDecl>(Entity);
+
+  // A non-type template argument must refer to an object or function.
+  if (!Func && !Var) {
+    // We found something, but we don't know specifically what it is.
+    S.Diag(Arg->getLocStart(), diag::err_template_arg_not_object_or_func)
+      << Arg->getSourceRange();
+    S.Diag(DRE->getDecl()->getLocation(), diag::note_template_arg_refers_here);
+    return true;
+  }
+
+  // Address / reference template args must have external linkage in C++98.
+  if (Entity->getLinkage() == InternalLinkage) {
+    S.Diag(Arg->getLocStart(), S.getLangOpts().CPlusPlus0x ?
+             diag::warn_cxx98_compat_template_arg_object_internal :
+             diag::ext_template_arg_object_internal)
+      << !Func << Entity << Arg->getSourceRange();
+    S.Diag(Entity->getLocation(), diag::note_template_arg_internal_object)
+      << !Func;
+  } else if (Entity->getLinkage() == NoLinkage) {
+    S.Diag(Arg->getLocStart(), diag::err_template_arg_object_no_linkage)
+      << !Func << Entity << Arg->getSourceRange();
+    S.Diag(Entity->getLocation(), diag::note_template_arg_internal_object)
+      << !Func;
+    return true;
+  }
+
+  if (Func) {
+    // If the template parameter has pointer type, the function decays.
+    if (ParamType->isPointerType() && !AddressTaken)
+      ArgType = S.Context.getPointerType(Func->getType());
+    else if (AddressTaken && ParamType->isReferenceType()) {
+      // If we originally had an address-of operator, but the
+      // parameter has reference type, complain and (if things look
+      // like they will work) drop the address-of operator.
+      if (!S.Context.hasSameUnqualifiedType(Func->getType(),
+                                            ParamType.getNonReferenceType())) {
+        S.Diag(AddrOpLoc, diag::err_template_arg_address_of_non_pointer)
+          << ParamType;
+        S.Diag(Param->getLocation(), diag::note_template_param_here);
+        return true;
+      }
+
+      S.Diag(AddrOpLoc, diag::err_template_arg_address_of_non_pointer)
+        << ParamType
+        << FixItHint::CreateRemoval(AddrOpLoc);
+      S.Diag(Param->getLocation(), diag::note_template_param_here);
+
+      ArgType = Func->getType();
+    }
+  } else {
+    // A value of reference type is not an object.
+    if (Var->getType()->isReferenceType()) {
+      S.Diag(Arg->getLocStart(),
+             diag::err_template_arg_reference_var)
+        << Var->getType() << Arg->getSourceRange();
+      S.Diag(Param->getLocation(), diag::note_template_param_here);
+      return true;
+    }
+
+    // A template argument must have static storage duration.
+    // FIXME: Ensure this works for thread_local as well as __thread.
+    if (Var->isThreadSpecified()) {
+      S.Diag(Arg->getLocStart(), diag::err_template_arg_thread_local)
+        << Arg->getSourceRange();
+      S.Diag(Var->getLocation(), diag::note_template_arg_refers_here);
+      return true;
+    }
+
+    // If the template parameter has pointer type, we must have taken
+    // the address of this object.
+    if (ParamType->isReferenceType()) {
+      if (AddressTaken) {
+        // If we originally had an address-of operator, but the
+        // parameter has reference type, complain and (if things look
+        // like they will work) drop the address-of operator.
+        if (!S.Context.hasSameUnqualifiedType(Var->getType(),
+                                            ParamType.getNonReferenceType())) {
+          S.Diag(AddrOpLoc, diag::err_template_arg_address_of_non_pointer)
+            << ParamType;
+          S.Diag(Param->getLocation(), diag::note_template_param_here);
+          return true;
+        }
+
+        S.Diag(AddrOpLoc, diag::err_template_arg_address_of_non_pointer)
+          << ParamType
+          << FixItHint::CreateRemoval(AddrOpLoc);
+        S.Diag(Param->getLocation(), diag::note_template_param_here);
+
+        ArgType = Var->getType();
+      }
+    } else if (!AddressTaken && ParamType->isPointerType()) {
+      if (Var->getType()->isArrayType()) {
+        // Array-to-pointer decay.
+        ArgType = S.Context.getArrayDecayedType(Var->getType());
+      } else {
+        // If the template parameter has pointer type but the address of
+        // this object was not taken, complain and (possibly) recover by
+        // taking the address of the entity.
+        ArgType = S.Context.getPointerType(Var->getType());
+        if (!S.Context.hasSameUnqualifiedType(ArgType, ParamType)) {
+          S.Diag(Arg->getLocStart(), diag::err_template_arg_not_address_of)
+            << ParamType;
+          S.Diag(Param->getLocation(), diag::note_template_param_here);
+          return true;
+        }
+
+        S.Diag(Arg->getLocStart(), diag::err_template_arg_not_address_of)
+          << ParamType
+          << FixItHint::CreateInsertion(Arg->getLocStart(), "&");
+
+        S.Diag(Param->getLocation(), diag::note_template_param_here);
+      }
+    }
+  }
+
+  bool ObjCLifetimeConversion;
+  if (ParamType->isPointerType() &&
+      !ParamType->getAs<PointerType>()->getPointeeType()->isFunctionType() &&
+      S.IsQualificationConversion(ArgType, ParamType, false, 
+                                  ObjCLifetimeConversion)) {
+    // For pointer-to-object types, qualification conversions are
+    // permitted.
+  } else {
+    if (const ReferenceType *ParamRef = ParamType->getAs<ReferenceType>()) {
+      if (!ParamRef->getPointeeType()->isFunctionType()) {
+        // C++ [temp.arg.nontype]p5b3:
+        //   For a non-type template-parameter of type reference to
+        //   object, no conversions apply. The type referred to by the
+        //   reference may be more cv-qualified than the (otherwise
+        //   identical) type of the template- argument. The
+        //   template-parameter is bound directly to the
+        //   template-argument, which shall be an lvalue.
+
+        // FIXME: Other qualifiers?
+        unsigned ParamQuals = ParamRef->getPointeeType().getCVRQualifiers();
+        unsigned ArgQuals = ArgType.getCVRQualifiers();
+
+        if ((ParamQuals | ArgQuals) != ParamQuals) {
+          S.Diag(Arg->getLocStart(),
+                 diag::err_template_arg_ref_bind_ignores_quals)
+            << ParamType << Arg->getType()
+            << Arg->getSourceRange();
+          S.Diag(Param->getLocation(), diag::note_template_param_here);
+          return true;
+        }
+      }
+    }
+
+    // At this point, the template argument refers to an object or
+    // function with external linkage. We now need to check whether the
+    // argument and parameter types are compatible.
+    if (!S.Context.hasSameUnqualifiedType(ArgType,
+                                          ParamType.getNonReferenceType())) {
+      // We can't perform this conversion or binding.
+      if (ParamType->isReferenceType())
+        S.Diag(Arg->getLocStart(), diag::err_template_arg_no_ref_bind)
+          << ParamType << ArgIn->getType() << Arg->getSourceRange();
+      else
+        S.Diag(Arg->getLocStart(),  diag::err_template_arg_not_convertible)
+          << ArgIn->getType() << ParamType << Arg->getSourceRange();
+      S.Diag(Param->getLocation(), diag::note_template_param_here);
+      return true;
+    }
+  }
+
+  // Create the template argument.
+  Converted = TemplateArgument(Entity->getCanonicalDecl());
+  S.MarkAnyDeclReferenced(Arg->getLocStart(), Entity);
+  return false;
+}
+
+/// \brief Checks whether the given template argument is a pointer to
+/// member constant according to C++ [temp.arg.nontype]p1.
+static bool CheckTemplateArgumentPointerToMember(Sema &S,
+                                                 NonTypeTemplateParmDecl *Param,
+                                                 QualType ParamType,
+                                                 Expr *&ResultArg,
+                                                 TemplateArgument &Converted) {
+  bool Invalid = false;
+
+  // Check for a null pointer value.
+  Expr *Arg = ResultArg;
+  switch (isNullPointerValueTemplateArgument(S, Param, ParamType, Arg)) {
+  case NPV_Error:
+    return true;
+  case NPV_NullPointer:
+    Converted = TemplateArgument((Decl *)0);
+    return false;
+  case NPV_NotNullPointer:
+    break;
+  }
+
+  bool ObjCLifetimeConversion;
+  if (S.IsQualificationConversion(Arg->getType(),
+                                  ParamType.getNonReferenceType(),
+                                  false, ObjCLifetimeConversion)) {
+    Arg = S.ImpCastExprToType(Arg, ParamType, CK_NoOp,
+                              Arg->getValueKind()).take();
+    ResultArg = Arg;
+  } else if (!S.Context.hasSameUnqualifiedType(Arg->getType(),
+                ParamType.getNonReferenceType())) {
+    // We can't perform this conversion.
+    S.Diag(Arg->getLocStart(), diag::err_template_arg_not_convertible)
+      << Arg->getType() << ParamType << Arg->getSourceRange();
+    S.Diag(Param->getLocation(), diag::note_template_param_here);
+    return true;
+  }
+
+  // See through any implicit casts we added to fix the type.
+  while (ImplicitCastExpr *Cast = dyn_cast<ImplicitCastExpr>(Arg))
+    Arg = Cast->getSubExpr();
+
+  // C++ [temp.arg.nontype]p1:
+  //
+  //   A template-argument for a non-type, non-template
+  //   template-parameter shall be one of: [...]
+  //
+  //     -- a pointer to member expressed as described in 5.3.1.
+  DeclRefExpr *DRE = 0;
+
+  // In C++98/03 mode, give an extension warning on any extra parentheses.
+  // See http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#773
+  bool ExtraParens = false;
+  while (ParenExpr *Parens = dyn_cast<ParenExpr>(Arg)) {
+    if (!Invalid && !ExtraParens) {
+      S.Diag(Arg->getLocStart(),
+             S.getLangOpts().CPlusPlus0x ?
+               diag::warn_cxx98_compat_template_arg_extra_parens :
+               diag::ext_template_arg_extra_parens)
+        << Arg->getSourceRange();
+      ExtraParens = true;
+    }
+
+    Arg = Parens->getSubExpr();
+  }
+
+  while (SubstNonTypeTemplateParmExpr *subst =
+           dyn_cast<SubstNonTypeTemplateParmExpr>(Arg))
+    Arg = subst->getReplacement()->IgnoreImpCasts();
+
+  // A pointer-to-member constant written &Class::member.
+  if (UnaryOperator *UnOp = dyn_cast<UnaryOperator>(Arg)) {
+    if (UnOp->getOpcode() == UO_AddrOf) {
+      DRE = dyn_cast<DeclRefExpr>(UnOp->getSubExpr());
+      if (DRE && !DRE->getQualifier())
+        DRE = 0;
+    }
+  }
+  // A constant of pointer-to-member type.
+  else if ((DRE = dyn_cast<DeclRefExpr>(Arg))) {
+    if (ValueDecl *VD = dyn_cast<ValueDecl>(DRE->getDecl())) {
+      if (VD->getType()->isMemberPointerType()) {
+        if (isa<NonTypeTemplateParmDecl>(VD) ||
+            (isa<VarDecl>(VD) &&
+             S.Context.getCanonicalType(VD->getType()).isConstQualified())) {
+          if (Arg->isTypeDependent() || Arg->isValueDependent())
+            Converted = TemplateArgument(Arg);
+          else
+            Converted = TemplateArgument(VD->getCanonicalDecl());
+          return Invalid;
+        }
+      }
+    }
+
+    DRE = 0;
+  }
+
+  if (!DRE)
+    return S.Diag(Arg->getLocStart(),
+                  diag::err_template_arg_not_pointer_to_member_form)
+      << Arg->getSourceRange();
+
+  if (isa<FieldDecl>(DRE->getDecl()) || isa<CXXMethodDecl>(DRE->getDecl())) {
+    assert((isa<FieldDecl>(DRE->getDecl()) ||
+            !cast<CXXMethodDecl>(DRE->getDecl())->isStatic()) &&
+           "Only non-static member pointers can make it here");
+
+    // Okay: this is the address of a non-static member, and therefore
+    // a member pointer constant.
+    if (Arg->isTypeDependent() || Arg->isValueDependent())
+      Converted = TemplateArgument(Arg);
+    else
+      Converted = TemplateArgument(DRE->getDecl()->getCanonicalDecl());
+    return Invalid;
+  }
+
+  // We found something else, but we don't know specifically what it is.
+  S.Diag(Arg->getLocStart(),
+         diag::err_template_arg_not_pointer_to_member_form)
+    << Arg->getSourceRange();
+  S.Diag(DRE->getDecl()->getLocation(), diag::note_template_arg_refers_here);
+  return true;
+}
+
+/// \brief Check a template argument against its corresponding
+/// non-type template parameter.
+///
+/// This routine implements the semantics of C++ [temp.arg.nontype].
+/// If an error occurred, it returns ExprError(); otherwise, it
+/// returns the converted template argument. \p
+/// InstantiatedParamType is the type of the non-type template
+/// parameter after it has been instantiated.
+ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
+                                       QualType InstantiatedParamType, Expr *Arg,
+                                       TemplateArgument &Converted,
+                                       CheckTemplateArgumentKind CTAK) {
+  SourceLocation StartLoc = Arg->getLocStart();
+
+  // If either the parameter has a dependent type or the argument is
+  // type-dependent, there's nothing we can check now.
+  if (InstantiatedParamType->isDependentType() || Arg->isTypeDependent()) {
+    // FIXME: Produce a cloned, canonical expression?
+    Converted = TemplateArgument(Arg);
+    return Owned(Arg);
+  }
+
+  // C++ [temp.arg.nontype]p5:
+  //   The following conversions are performed on each expression used
+  //   as a non-type template-argument. If a non-type
+  //   template-argument cannot be converted to the type of the
+  //   corresponding template-parameter then the program is
+  //   ill-formed.
+  QualType ParamType = InstantiatedParamType;
+  if (ParamType->isIntegralOrEnumerationType()) {
+    // C++11:
+    //   -- for a non-type template-parameter of integral or
+    //      enumeration type, conversions permitted in a converted
+    //      constant expression are applied.
+    //
+    // C++98:
+    //   -- for a non-type template-parameter of integral or
+    //      enumeration type, integral promotions (4.5) and integral
+    //      conversions (4.7) are applied.
+
+    if (CTAK == CTAK_Deduced &&
+        !Context.hasSameUnqualifiedType(ParamType, Arg->getType())) {
+      // C++ [temp.deduct.type]p17:
+      //   If, in the declaration of a function template with a non-type
+      //   template-parameter, the non-type template-parameter is used
+      //   in an expression in the function parameter-list and, if the
+      //   corresponding template-argument is deduced, the
+      //   template-argument type shall match the type of the
+      //   template-parameter exactly, except that a template-argument
+      //   deduced from an array bound may be of any integral type.
+      Diag(StartLoc, diag::err_deduced_non_type_template_arg_type_mismatch)
+        << Arg->getType().getUnqualifiedType()
+        << ParamType.getUnqualifiedType();
+      Diag(Param->getLocation(), diag::note_template_param_here);
+      return ExprError();
+    }
+
+    if (getLangOpts().CPlusPlus0x) {
+      // We can't check arbitrary value-dependent arguments.
+      // FIXME: If there's no viable conversion to the template parameter type,
+      // we should be able to diagnose that prior to instantiation.
+      if (Arg->isValueDependent()) {
+        Converted = TemplateArgument(Arg);
+        return Owned(Arg);
+      }
+
+      // C++ [temp.arg.nontype]p1:
+      //   A template-argument for a non-type, non-template template-parameter
+      //   shall be one of:
+      //
+      //     -- for a non-type template-parameter of integral or enumeration
+      //        type, a converted constant expression of the type of the
+      //        template-parameter; or
+      llvm::APSInt Value;
+      ExprResult ArgResult =
+        CheckConvertedConstantExpression(Arg, ParamType, Value,
+                                         CCEK_TemplateArg);
+      if (ArgResult.isInvalid())
+        return ExprError();
+
+      // Widen the argument value to sizeof(parameter type). This is almost
+      // always a no-op, except when the parameter type is bool. In
+      // that case, this may extend the argument from 1 bit to 8 bits.
+      QualType IntegerType = ParamType;
+      if (const EnumType *Enum = IntegerType->getAs<EnumType>())
+        IntegerType = Enum->getDecl()->getIntegerType();
+      Value = Value.extOrTrunc(Context.getTypeSize(IntegerType));
+
+      Converted = TemplateArgument(Value, Context.getCanonicalType(ParamType));
+      return ArgResult;
+    }
+
+    ExprResult ArgResult = DefaultLvalueConversion(Arg);
+    if (ArgResult.isInvalid())
+      return ExprError();
+    Arg = ArgResult.take();
+
+    QualType ArgType = Arg->getType();
+
+    // C++ [temp.arg.nontype]p1:
+    //   A template-argument for a non-type, non-template
+    //   template-parameter shall be one of:
+    //
+    //     -- an integral constant-expression of integral or enumeration
+    //        type; or
+    //     -- the name of a non-type template-parameter; or
+    SourceLocation NonConstantLoc;
+    llvm::APSInt Value;
+    if (!ArgType->isIntegralOrEnumerationType()) {
+      Diag(Arg->getLocStart(),
+           diag::err_template_arg_not_integral_or_enumeral)
+        << ArgType << Arg->getSourceRange();
+      Diag(Param->getLocation(), diag::note_template_param_here);
+      return ExprError();
+    } else if (!Arg->isValueDependent()) {
+      Arg = VerifyIntegerConstantExpression(Arg, &Value,
+        PDiag(diag::err_template_arg_not_ice) << ArgType, false).take();
+      if (!Arg)
+        return ExprError();
+    }
+
+    // From here on out, all we care about are the unqualified forms
+    // of the parameter and argument types.
+    ParamType = ParamType.getUnqualifiedType();
+    ArgType = ArgType.getUnqualifiedType();
+
+    // Try to convert the argument to the parameter's type.
+    if (Context.hasSameType(ParamType, ArgType)) {
+      // Okay: no conversion necessary
+    } else if (ParamType->isBooleanType()) {
+      // This is an integral-to-boolean conversion.
+      Arg = ImpCastExprToType(Arg, ParamType, CK_IntegralToBoolean).take();
+    } else if (IsIntegralPromotion(Arg, ArgType, ParamType) ||
+               !ParamType->isEnumeralType()) {
+      // This is an integral promotion or conversion.
+      Arg = ImpCastExprToType(Arg, ParamType, CK_IntegralCast).take();
+    } else {
+      // We can't perform this conversion.
+      Diag(Arg->getLocStart(),
+           diag::err_template_arg_not_convertible)
+        << Arg->getType() << InstantiatedParamType << Arg->getSourceRange();
+      Diag(Param->getLocation(), diag::note_template_param_here);
+      return ExprError();
+    }
+
+    // Add the value of this argument to the list of converted
+    // arguments. We use the bitwidth and signedness of the template
+    // parameter.
+    if (Arg->isValueDependent()) {
+      // The argument is value-dependent. Create a new
+      // TemplateArgument with the converted expression.
+      Converted = TemplateArgument(Arg);
+      return Owned(Arg);
+    }
+
+    QualType IntegerType = Context.getCanonicalType(ParamType);
+    if (const EnumType *Enum = IntegerType->getAs<EnumType>())
+      IntegerType = Context.getCanonicalType(Enum->getDecl()->getIntegerType());
+
+    if (ParamType->isBooleanType()) {
+      // Value must be zero or one.
+      Value = Value != 0;
+      unsigned AllowedBits = Context.getTypeSize(IntegerType);
+      if (Value.getBitWidth() != AllowedBits)
+        Value = Value.extOrTrunc(AllowedBits);
+      Value.setIsSigned(IntegerType->isSignedIntegerOrEnumerationType());
+    } else {
+      llvm::APSInt OldValue = Value;
+      
+      // Coerce the template argument's value to the value it will have
+      // based on the template parameter's type.
+      unsigned AllowedBits = Context.getTypeSize(IntegerType);
+      if (Value.getBitWidth() != AllowedBits)
+        Value = Value.extOrTrunc(AllowedBits);
+      Value.setIsSigned(IntegerType->isSignedIntegerOrEnumerationType());
+      
+      // Complain if an unsigned parameter received a negative value.
+      if (IntegerType->isUnsignedIntegerOrEnumerationType()
+               && (OldValue.isSigned() && OldValue.isNegative())) {
+        Diag(Arg->getLocStart(), diag::warn_template_arg_negative)
+          << OldValue.toString(10) << Value.toString(10) << Param->getType()
+          << Arg->getSourceRange();
+        Diag(Param->getLocation(), diag::note_template_param_here);
+      }
+      
+      // Complain if we overflowed the template parameter's type.
+      unsigned RequiredBits;
+      if (IntegerType->isUnsignedIntegerOrEnumerationType())
+        RequiredBits = OldValue.getActiveBits();
+      else if (OldValue.isUnsigned())
+        RequiredBits = OldValue.getActiveBits() + 1;
+      else
+        RequiredBits = OldValue.getMinSignedBits();
+      if (RequiredBits > AllowedBits) {
+        Diag(Arg->getLocStart(),
+             diag::warn_template_arg_too_large)
+          << OldValue.toString(10) << Value.toString(10) << Param->getType()
+          << Arg->getSourceRange();
+        Diag(Param->getLocation(), diag::note_template_param_here);
+      }
+    }
+
+    Converted = TemplateArgument(Value,
+                                 ParamType->isEnumeralType() 
+                                   ? Context.getCanonicalType(ParamType)
+                                   : IntegerType);
+    return Owned(Arg);
+  }
+
+  QualType ArgType = Arg->getType();
+  DeclAccessPair FoundResult; // temporary for ResolveOverloadedFunction
+
+  // Handle pointer-to-function, reference-to-function, and
+  // pointer-to-member-function all in (roughly) the same way.
+  if (// -- For a non-type template-parameter of type pointer to
+      //    function, only the function-to-pointer conversion (4.3) is
+      //    applied. If the template-argument represents a set of
+      //    overloaded functions (or a pointer to such), the matching
+      //    function is selected from the set (13.4).
+      (ParamType->isPointerType() &&
+       ParamType->getAs<PointerType>()->getPointeeType()->isFunctionType()) ||
+      // -- For a non-type template-parameter of type reference to
+      //    function, no conversions apply. If the template-argument
+      //    represents a set of overloaded functions, the matching
+      //    function is selected from the set (13.4).
+      (ParamType->isReferenceType() &&
+       ParamType->getAs<ReferenceType>()->getPointeeType()->isFunctionType()) ||
+      // -- For a non-type template-parameter of type pointer to
+      //    member function, no conversions apply. If the
+      //    template-argument represents a set of overloaded member
+      //    functions, the matching member function is selected from
+      //    the set (13.4).
+      (ParamType->isMemberPointerType() &&
+       ParamType->getAs<MemberPointerType>()->getPointeeType()
+         ->isFunctionType())) {
+
+    if (Arg->getType() == Context.OverloadTy) {
+      if (FunctionDecl *Fn = ResolveAddressOfOverloadedFunction(Arg, ParamType,
+                                                                true,
+                                                                FoundResult)) {
+        if (DiagnoseUseOfDecl(Fn, Arg->getLocStart()))
+          return ExprError();
+
+        Arg = FixOverloadedFunctionReference(Arg, FoundResult, Fn);
+        ArgType = Arg->getType();
+      } else
+        return ExprError();
+    }
+
+    if (!ParamType->isMemberPointerType()) {
+      if (CheckTemplateArgumentAddressOfObjectOrFunction(*this, Param,
+                                                         ParamType,
+                                                         Arg, Converted))
+        return ExprError();
+      return Owned(Arg);
+    }
+
+    if (CheckTemplateArgumentPointerToMember(*this, Param, ParamType, Arg,
+                                             Converted))
+      return ExprError();
+    return Owned(Arg);
+  }
+
+  if (ParamType->isPointerType()) {
+    //   -- for a non-type template-parameter of type pointer to
+    //      object, qualification conversions (4.4) and the
+    //      array-to-pointer conversion (4.2) are applied.
+    // C++0x also allows a value of std::nullptr_t.
+    assert(ParamType->getPointeeType()->isIncompleteOrObjectType() &&
+           "Only object pointers allowed here");
+
+    if (CheckTemplateArgumentAddressOfObjectOrFunction(*this, Param,
+                                                       ParamType,
+                                                       Arg, Converted))
+      return ExprError();
+    return Owned(Arg);
+  }
+
+  if (const ReferenceType *ParamRefType = ParamType->getAs<ReferenceType>()) {
+    //   -- For a non-type template-parameter of type reference to
+    //      object, no conversions apply. The type referred to by the
+    //      reference may be more cv-qualified than the (otherwise
+    //      identical) type of the template-argument. The
+    //      template-parameter is bound directly to the
+    //      template-argument, which must be an lvalue.
+    assert(ParamRefType->getPointeeType()->isIncompleteOrObjectType() &&
+           "Only object references allowed here");
+
+    if (Arg->getType() == Context.OverloadTy) {
+      if (FunctionDecl *Fn = ResolveAddressOfOverloadedFunction(Arg,
+                                                 ParamRefType->getPointeeType(),
+                                                                true,
+                                                                FoundResult)) {
+        if (DiagnoseUseOfDecl(Fn, Arg->getLocStart()))
+          return ExprError();
+
+        Arg = FixOverloadedFunctionReference(Arg, FoundResult, Fn);
+        ArgType = Arg->getType();
+      } else
+        return ExprError();
+    }
+
+    if (CheckTemplateArgumentAddressOfObjectOrFunction(*this, Param,
+                                                       ParamType,
+                                                       Arg, Converted))
+      return ExprError();
+    return Owned(Arg);
+  }
+
+  // Deal with parameters of type std::nullptr_t.
+  if (ParamType->isNullPtrType()) {
+    if (Arg->isTypeDependent() || Arg->isValueDependent()) {
+      Converted = TemplateArgument(Arg);
+      return Owned(Arg);
+    }
+    
+    switch (isNullPointerValueTemplateArgument(*this, Param, ParamType, Arg)) {
+    case NPV_NotNullPointer:
+      Diag(Arg->getExprLoc(), diag::err_template_arg_not_convertible)
+        << Arg->getType() << ParamType;
+      Diag(Param->getLocation(), diag::note_template_param_here);
+      return ExprError();
+      
+    case NPV_Error:
+      return ExprError();
+      
+    case NPV_NullPointer:
+      Converted = TemplateArgument((Decl *)0);
+      return Owned(Arg);;
+    }
+  }
+
+  //     -- For a non-type template-parameter of type pointer to data
+  //        member, qualification conversions (4.4) are applied.
+  assert(ParamType->isMemberPointerType() && "Only pointers to members remain");
+
+  if (CheckTemplateArgumentPointerToMember(*this, Param, ParamType, Arg,
+                                           Converted))
+    return ExprError();
+  return Owned(Arg);
+}
+
+/// \brief Check a template argument against its corresponding
+/// template template parameter.
+///
+/// This routine implements the semantics of C++ [temp.arg.template].
+/// It returns true if an error occurred, and false otherwise.
+bool Sema::CheckTemplateArgument(TemplateTemplateParmDecl *Param,
+                                 const TemplateArgumentLoc &Arg) {
+  TemplateName Name = Arg.getArgument().getAsTemplate();
+  TemplateDecl *Template = Name.getAsTemplateDecl();
+  if (!Template) {
+    // Any dependent template name is fine.
+    assert(Name.isDependent() && "Non-dependent template isn't a declaration?");
+    return false;
+  }
+
+  // C++0x [temp.arg.template]p1:
+  //   A template-argument for a template template-parameter shall be
+  //   the name of a class template or an alias template, expressed as an
+  //   id-expression. When the template-argument names a class template, only
+  //   primary class templates are considered when matching the
+  //   template template argument with the corresponding parameter;
+  //   partial specializations are not considered even if their
+  //   parameter lists match that of the template template parameter.
+  //
+  // Note that we also allow template template parameters here, which
+  // will happen when we are dealing with, e.g., class template
+  // partial specializations.
+  if (!isa<ClassTemplateDecl>(Template) &&
+      !isa<TemplateTemplateParmDecl>(Template) &&
+      !isa<TypeAliasTemplateDecl>(Template)) {
+    assert(isa<FunctionTemplateDecl>(Template) &&
+           "Only function templates are possible here");
+    Diag(Arg.getLocation(), diag::err_template_arg_not_class_template);
+    Diag(Template->getLocation(), diag::note_template_arg_refers_here_func)
+      << Template;
+  }
+
+  return !TemplateParameterListsAreEqual(Template->getTemplateParameters(),
+                                         Param->getTemplateParameters(),
+                                         true,
+                                         TPL_TemplateTemplateArgumentMatch,
+                                         Arg.getLocation());
+}
+
+/// \brief Given a non-type template argument that refers to a
+/// declaration and the type of its corresponding non-type template
+/// parameter, produce an expression that properly refers to that
+/// declaration.
+ExprResult
+Sema::BuildExpressionFromDeclTemplateArgument(const TemplateArgument &Arg,
+                                              QualType ParamType,
+                                              SourceLocation Loc) {
+  assert(Arg.getKind() == TemplateArgument::Declaration &&
+         "Only declaration template arguments permitted here");
+  
+  // For a NULL non-type template argument, return nullptr casted to the
+  // parameter's type.
+  if (!Arg.getAsDecl()) {
+    return ImpCastExprToType(
+             new (Context) CXXNullPtrLiteralExpr(Context.NullPtrTy, Loc),
+                             ParamType,
+                             ParamType->getAs<MemberPointerType>()
+                               ? CK_NullToMemberPointer
+                               : CK_NullToPointer);
+  }
+  
+  ValueDecl *VD = cast<ValueDecl>(Arg.getAsDecl());
+
+  if (VD->getDeclContext()->isRecord() &&
+      (isa<CXXMethodDecl>(VD) || isa<FieldDecl>(VD))) {
+    // If the value is a class member, we might have a pointer-to-member.
+    // Determine whether the non-type template template parameter is of
+    // pointer-to-member type. If so, we need to build an appropriate
+    // expression for a pointer-to-member, since a "normal" DeclRefExpr
+    // would refer to the member itself.
+    if (ParamType->isMemberPointerType()) {
+      QualType ClassType
+        = Context.getTypeDeclType(cast<RecordDecl>(VD->getDeclContext()));
+      NestedNameSpecifier *Qualifier
+        = NestedNameSpecifier::Create(Context, 0, false,
+                                      ClassType.getTypePtr());
+      CXXScopeSpec SS;
+      SS.MakeTrivial(Context, Qualifier, Loc);
+
+      // The actual value-ness of this is unimportant, but for
+      // internal consistency's sake, references to instance methods
+      // are r-values.
+      ExprValueKind VK = VK_LValue;
+      if (isa<CXXMethodDecl>(VD) && cast<CXXMethodDecl>(VD)->isInstance())
+        VK = VK_RValue;
+
+      ExprResult RefExpr = BuildDeclRefExpr(VD,
+                                            VD->getType().getNonReferenceType(),
+                                            VK,
+                                            Loc,
+                                            &SS);
+      if (RefExpr.isInvalid())
+        return ExprError();
+
+      RefExpr = CreateBuiltinUnaryOp(Loc, UO_AddrOf, RefExpr.get());
+
+      // We might need to perform a trailing qualification conversion, since
+      // the element type on the parameter could be more qualified than the
+      // element type in the expression we constructed.
+      bool ObjCLifetimeConversion;
+      if (IsQualificationConversion(((Expr*) RefExpr.get())->getType(),
+                                    ParamType.getUnqualifiedType(), false,
+                                    ObjCLifetimeConversion))
+        RefExpr = ImpCastExprToType(RefExpr.take(), ParamType.getUnqualifiedType(), CK_NoOp);
+
+      assert(!RefExpr.isInvalid() &&
+             Context.hasSameType(((Expr*) RefExpr.get())->getType(),
+                                 ParamType.getUnqualifiedType()));
+      return move(RefExpr);
+    }
+  }
+
+  QualType T = VD->getType().getNonReferenceType();
+  if (ParamType->isPointerType()) {
+    // When the non-type template parameter is a pointer, take the
+    // address of the declaration.
+    ExprResult RefExpr = BuildDeclRefExpr(VD, T, VK_LValue, Loc);
+    if (RefExpr.isInvalid())
+      return ExprError();
+
+    if (T->isFunctionType() || T->isArrayType()) {
+      // Decay functions and arrays.
+      RefExpr = DefaultFunctionArrayConversion(RefExpr.take());
+      if (RefExpr.isInvalid())
+        return ExprError();
+
+      return move(RefExpr);
+    }
+
+    // Take the address of everything else
+    return CreateBuiltinUnaryOp(Loc, UO_AddrOf, RefExpr.get());
+  }
+
+  ExprValueKind VK = VK_RValue;
+
+  // If the non-type template parameter has reference type, qualify the
+  // resulting declaration reference with the extra qualifiers on the
+  // type that the reference refers to.
+  if (const ReferenceType *TargetRef = ParamType->getAs<ReferenceType>()) {
+    VK = VK_LValue;
+    T = Context.getQualifiedType(T,
+                              TargetRef->getPointeeType().getQualifiers());
+  }
+
+  return BuildDeclRefExpr(VD, T, VK, Loc);
+}
+
+/// \brief Construct a new expression that refers to the given
+/// integral template argument with the given source-location
+/// information.
+///
+/// This routine takes care of the mapping from an integral template
+/// argument (which may have any integral type) to the appropriate
+/// literal value.
+ExprResult
+Sema::BuildExpressionFromIntegralTemplateArgument(const TemplateArgument &Arg,
+                                                  SourceLocation Loc) {
+  assert(Arg.getKind() == TemplateArgument::Integral &&
+         "Operation is only valid for integral template arguments");
+  QualType T = Arg.getIntegralType();
+  if (T->isAnyCharacterType()) {
+    CharacterLiteral::CharacterKind Kind;
+    if (T->isWideCharType())
+      Kind = CharacterLiteral::Wide;
+    else if (T->isChar16Type())
+      Kind = CharacterLiteral::UTF16;
+    else if (T->isChar32Type())
+      Kind = CharacterLiteral::UTF32;
+    else
+      Kind = CharacterLiteral::Ascii;
+
+    return Owned(new (Context) CharacterLiteral(
+                                            Arg.getAsIntegral()->getZExtValue(),
+                                            Kind, T, Loc));
+  }
+
+  if (T->isBooleanType())
+    return Owned(new (Context) CXXBoolLiteralExpr(
+                                            Arg.getAsIntegral()->getBoolValue(),
+                                            T, Loc));
+
+  if (T->isNullPtrType())
+    return Owned(new (Context) CXXNullPtrLiteralExpr(Context.NullPtrTy, Loc));
+  
+  // If this is an enum type that we're instantiating, we need to use an integer
+  // type the same size as the enumerator.  We don't want to build an
+  // IntegerLiteral with enum type.
+  QualType BT;
+  if (const EnumType *ET = T->getAs<EnumType>())
+    BT = ET->getDecl()->getIntegerType();
+  else
+    BT = T;
+
+  Expr *E = IntegerLiteral::Create(Context, *Arg.getAsIntegral(), BT, Loc);
+  if (T->isEnumeralType()) {
+    // FIXME: This is a hack. We need a better way to handle substituted
+    // non-type template parameters.
+    E = CStyleCastExpr::Create(Context, T, VK_RValue, CK_IntegralCast, E, 0, 
+                               Context.getTrivialTypeSourceInfo(T, Loc),
+                               Loc, Loc);
+  }
+  
+  return Owned(E);
+}
+
+/// \brief Match two template parameters within template parameter lists.
+static bool MatchTemplateParameterKind(Sema &S, NamedDecl *New, NamedDecl *Old,
+                                       bool Complain,
+                                     Sema::TemplateParameterListEqualKind Kind,
+                                       SourceLocation TemplateArgLoc) {
+  // Check the actual kind (type, non-type, template).
+  if (Old->getKind() != New->getKind()) {
+    if (Complain) {
+      unsigned NextDiag = diag::err_template_param_different_kind;
+      if (TemplateArgLoc.isValid()) {
+        S.Diag(TemplateArgLoc, diag::err_template_arg_template_params_mismatch);
+        NextDiag = diag::note_template_param_different_kind;
+      }
+      S.Diag(New->getLocation(), NextDiag)
+        << (Kind != Sema::TPL_TemplateMatch);
+      S.Diag(Old->getLocation(), diag::note_template_prev_declaration)
+        << (Kind != Sema::TPL_TemplateMatch);
+    }
+
+    return false;
+  }
+
+  // Check that both are parameter packs are neither are parameter packs.
+  // However, if we are matching a template template argument to a
+  // template template parameter, the template template parameter can have
+  // a parameter pack where the template template argument does not.
+  if (Old->isTemplateParameterPack() != New->isTemplateParameterPack() &&
+      !(Kind == Sema::TPL_TemplateTemplateArgumentMatch &&
+        Old->isTemplateParameterPack())) {
+    if (Complain) {
+      unsigned NextDiag = diag::err_template_parameter_pack_non_pack;
+      if (TemplateArgLoc.isValid()) {
+        S.Diag(TemplateArgLoc,
+             diag::err_template_arg_template_params_mismatch);
+        NextDiag = diag::note_template_parameter_pack_non_pack;
+      }
+
+      unsigned ParamKind = isa<TemplateTypeParmDecl>(New)? 0
+                      : isa<NonTypeTemplateParmDecl>(New)? 1
+                      : 2;
+      S.Diag(New->getLocation(), NextDiag)
+        << ParamKind << New->isParameterPack();
+      S.Diag(Old->getLocation(), diag::note_template_parameter_pack_here)
+        << ParamKind << Old->isParameterPack();
+    }
+
+    return false;
+  }
+
+  // For non-type template parameters, check the type of the parameter.
+  if (NonTypeTemplateParmDecl *OldNTTP
+                                    = dyn_cast<NonTypeTemplateParmDecl>(Old)) {
+    NonTypeTemplateParmDecl *NewNTTP = cast<NonTypeTemplateParmDecl>(New);
+
+    // If we are matching a template template argument to a template
+    // template parameter and one of the non-type template parameter types
+    // is dependent, then we must wait until template instantiation time
+    // to actually compare the arguments.
+    if (Kind == Sema::TPL_TemplateTemplateArgumentMatch &&
+        (OldNTTP->getType()->isDependentType() ||
+         NewNTTP->getType()->isDependentType()))
+      return true;
+
+    if (!S.Context.hasSameType(OldNTTP->getType(), NewNTTP->getType())) {
+      if (Complain) {
+        unsigned NextDiag = diag::err_template_nontype_parm_different_type;
+        if (TemplateArgLoc.isValid()) {
+          S.Diag(TemplateArgLoc,
+                 diag::err_template_arg_template_params_mismatch);
+          NextDiag = diag::note_template_nontype_parm_different_type;
+        }
+        S.Diag(NewNTTP->getLocation(), NextDiag)
+          << NewNTTP->getType()
+          << (Kind != Sema::TPL_TemplateMatch);
+        S.Diag(OldNTTP->getLocation(),
+               diag::note_template_nontype_parm_prev_declaration)
+          << OldNTTP->getType();
+      }
+
+      return false;
+    }
+
+    return true;
+  }
+
+  // For template template parameters, check the template parameter types.
+  // The template parameter lists of template template
+  // parameters must agree.
+  if (TemplateTemplateParmDecl *OldTTP
+                                    = dyn_cast<TemplateTemplateParmDecl>(Old)) {
+    TemplateTemplateParmDecl *NewTTP = cast<TemplateTemplateParmDecl>(New);
+    return S.TemplateParameterListsAreEqual(NewTTP->getTemplateParameters(),
+                                            OldTTP->getTemplateParameters(),
+                                            Complain,
+                                        (Kind == Sema::TPL_TemplateMatch
+                                           ? Sema::TPL_TemplateTemplateParmMatch
+                                           : Kind),
+                                            TemplateArgLoc);
+  }
+
+  return true;
+}
+
+/// \brief Diagnose a known arity mismatch when comparing template argument
+/// lists.
+static
+void DiagnoseTemplateParameterListArityMismatch(Sema &S,
+                                                TemplateParameterList *New,
+                                                TemplateParameterList *Old,
+                                      Sema::TemplateParameterListEqualKind Kind,
+                                                SourceLocation TemplateArgLoc) {
+  unsigned NextDiag = diag::err_template_param_list_different_arity;
+  if (TemplateArgLoc.isValid()) {
+    S.Diag(TemplateArgLoc, diag::err_template_arg_template_params_mismatch);
+    NextDiag = diag::note_template_param_list_different_arity;
+  }
+  S.Diag(New->getTemplateLoc(), NextDiag)
+    << (New->size() > Old->size())
+    << (Kind != Sema::TPL_TemplateMatch)
+    << SourceRange(New->getTemplateLoc(), New->getRAngleLoc());
+  S.Diag(Old->getTemplateLoc(), diag::note_template_prev_declaration)
+    << (Kind != Sema::TPL_TemplateMatch)
+    << SourceRange(Old->getTemplateLoc(), Old->getRAngleLoc());
+}
+
+/// \brief Determine whether the given template parameter lists are
+/// equivalent.
+///
+/// \param New  The new template parameter list, typically written in the
+/// source code as part of a new template declaration.
+///
+/// \param Old  The old template parameter list, typically found via
+/// name lookup of the template declared with this template parameter
+/// list.
+///
+/// \param Complain  If true, this routine will produce a diagnostic if
+/// the template parameter lists are not equivalent.
+///
+/// \param Kind describes how we are to match the template parameter lists.
+///
+/// \param TemplateArgLoc If this source location is valid, then we
+/// are actually checking the template parameter list of a template
+/// argument (New) against the template parameter list of its
+/// corresponding template template parameter (Old). We produce
+/// slightly different diagnostics in this scenario.
+///
+/// \returns True if the template parameter lists are equal, false
+/// otherwise.
+bool
+Sema::TemplateParameterListsAreEqual(TemplateParameterList *New,
+                                     TemplateParameterList *Old,
+                                     bool Complain,
+                                     TemplateParameterListEqualKind Kind,
+                                     SourceLocation TemplateArgLoc) {
+  if (Old->size() != New->size() && Kind != TPL_TemplateTemplateArgumentMatch) {
+    if (Complain)
+      DiagnoseTemplateParameterListArityMismatch(*this, New, Old, Kind,
+                                                 TemplateArgLoc);
+
+    return false;
+  }
+
+  // C++0x [temp.arg.template]p3:
+  //   A template-argument matches a template template-parameter (call it P)
+  //   when each of the template parameters in the template-parameter-list of
+  //   the template-argument's corresponding class template or alias template
+  //   (call it A) matches the corresponding template parameter in the
+  //   template-parameter-list of P. [...]
+  TemplateParameterList::iterator NewParm = New->begin();
+  TemplateParameterList::iterator NewParmEnd = New->end();
+  for (TemplateParameterList::iterator OldParm = Old->begin(),
+                                    OldParmEnd = Old->end();
+       OldParm != OldParmEnd; ++OldParm) {
+    if (Kind != TPL_TemplateTemplateArgumentMatch ||
+        !(*OldParm)->isTemplateParameterPack()) {
+      if (NewParm == NewParmEnd) {
+        if (Complain)
+          DiagnoseTemplateParameterListArityMismatch(*this, New, Old, Kind,
+                                                     TemplateArgLoc);
+
+        return false;
+      }
+
+      if (!MatchTemplateParameterKind(*this, *NewParm, *OldParm, Complain,
+                                      Kind, TemplateArgLoc))
+        return false;
+
+      ++NewParm;
+      continue;
+    }
+
+    // C++0x [temp.arg.template]p3:
+    //   [...] When P's template- parameter-list contains a template parameter
+    //   pack (14.5.3), the template parameter pack will match zero or more
+    //   template parameters or template parameter packs in the
+    //   template-parameter-list of A with the same type and form as the
+    //   template parameter pack in P (ignoring whether those template
+    //   parameters are template parameter packs).
+    for (; NewParm != NewParmEnd; ++NewParm) {
+      if (!MatchTemplateParameterKind(*this, *NewParm, *OldParm, Complain,
+                                      Kind, TemplateArgLoc))
+        return false;
+    }
+  }
+
+  // Make sure we exhausted all of the arguments.
+  if (NewParm != NewParmEnd) {
+    if (Complain)
+      DiagnoseTemplateParameterListArityMismatch(*this, New, Old, Kind,
+                                                 TemplateArgLoc);
+
+    return false;
+  }
+
+  return true;
+}
+
+/// \brief Check whether a template can be declared within this scope.
+///
+/// If the template declaration is valid in this scope, returns
+/// false. Otherwise, issues a diagnostic and returns true.
+bool
+Sema::CheckTemplateDeclScope(Scope *S, TemplateParameterList *TemplateParams) {
+  if (!S)
+    return false;
+
+  // Find the nearest enclosing declaration scope.
+  while ((S->getFlags() & Scope::DeclScope) == 0 ||
+         (S->getFlags() & Scope::TemplateParamScope) != 0)
+    S = S->getParent();
+
+  // C++ [temp]p2:
+  //   A template-declaration can appear only as a namespace scope or
+  //   class scope declaration.
+  DeclContext *Ctx = static_cast<DeclContext *>(S->getEntity());
+  if (Ctx && isa<LinkageSpecDecl>(Ctx) &&
+      cast<LinkageSpecDecl>(Ctx)->getLanguage() != LinkageSpecDecl::lang_cxx)
+    return Diag(TemplateParams->getTemplateLoc(), diag::err_template_linkage)
+             << TemplateParams->getSourceRange();
+
+  while (Ctx && isa<LinkageSpecDecl>(Ctx))
+    Ctx = Ctx->getParent();
+
+  if (Ctx && (Ctx->isFileContext() || Ctx->isRecord()))
+    return false;
+
+  return Diag(TemplateParams->getTemplateLoc(),
+              diag::err_template_outside_namespace_or_class_scope)
+    << TemplateParams->getSourceRange();
+}
+
+/// \brief Determine what kind of template specialization the given declaration
+/// is.
+static TemplateSpecializationKind getTemplateSpecializationKind(Decl *D) {
+  if (!D)
+    return TSK_Undeclared;
+
+  if (CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(D))
+    return Record->getTemplateSpecializationKind();
+  if (FunctionDecl *Function = dyn_cast<FunctionDecl>(D))
+    return Function->getTemplateSpecializationKind();
+  if (VarDecl *Var = dyn_cast<VarDecl>(D))
+    return Var->getTemplateSpecializationKind();
+
+  return TSK_Undeclared;
+}
+
+/// \brief Check whether a specialization is well-formed in the current
+/// context.
+///
+/// This routine determines whether a template specialization can be declared
+/// in the current context (C++ [temp.expl.spec]p2).
+///
+/// \param S the semantic analysis object for which this check is being
+/// performed.
+///
+/// \param Specialized the entity being specialized or instantiated, which
+/// may be a kind of template (class template, function template, etc.) or
+/// a member of a class template (member function, static data member,
+/// member class).
+///
+/// \param PrevDecl the previous declaration of this entity, if any.
+///
+/// \param Loc the location of the explicit specialization or instantiation of
+/// this entity.
+///
+/// \param IsPartialSpecialization whether this is a partial specialization of
+/// a class template.
+///
+/// \returns true if there was an error that we cannot recover from, false
+/// otherwise.
+static bool CheckTemplateSpecializationScope(Sema &S,
+                                             NamedDecl *Specialized,
+                                             NamedDecl *PrevDecl,
+                                             SourceLocation Loc,
+                                             bool IsPartialSpecialization) {
+  // Keep these "kind" numbers in sync with the %select statements in the
+  // various diagnostics emitted by this routine.
+  int EntityKind = 0;
+  if (isa<ClassTemplateDecl>(Specialized))
+    EntityKind = IsPartialSpecialization? 1 : 0;
+  else if (isa<FunctionTemplateDecl>(Specialized))
+    EntityKind = 2;
+  else if (isa<CXXMethodDecl>(Specialized))
+    EntityKind = 3;
+  else if (isa<VarDecl>(Specialized))
+    EntityKind = 4;
+  else if (isa<RecordDecl>(Specialized))
+    EntityKind = 5;
+  else if (isa<EnumDecl>(Specialized) && S.getLangOpts().CPlusPlus0x)
+    EntityKind = 6;
+  else {
+    S.Diag(Loc, diag::err_template_spec_unknown_kind)
+      << S.getLangOpts().CPlusPlus0x;
+    S.Diag(Specialized->getLocation(), diag::note_specialized_entity);
+    return true;
+  }
+
+  // C++ [temp.expl.spec]p2:
+  //   An explicit specialization shall be declared in the namespace
+  //   of which the template is a member, or, for member templates, in
+  //   the namespace of which the enclosing class or enclosing class
+  //   template is a member. An explicit specialization of a member
+  //   function, member class or static data member of a class
+  //   template shall be declared in the namespace of which the class
+  //   template is a member. Such a declaration may also be a
+  //   definition. If the declaration is not a definition, the
+  //   specialization may be defined later in the name- space in which
+  //   the explicit specialization was declared, or in a namespace
+  //   that encloses the one in which the explicit specialization was
+  //   declared.
+  if (S.CurContext->getRedeclContext()->isFunctionOrMethod()) {
+    S.Diag(Loc, diag::err_template_spec_decl_function_scope)
+      << Specialized;
+    return true;
+  }
+
+  if (S.CurContext->isRecord() && !IsPartialSpecialization) {
+    if (S.getLangOpts().MicrosoftExt) {
+      // Do not warn for class scope explicit specialization during
+      // instantiation, warning was already emitted during pattern
+      // semantic analysis.
+      if (!S.ActiveTemplateInstantiations.size())
+        S.Diag(Loc, diag::ext_function_specialization_in_class)
+          << Specialized;
+    } else {
+      S.Diag(Loc, diag::err_template_spec_decl_class_scope)
+        << Specialized;
+      return true;
+    }
+  }
+
+  if (S.CurContext->isRecord() &&
+      !S.CurContext->Equals(Specialized->getDeclContext())) {
+    // Make sure that we're specializing in the right record context.
+    // Otherwise, things can go horribly wrong.
+    S.Diag(Loc, diag::err_template_spec_decl_class_scope)
+      << Specialized;
+    return true;
+  }
+  
+  // C++ [temp.class.spec]p6:
+  //   A class template partial specialization may be declared or redeclared
+  //   in any namespace scope in which its definition may be defined (14.5.1
+  //   and 14.5.2).
+  bool ComplainedAboutScope = false;
+  DeclContext *SpecializedContext 
+    = Specialized->getDeclContext()->getEnclosingNamespaceContext();
+  DeclContext *DC = S.CurContext->getEnclosingNamespaceContext();
+  if ((!PrevDecl ||
+       getTemplateSpecializationKind(PrevDecl) == TSK_Undeclared ||
+       getTemplateSpecializationKind(PrevDecl) == TSK_ImplicitInstantiation)){
+    // C++ [temp.exp.spec]p2:
+    //   An explicit specialization shall be declared in the namespace of which
+    //   the template is a member, or, for member templates, in the namespace
+    //   of which the enclosing class or enclosing class template is a member.
+    //   An explicit specialization of a member function, member class or
+    //   static data member of a class template shall be declared in the
+    //   namespace of which the class template is a member.
+    //
+    // C++0x [temp.expl.spec]p2:
+    //   An explicit specialization shall be declared in a namespace enclosing
+    //   the specialized template.
+    if (!DC->InEnclosingNamespaceSetOf(SpecializedContext)) {
+      bool IsCPlusPlus0xExtension = DC->Encloses(SpecializedContext);
+      if (isa<TranslationUnitDecl>(SpecializedContext)) {
+        assert(!IsCPlusPlus0xExtension &&
+               "DC encloses TU but isn't in enclosing namespace set");
+        S.Diag(Loc, diag::err_template_spec_decl_out_of_scope_global)
+          << EntityKind << Specialized;
+      } else if (isa<NamespaceDecl>(SpecializedContext)) {
+        int Diag;
+        if (!IsCPlusPlus0xExtension)
+          Diag = diag::err_template_spec_decl_out_of_scope;
+        else if (!S.getLangOpts().CPlusPlus0x)
+          Diag = diag::ext_template_spec_decl_out_of_scope;
+        else
+          Diag = diag::warn_cxx98_compat_template_spec_decl_out_of_scope;
+        S.Diag(Loc, Diag)
+          << EntityKind << Specialized << cast<NamedDecl>(SpecializedContext);
+      }
+
+      S.Diag(Specialized->getLocation(), diag::note_specialized_entity);
+      ComplainedAboutScope =
+        !(IsCPlusPlus0xExtension && S.getLangOpts().CPlusPlus0x);
+    }
+  }
+
+  // Make sure that this redeclaration (or definition) occurs in an enclosing
+  // namespace.
+  // Note that HandleDeclarator() performs this check for explicit
+  // specializations of function templates, static data members, and member
+  // functions, so we skip the check here for those kinds of entities.
+  // FIXME: HandleDeclarator's diagnostics aren't quite as good, though.
+  // Should we refactor that check, so that it occurs later?
+  if (!ComplainedAboutScope && !DC->Encloses(SpecializedContext) &&
+      !(isa<FunctionTemplateDecl>(Specialized) || isa<VarDecl>(Specialized) ||
+        isa<FunctionDecl>(Specialized))) {
+    if (isa<TranslationUnitDecl>(SpecializedContext))
+      S.Diag(Loc, diag::err_template_spec_redecl_global_scope)
+        << EntityKind << Specialized;
+    else if (isa<NamespaceDecl>(SpecializedContext))
+      S.Diag(Loc, diag::err_template_spec_redecl_out_of_scope)
+        << EntityKind << Specialized
+        << cast<NamedDecl>(SpecializedContext);
+
+    S.Diag(Specialized->getLocation(), diag::note_specialized_entity);
+  }
+
+  // FIXME: check for specialization-after-instantiation errors and such.
+
+  return false;
+}
+
+/// \brief Subroutine of Sema::CheckClassTemplatePartialSpecializationArgs
+/// that checks non-type template partial specialization arguments.
+static bool CheckNonTypeClassTemplatePartialSpecializationArgs(Sema &S,
+                                                NonTypeTemplateParmDecl *Param,
+                                                  const TemplateArgument *Args,
+                                                        unsigned NumArgs) {
+  for (unsigned I = 0; I != NumArgs; ++I) {
+    if (Args[I].getKind() == TemplateArgument::Pack) {
+      if (CheckNonTypeClassTemplatePartialSpecializationArgs(S, Param,
+                                                           Args[I].pack_begin(),
+                                                           Args[I].pack_size()))
+        return true;
+
+      continue;
+    }
+
+    Expr *ArgExpr = Args[I].getAsExpr();
+    if (!ArgExpr) {
+      continue;
+    }
+
+    // We can have a pack expansion of any of the bullets below.
+    if (PackExpansionExpr *Expansion = dyn_cast<PackExpansionExpr>(ArgExpr))
+      ArgExpr = Expansion->getPattern();
+
+    // Strip off any implicit casts we added as part of type checking.
+    while (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(ArgExpr))
+      ArgExpr = ICE->getSubExpr();
+
+    // C++ [temp.class.spec]p8:
+    //   A non-type argument is non-specialized if it is the name of a
+    //   non-type parameter. All other non-type arguments are
+    //   specialized.
+    //
+    // Below, we check the two conditions that only apply to
+    // specialized non-type arguments, so skip any non-specialized
+    // arguments.
+    if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(ArgExpr))
+      if (isa<NonTypeTemplateParmDecl>(DRE->getDecl()))
+        continue;
+
+    // C++ [temp.class.spec]p9:
+    //   Within the argument list of a class template partial
+    //   specialization, the following restrictions apply:
+    //     -- A partially specialized non-type argument expression
+    //        shall not involve a template parameter of the partial
+    //        specialization except when the argument expression is a
+    //        simple identifier.
+    if (ArgExpr->isTypeDependent() || ArgExpr->isValueDependent()) {
+      S.Diag(ArgExpr->getLocStart(),
+           diag::err_dependent_non_type_arg_in_partial_spec)
+        << ArgExpr->getSourceRange();
+      return true;
+    }
+
+    //     -- The type of a template parameter corresponding to a
+    //        specialized non-type argument shall not be dependent on a
+    //        parameter of the specialization.
+    if (Param->getType()->isDependentType()) {
+      S.Diag(ArgExpr->getLocStart(),
+           diag::err_dependent_typed_non_type_arg_in_partial_spec)
+        << Param->getType()
+        << ArgExpr->getSourceRange();
+      S.Diag(Param->getLocation(), diag::note_template_param_here);
+      return true;
+    }
+  }
+
+  return false;
+}
+
+/// \brief Check the non-type template arguments of a class template
+/// partial specialization according to C++ [temp.class.spec]p9.
+///
+/// \param TemplateParams the template parameters of the primary class
+/// template.
+///
+/// \param TemplateArg the template arguments of the class template
+/// partial specialization.
+///
+/// \returns true if there was an error, false otherwise.
+static bool CheckClassTemplatePartialSpecializationArgs(Sema &S,
+                                        TemplateParameterList *TemplateParams,
+                       SmallVectorImpl<TemplateArgument> &TemplateArgs) {
+  const TemplateArgument *ArgList = TemplateArgs.data();
+
+  for (unsigned I = 0, N = TemplateParams->size(); I != N; ++I) {
+    NonTypeTemplateParmDecl *Param
+      = dyn_cast<NonTypeTemplateParmDecl>(TemplateParams->getParam(I));
+    if (!Param)
+      continue;
+
+    if (CheckNonTypeClassTemplatePartialSpecializationArgs(S, Param,
+                                                           &ArgList[I], 1))
+      return true;
+  }
+
+  return false;
+}
+
+DeclResult
+Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec,
+                                       TagUseKind TUK,
+                                       SourceLocation KWLoc,
+                                       SourceLocation ModulePrivateLoc,
+                                       CXXScopeSpec &SS,
+                                       TemplateTy TemplateD,
+                                       SourceLocation TemplateNameLoc,
+                                       SourceLocation LAngleLoc,
+                                       ASTTemplateArgsPtr TemplateArgsIn,
+                                       SourceLocation RAngleLoc,
+                                       AttributeList *Attr,
+                               MultiTemplateParamsArg TemplateParameterLists) {
+  assert(TUK != TUK_Reference && "References are not specializations");
+
+  // NOTE: KWLoc is the location of the tag keyword. This will instead
+  // store the location of the outermost template keyword in the declaration.
+  SourceLocation TemplateKWLoc = TemplateParameterLists.size() > 0
+    ? TemplateParameterLists.get()[0]->getTemplateLoc() : SourceLocation();
+
+  // Find the class template we're specializing
+  TemplateName Name = TemplateD.getAsVal<TemplateName>();
+  ClassTemplateDecl *ClassTemplate
+    = dyn_cast_or_null<ClassTemplateDecl>(Name.getAsTemplateDecl());
+
+  if (!ClassTemplate) {
+    Diag(TemplateNameLoc, diag::err_not_class_template_specialization)
+      << (Name.getAsTemplateDecl() &&
+          isa<TemplateTemplateParmDecl>(Name.getAsTemplateDecl()));
+    return true;
+  }
+
+  bool isExplicitSpecialization = false;
+  bool isPartialSpecialization = false;
+
+  // Check the validity of the template headers that introduce this
+  // template.
+  // FIXME: We probably shouldn't complain about these headers for
+  // friend declarations.
+  bool Invalid = false;
+  TemplateParameterList *TemplateParams
+    = MatchTemplateParametersToScopeSpecifier(TemplateNameLoc, 
+                                              TemplateNameLoc,
+                                              SS,
+                        (TemplateParameterList**)TemplateParameterLists.get(),
+                                              TemplateParameterLists.size(),
+                                              TUK == TUK_Friend,
+                                              isExplicitSpecialization,
+                                              Invalid);
+  if (Invalid)
+    return true;
+
+  if (TemplateParams && TemplateParams->size() > 0) {
+    isPartialSpecialization = true;
+
+    if (TUK == TUK_Friend) {
+      Diag(KWLoc, diag::err_partial_specialization_friend)
+        << SourceRange(LAngleLoc, RAngleLoc);
+      return true;
+    }
+
+    // C++ [temp.class.spec]p10:
+    //   The template parameter list of a specialization shall not
+    //   contain default template argument values.
+    for (unsigned I = 0, N = TemplateParams->size(); I != N; ++I) {
+      Decl *Param = TemplateParams->getParam(I);
+      if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(Param)) {
+        if (TTP->hasDefaultArgument()) {
+          Diag(TTP->getDefaultArgumentLoc(),
+               diag::err_default_arg_in_partial_spec);
+          TTP->removeDefaultArgument();
+        }
+      } else if (NonTypeTemplateParmDecl *NTTP
+                   = dyn_cast<NonTypeTemplateParmDecl>(Param)) {
+        if (Expr *DefArg = NTTP->getDefaultArgument()) {
+          Diag(NTTP->getDefaultArgumentLoc(),
+               diag::err_default_arg_in_partial_spec)
+            << DefArg->getSourceRange();
+          NTTP->removeDefaultArgument();
+        }
+      } else {
+        TemplateTemplateParmDecl *TTP = cast<TemplateTemplateParmDecl>(Param);
+        if (TTP->hasDefaultArgument()) {
+          Diag(TTP->getDefaultArgument().getLocation(),
+               diag::err_default_arg_in_partial_spec)
+            << TTP->getDefaultArgument().getSourceRange();
+          TTP->removeDefaultArgument();
+        }
+      }
+    }
+  } else if (TemplateParams) {
+    if (TUK == TUK_Friend)
+      Diag(KWLoc, diag::err_template_spec_friend)
+        << FixItHint::CreateRemoval(
+                                SourceRange(TemplateParams->getTemplateLoc(),
+                                            TemplateParams->getRAngleLoc()))
+        << SourceRange(LAngleLoc, RAngleLoc);
+    else
+      isExplicitSpecialization = true;
+  } else if (TUK != TUK_Friend) {
+    Diag(KWLoc, diag::err_template_spec_needs_header)
+      << FixItHint::CreateInsertion(KWLoc, "template<> ");
+    isExplicitSpecialization = true;
+  }
+
+  // Check that the specialization uses the same tag kind as the
+  // original template.
+  TagTypeKind Kind = TypeWithKeyword::getTagTypeKindForTypeSpec(TagSpec);
+  assert(Kind != TTK_Enum && "Invalid enum tag in class template spec!");
+  if (!isAcceptableTagRedeclaration(ClassTemplate->getTemplatedDecl(),
+                                    Kind, TUK == TUK_Definition, KWLoc,
+                                    *ClassTemplate->getIdentifier())) {
+    Diag(KWLoc, diag::err_use_with_wrong_tag)
+      << ClassTemplate
+      << FixItHint::CreateReplacement(KWLoc,
+                            ClassTemplate->getTemplatedDecl()->getKindName());
+    Diag(ClassTemplate->getTemplatedDecl()->getLocation(),
+         diag::note_previous_use);
+    Kind = ClassTemplate->getTemplatedDecl()->getTagKind();
+  }
+
+  // Translate the parser's template argument list in our AST format.
+  TemplateArgumentListInfo TemplateArgs;
+  TemplateArgs.setLAngleLoc(LAngleLoc);
+  TemplateArgs.setRAngleLoc(RAngleLoc);
+  translateTemplateArguments(TemplateArgsIn, TemplateArgs);
+
+  // Check for unexpanded parameter packs in any of the template arguments.
+  for (unsigned I = 0, N = TemplateArgs.size(); I != N; ++I)
+    if (DiagnoseUnexpandedParameterPack(TemplateArgs[I],
+                                        UPPC_PartialSpecialization))
+      return true;
+
+  // Check that the template argument list is well-formed for this
+  // template.
+  SmallVector<TemplateArgument, 4> Converted;
+  if (CheckTemplateArgumentList(ClassTemplate, TemplateNameLoc,
+                                TemplateArgs, false, Converted))
+    return true;
+
+  // Find the class template (partial) specialization declaration that
+  // corresponds to these arguments.
+  if (isPartialSpecialization) {
+    if (CheckClassTemplatePartialSpecializationArgs(*this,
+                                         ClassTemplate->getTemplateParameters(),
+                                         Converted))
+      return true;
+
+    bool InstantiationDependent;
+    if (!Name.isDependent() &&
+        !TemplateSpecializationType::anyDependentTemplateArguments(
+                                             TemplateArgs.getArgumentArray(),
+                                                         TemplateArgs.size(),
+                                                     InstantiationDependent)) {
+      Diag(TemplateNameLoc, diag::err_partial_spec_fully_specialized)
+        << ClassTemplate->getDeclName();
+      isPartialSpecialization = false;
+    }
+  }
+
+  void *InsertPos = 0;
+  ClassTemplateSpecializationDecl *PrevDecl = 0;
+
+  if (isPartialSpecialization)
+    // FIXME: Template parameter list matters, too
+    PrevDecl
+      = ClassTemplate->findPartialSpecialization(Converted.data(),
+                                                 Converted.size(),
+                                                 InsertPos);
+  else
+    PrevDecl
+      = ClassTemplate->findSpecialization(Converted.data(),
+                                          Converted.size(), InsertPos);
+
+  ClassTemplateSpecializationDecl *Specialization = 0;
+
+  // Check whether we can declare a class template specialization in
+  // the current scope.
+  if (TUK != TUK_Friend &&
+      CheckTemplateSpecializationScope(*this, ClassTemplate, PrevDecl,
+                                       TemplateNameLoc,
+                                       isPartialSpecialization))
+    return true;
+
+  // The canonical type
+  QualType CanonType;
+  if (PrevDecl &&
+      (PrevDecl->getSpecializationKind() == TSK_Undeclared ||
+               TUK == TUK_Friend)) {
+    // Since the only prior class template specialization with these
+    // arguments was referenced but not declared, or we're only
+    // referencing this specialization as a friend, reuse that
+    // declaration node as our own, updating its source location and
+    // the list of outer template parameters to reflect our new declaration.
+    Specialization = PrevDecl;
+    Specialization->setLocation(TemplateNameLoc);
+    if (TemplateParameterLists.size() > 0) {
+      Specialization->setTemplateParameterListsInfo(Context,
+                                              TemplateParameterLists.size(),
+                    (TemplateParameterList**) TemplateParameterLists.release());
+    }
+    PrevDecl = 0;
+    CanonType = Context.getTypeDeclType(Specialization);
+  } else if (isPartialSpecialization) {
+    // Build the canonical type that describes the converted template
+    // arguments of the class template partial specialization.
+    TemplateName CanonTemplate = Context.getCanonicalTemplateName(Name);
+    CanonType = Context.getTemplateSpecializationType(CanonTemplate,
+                                                      Converted.data(),
+                                                      Converted.size());
+
+    if (Context.hasSameType(CanonType,
+                        ClassTemplate->getInjectedClassNameSpecialization())) {
+      // C++ [temp.class.spec]p9b3:
+      //
+      //   -- The argument list of the specialization shall not be identical
+      //      to the implicit argument list of the primary template.
+      Diag(TemplateNameLoc, diag::err_partial_spec_args_match_primary_template)
+        << (TUK == TUK_Definition)
+        << FixItHint::CreateRemoval(SourceRange(LAngleLoc, RAngleLoc));
+      return CheckClassTemplate(S, TagSpec, TUK, KWLoc, SS,
+                                ClassTemplate->getIdentifier(),
+                                TemplateNameLoc,
+                                Attr,
+                                TemplateParams,
+                                AS_none, /*ModulePrivateLoc=*/SourceLocation(),
+                                TemplateParameterLists.size() - 1,
+                  (TemplateParameterList**) TemplateParameterLists.release());
+    }
+
+    // Create a new class template partial specialization declaration node.
+    ClassTemplatePartialSpecializationDecl *PrevPartial
+      = cast_or_null<ClassTemplatePartialSpecializationDecl>(PrevDecl);
+    unsigned SequenceNumber = PrevPartial? PrevPartial->getSequenceNumber()
+                            : ClassTemplate->getNextPartialSpecSequenceNumber();
+    ClassTemplatePartialSpecializationDecl *Partial
+      = ClassTemplatePartialSpecializationDecl::Create(Context, Kind,
+                                             ClassTemplate->getDeclContext(),
+                                                       KWLoc, TemplateNameLoc,
+                                                       TemplateParams,
+                                                       ClassTemplate,
+                                                       Converted.data(),
+                                                       Converted.size(),
+                                                       TemplateArgs,
+                                                       CanonType,
+                                                       PrevPartial,
+                                                       SequenceNumber);
+    SetNestedNameSpecifier(Partial, SS);
+    if (TemplateParameterLists.size() > 1 && SS.isSet()) {
+      Partial->setTemplateParameterListsInfo(Context,
+                                             TemplateParameterLists.size() - 1,
+                    (TemplateParameterList**) TemplateParameterLists.release());
+    }
+
+    if (!PrevPartial)
+      ClassTemplate->AddPartialSpecialization(Partial, InsertPos);
+    Specialization = Partial;
+
+    // If we are providing an explicit specialization of a member class
+    // template specialization, make a note of that.
+    if (PrevPartial && PrevPartial->getInstantiatedFromMember())
+      PrevPartial->setMemberSpecialization();
+
+    // Check that all of the template parameters of the class template
+    // partial specialization are deducible from the template
+    // arguments. If not, this class template partial specialization
+    // will never be used.
+    llvm::SmallBitVector DeducibleParams(TemplateParams->size());
+    MarkUsedTemplateParameters(Partial->getTemplateArgs(), true,
+                               TemplateParams->getDepth(),
+                               DeducibleParams);
+
+    if (!DeducibleParams.all()) {
+      unsigned NumNonDeducible = DeducibleParams.size()-DeducibleParams.count();
+      Diag(TemplateNameLoc, diag::warn_partial_specs_not_deducible)
+        << (NumNonDeducible > 1)
+        << SourceRange(TemplateNameLoc, RAngleLoc);
+      for (unsigned I = 0, N = DeducibleParams.size(); I != N; ++I) {
+        if (!DeducibleParams[I]) {
+          NamedDecl *Param = cast<NamedDecl>(TemplateParams->getParam(I));
+          if (Param->getDeclName())
+            Diag(Param->getLocation(),
+                 diag::note_partial_spec_unused_parameter)
+              << Param->getDeclName();
+          else
+            Diag(Param->getLocation(),
+                 diag::note_partial_spec_unused_parameter)
+              << "<anonymous>";
+        }
+      }
+    }
+  } else {
+    // Create a new class template specialization declaration node for
+    // this explicit specialization or friend declaration.
+    Specialization
+      = ClassTemplateSpecializationDecl::Create(Context, Kind,
+                                             ClassTemplate->getDeclContext(),
+                                                KWLoc, TemplateNameLoc,
+                                                ClassTemplate,
+                                                Converted.data(),
+                                                Converted.size(),
+                                                PrevDecl);
+    SetNestedNameSpecifier(Specialization, SS);
+    if (TemplateParameterLists.size() > 0) {
+      Specialization->setTemplateParameterListsInfo(Context,
+                                              TemplateParameterLists.size(),
+                    (TemplateParameterList**) TemplateParameterLists.release());
+    }
+
+    if (!PrevDecl)
+      ClassTemplate->AddSpecialization(Specialization, InsertPos);
+
+    CanonType = Context.getTypeDeclType(Specialization);
+  }
+
+  // C++ [temp.expl.spec]p6:
+  //   If a template, a member template or the member of a class template is
+  //   explicitly specialized then that specialization shall be declared
+  //   before the first use of that specialization that would cause an implicit
+  //   instantiation to take place, in every translation unit in which such a
+  //   use occurs; no diagnostic is required.
+  if (PrevDecl && PrevDecl->getPointOfInstantiation().isValid()) {
+    bool Okay = false;
+    for (Decl *Prev = PrevDecl; Prev; Prev = Prev->getPreviousDecl()) {
+      // Is there any previous explicit specialization declaration?
+      if (getTemplateSpecializationKind(Prev) == TSK_ExplicitSpecialization) {
+        Okay = true;
+        break;
+      }
+    }
+
+    if (!Okay) {
+      SourceRange Range(TemplateNameLoc, RAngleLoc);
+      Diag(TemplateNameLoc, diag::err_specialization_after_instantiation)
+        << Context.getTypeDeclType(Specialization) << Range;
+
+      Diag(PrevDecl->getPointOfInstantiation(),
+           diag::note_instantiation_required_here)
+        << (PrevDecl->getTemplateSpecializationKind()
+                                                != TSK_ImplicitInstantiation);
+      return true;
+    }
+  }
+
+  // If this is not a friend, note that this is an explicit specialization.
+  if (TUK != TUK_Friend)
+    Specialization->setSpecializationKind(TSK_ExplicitSpecialization);
+
+  // Check that this isn't a redefinition of this specialization.
+  if (TUK == TUK_Definition) {
+    if (RecordDecl *Def = Specialization->getDefinition()) {
+      SourceRange Range(TemplateNameLoc, RAngleLoc);
+      Diag(TemplateNameLoc, diag::err_redefinition)
+        << Context.getTypeDeclType(Specialization) << Range;
+      Diag(Def->getLocation(), diag::note_previous_definition);
+      Specialization->setInvalidDecl();
+      return true;
+    }
+  }
+
+  if (Attr)
+    ProcessDeclAttributeList(S, Specialization, Attr);
+
+  if (ModulePrivateLoc.isValid())
+    Diag(Specialization->getLocation(), diag::err_module_private_specialization)
+      << (isPartialSpecialization? 1 : 0)
+      << FixItHint::CreateRemoval(ModulePrivateLoc);
+  
+  // Build the fully-sugared type for this class template
+  // specialization as the user wrote in the specialization
+  // itself. This means that we'll pretty-print the type retrieved
+  // from the specialization's declaration the way that the user
+  // actually wrote the specialization, rather than formatting the
+  // name based on the "canonical" representation used to store the
+  // template arguments in the specialization.
+  TypeSourceInfo *WrittenTy
+    = Context.getTemplateSpecializationTypeInfo(Name, TemplateNameLoc,
+                                                TemplateArgs, CanonType);
+  if (TUK != TUK_Friend) {
+    Specialization->setTypeAsWritten(WrittenTy);
+    Specialization->setTemplateKeywordLoc(TemplateKWLoc);
+  }
+  TemplateArgsIn.release();
+
+  // C++ [temp.expl.spec]p9:
+  //   A template explicit specialization is in the scope of the
+  //   namespace in which the template was defined.
+  //
+  // We actually implement this paragraph where we set the semantic
+  // context (in the creation of the ClassTemplateSpecializationDecl),
+  // but we also maintain the lexical context where the actual
+  // definition occurs.
+  Specialization->setLexicalDeclContext(CurContext);
+
+  // We may be starting the definition of this specialization.
+  if (TUK == TUK_Definition)
+    Specialization->startDefinition();
+
+  if (TUK == TUK_Friend) {
+    FriendDecl *Friend = FriendDecl::Create(Context, CurContext,
+                                            TemplateNameLoc,
+                                            WrittenTy,
+                                            /*FIXME:*/KWLoc);
+    Friend->setAccess(AS_public);
+    CurContext->addDecl(Friend);
+  } else {
+    // Add the specialization into its lexical context, so that it can
+    // be seen when iterating through the list of declarations in that
+    // context. However, specializations are not found by name lookup.
+    CurContext->addDecl(Specialization);
+  }
+  return Specialization;
+}
+
+Decl *Sema::ActOnTemplateDeclarator(Scope *S,
+                              MultiTemplateParamsArg TemplateParameterLists,
+                                    Declarator &D) {
+  return HandleDeclarator(S, D, move(TemplateParameterLists));
+}
+
+Decl *Sema::ActOnStartOfFunctionTemplateDef(Scope *FnBodyScope,
+                               MultiTemplateParamsArg TemplateParameterLists,
+                                            Declarator &D) {
+  assert(getCurFunctionDecl() == 0 && "Function parsing confused");
+  DeclaratorChunk::FunctionTypeInfo &FTI = D.getFunctionTypeInfo();
+
+  if (FTI.hasPrototype) {
+    // FIXME: Diagnose arguments without names in C.
+  }
+
+  Scope *ParentScope = FnBodyScope->getParent();
+
+  D.setFunctionDefinitionKind(FDK_Definition);
+  Decl *DP = HandleDeclarator(ParentScope, D,
+                              move(TemplateParameterLists));
+  if (FunctionTemplateDecl *FunctionTemplate
+        = dyn_cast_or_null<FunctionTemplateDecl>(DP))
+    return ActOnStartOfFunctionDef(FnBodyScope,
+                                   FunctionTemplate->getTemplatedDecl());
+  if (FunctionDecl *Function = dyn_cast_or_null<FunctionDecl>(DP))
+    return ActOnStartOfFunctionDef(FnBodyScope, Function);
+  return 0;
+}
+
+/// \brief Strips various properties off an implicit instantiation
+/// that has just been explicitly specialized.
+static void StripImplicitInstantiation(NamedDecl *D) {
+  // FIXME: "make check" is clean if the call to dropAttrs() is commented out.
+  D->dropAttrs();
+
+  if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
+    FD->setInlineSpecified(false);
+  }
+}
+
+/// \brief Compute the diagnostic location for an explicit instantiation
+//  declaration or definition.
+static SourceLocation DiagLocForExplicitInstantiation(
+    NamedDecl* D, SourceLocation PointOfInstantiation) {
+  // Explicit instantiations following a specialization have no effect and
+  // hence no PointOfInstantiation. In that case, walk decl backwards
+  // until a valid name loc is found.
+  SourceLocation PrevDiagLoc = PointOfInstantiation;
+  for (Decl *Prev = D; Prev && !PrevDiagLoc.isValid();
+       Prev = Prev->getPreviousDecl()) {
+    PrevDiagLoc = Prev->getLocation();
+  }
+  assert(PrevDiagLoc.isValid() &&
+         "Explicit instantiation without point of instantiation?");
+  return PrevDiagLoc;
+}
+
+/// \brief Diagnose cases where we have an explicit template specialization
+/// before/after an explicit template instantiation, producing diagnostics
+/// for those cases where they are required and determining whether the
+/// new specialization/instantiation will have any effect.
+///
+/// \param NewLoc the location of the new explicit specialization or
+/// instantiation.
+///
+/// \param NewTSK the kind of the new explicit specialization or instantiation.
+///
+/// \param PrevDecl the previous declaration of the entity.
+///
+/// \param PrevTSK the kind of the old explicit specialization or instantiatin.
+///
+/// \param PrevPointOfInstantiation if valid, indicates where the previus
+/// declaration was instantiated (either implicitly or explicitly).
+///
+/// \param HasNoEffect will be set to true to indicate that the new
+/// specialization or instantiation has no effect and should be ignored.
+///
+/// \returns true if there was an error that should prevent the introduction of
+/// the new declaration into the AST, false otherwise.
+bool
+Sema::CheckSpecializationInstantiationRedecl(SourceLocation NewLoc,
+                                             TemplateSpecializationKind NewTSK,
+                                             NamedDecl *PrevDecl,
+                                             TemplateSpecializationKind PrevTSK,
+                                        SourceLocation PrevPointOfInstantiation,
+                                             bool &HasNoEffect) {
+  HasNoEffect = false;
+
+  switch (NewTSK) {
+  case TSK_Undeclared:
+  case TSK_ImplicitInstantiation:
+    llvm_unreachable("Don't check implicit instantiations here");
+
+  case TSK_ExplicitSpecialization:
+    switch (PrevTSK) {
+    case TSK_Undeclared:
+    case TSK_ExplicitSpecialization:
+      // Okay, we're just specializing something that is either already
+      // explicitly specialized or has merely been mentioned without any
+      // instantiation.
+      return false;
+
+    case TSK_ImplicitInstantiation:
+      if (PrevPointOfInstantiation.isInvalid()) {
+        // The declaration itself has not actually been instantiated, so it is
+        // still okay to specialize it.
+        StripImplicitInstantiation(PrevDecl);
+        return false;
+      }
+      // Fall through
+
+    case TSK_ExplicitInstantiationDeclaration:
+    case TSK_ExplicitInstantiationDefinition:
+      assert((PrevTSK == TSK_ImplicitInstantiation ||
+              PrevPointOfInstantiation.isValid()) &&
+             "Explicit instantiation without point of instantiation?");
+
+      // C++ [temp.expl.spec]p6:
+      //   If a template, a member template or the member of a class template
+      //   is explicitly specialized then that specialization shall be declared
+      //   before the first use of that specialization that would cause an
+      //   implicit instantiation to take place, in every translation unit in
+      //   which such a use occurs; no diagnostic is required.
+      for (Decl *Prev = PrevDecl; Prev; Prev = Prev->getPreviousDecl()) {
+        // Is there any previous explicit specialization declaration?
+        if (getTemplateSpecializationKind(Prev) == TSK_ExplicitSpecialization)
+          return false;
+      }
+
+      Diag(NewLoc, diag::err_specialization_after_instantiation)
+        << PrevDecl;
+      Diag(PrevPointOfInstantiation, diag::note_instantiation_required_here)
+        << (PrevTSK != TSK_ImplicitInstantiation);
+
+      return true;
+    }
+
+  case TSK_ExplicitInstantiationDeclaration:
+    switch (PrevTSK) {
+    case TSK_ExplicitInstantiationDeclaration:
+      // This explicit instantiation declaration is redundant (that's okay).
+      HasNoEffect = true;
+      return false;
+
+    case TSK_Undeclared:
+    case TSK_ImplicitInstantiation:
+      // We're explicitly instantiating something that may have already been
+      // implicitly instantiated; that's fine.
+      return false;
+
+    case TSK_ExplicitSpecialization:
+      // C++0x [temp.explicit]p4:
+      //   For a given set of template parameters, if an explicit instantiation
+      //   of a template appears after a declaration of an explicit
+      //   specialization for that template, the explicit instantiation has no
+      //   effect.
+      HasNoEffect = true;
+      return false;
+
+    case TSK_ExplicitInstantiationDefinition:
+      // C++0x [temp.explicit]p10:
+      //   If an entity is the subject of both an explicit instantiation
+      //   declaration and an explicit instantiation definition in the same
+      //   translation unit, the definition shall follow the declaration.
+      Diag(NewLoc,
+           diag::err_explicit_instantiation_declaration_after_definition);
+
+      // Explicit instantiations following a specialization have no effect and
+      // hence no PrevPointOfInstantiation. In that case, walk decl backwards
+      // until a valid name loc is found.
+      Diag(DiagLocForExplicitInstantiation(PrevDecl, PrevPointOfInstantiation),
+           diag::note_explicit_instantiation_definition_here);
+      HasNoEffect = true;
+      return false;
+    }
+
+  case TSK_ExplicitInstantiationDefinition:
+    switch (PrevTSK) {
+    case TSK_Undeclared:
+    case TSK_ImplicitInstantiation:
+      // We're explicitly instantiating something that may have already been
+      // implicitly instantiated; that's fine.
+      return false;
+
+    case TSK_ExplicitSpecialization:
+      // C++ DR 259, C++0x [temp.explicit]p4:
+      //   For a given set of template parameters, if an explicit
+      //   instantiation of a template appears after a declaration of
+      //   an explicit specialization for that template, the explicit
+      //   instantiation has no effect.
+      //
+      // In C++98/03 mode, we only give an extension warning here, because it
+      // is not harmful to try to explicitly instantiate something that
+      // has been explicitly specialized.
+      Diag(NewLoc, getLangOpts().CPlusPlus0x ?
+           diag::warn_cxx98_compat_explicit_instantiation_after_specialization :
+           diag::ext_explicit_instantiation_after_specialization)
+        << PrevDecl;
+      Diag(PrevDecl->getLocation(),
+           diag::note_previous_template_specialization);
+      HasNoEffect = true;
+      return false;
+
+    case TSK_ExplicitInstantiationDeclaration:
+      // We're explicity instantiating a definition for something for which we
+      // were previously asked to suppress instantiations. That's fine.
+
+      // C++0x [temp.explicit]p4:
+      //   For a given set of template parameters, if an explicit instantiation
+      //   of a template appears after a declaration of an explicit
+      //   specialization for that template, the explicit instantiation has no
+      //   effect.
+      for (Decl *Prev = PrevDecl; Prev; Prev = Prev->getPreviousDecl()) {
+        // Is there any previous explicit specialization declaration?
+        if (getTemplateSpecializationKind(Prev) == TSK_ExplicitSpecialization) {
+          HasNoEffect = true;
+          break;
+        }
+      }
+
+      return false;
+
+    case TSK_ExplicitInstantiationDefinition:
+      // C++0x [temp.spec]p5:
+      //   For a given template and a given set of template-arguments,
+      //     - an explicit instantiation definition shall appear at most once
+      //       in a program,
+      Diag(NewLoc, diag::err_explicit_instantiation_duplicate)
+        << PrevDecl;
+      Diag(DiagLocForExplicitInstantiation(PrevDecl, PrevPointOfInstantiation),
+           diag::note_previous_explicit_instantiation);
+      HasNoEffect = true;
+      return false;
+    }
+  }
+
+  llvm_unreachable("Missing specialization/instantiation case?");
+}
+
+/// \brief Perform semantic analysis for the given dependent function
+/// template specialization.  The only possible way to get a dependent
+/// function template specialization is with a friend declaration,
+/// like so:
+///
+///   template <class T> void foo(T);
+///   template <class T> class A {
+///     friend void foo<>(T);
+///   };
+///
+/// There really isn't any useful analysis we can do here, so we
+/// just store the information.
+bool
+Sema::CheckDependentFunctionTemplateSpecialization(FunctionDecl *FD,
+                   const TemplateArgumentListInfo &ExplicitTemplateArgs,
+                                                   LookupResult &Previous) {
+  // Remove anything from Previous that isn't a function template in
+  // the correct context.
+  DeclContext *FDLookupContext = FD->getDeclContext()->getRedeclContext();
+  LookupResult::Filter F = Previous.makeFilter();
+  while (F.hasNext()) {
+    NamedDecl *D = F.next()->getUnderlyingDecl();
+    if (!isa<FunctionTemplateDecl>(D) ||
+        !FDLookupContext->InEnclosingNamespaceSetOf(
+                              D->getDeclContext()->getRedeclContext()))
+      F.erase();
+  }
+  F.done();
+
+  // Should this be diagnosed here?
+  if (Previous.empty()) return true;
+
+  FD->setDependentTemplateSpecialization(Context, Previous.asUnresolvedSet(),
+                                         ExplicitTemplateArgs);
+  return false;
+}
+
+/// \brief Perform semantic analysis for the given function template
+/// specialization.
+///
+/// This routine performs all of the semantic analysis required for an
+/// explicit function template specialization. On successful completion,
+/// the function declaration \p FD will become a function template
+/// specialization.
+///
+/// \param FD the function declaration, which will be updated to become a
+/// function template specialization.
+///
+/// \param ExplicitTemplateArgs the explicitly-provided template arguments,
+/// if any. Note that this may be valid info even when 0 arguments are
+/// explicitly provided as in, e.g., \c void sort<>(char*, char*);
+/// as it anyway contains info on the angle brackets locations.
+///
+/// \param Previous the set of declarations that may be specialized by
+/// this function specialization.
+bool
+Sema::CheckFunctionTemplateSpecialization(FunctionDecl *FD,
+                                 TemplateArgumentListInfo *ExplicitTemplateArgs,
+                                          LookupResult &Previous) {
+  // The set of function template specializations that could match this
+  // explicit function template specialization.
+  UnresolvedSet<8> Candidates;
+
+  DeclContext *FDLookupContext = FD->getDeclContext()->getRedeclContext();
+  for (LookupResult::iterator I = Previous.begin(), E = Previous.end();
+         I != E; ++I) {
+    NamedDecl *Ovl = (*I)->getUnderlyingDecl();
+    if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(Ovl)) {
+      // Only consider templates found within the same semantic lookup scope as
+      // FD.
+      if (!FDLookupContext->InEnclosingNamespaceSetOf(
+                                Ovl->getDeclContext()->getRedeclContext()))
+        continue;
+
+      // C++ [temp.expl.spec]p11:
+      //   A trailing template-argument can be left unspecified in the
+      //   template-id naming an explicit function template specialization
+      //   provided it can be deduced from the function argument type.
+      // Perform template argument deduction to determine whether we may be
+      // specializing this template.
+      // FIXME: It is somewhat wasteful to build
+      TemplateDeductionInfo Info(Context, FD->getLocation());
+      FunctionDecl *Specialization = 0;
+      if (TemplateDeductionResult TDK
+            = DeduceTemplateArguments(FunTmpl, ExplicitTemplateArgs,
+                                      FD->getType(),
+                                      Specialization,
+                                      Info)) {
+        // FIXME: Template argument deduction failed; record why it failed, so
+        // that we can provide nifty diagnostics.
+        (void)TDK;
+        continue;
+      }
+
+      // Record this candidate.
+      Candidates.addDecl(Specialization, I.getAccess());
+    }
+  }
+
+  // Find the most specialized function template.
+  UnresolvedSetIterator Result
+    = getMostSpecialized(Candidates.begin(), Candidates.end(),
+                         TPOC_Other, 0, FD->getLocation(),
+                  PDiag(diag::err_function_template_spec_no_match)
+                    << FD->getDeclName(),
+                  PDiag(diag::err_function_template_spec_ambiguous)
+                    << FD->getDeclName() << (ExplicitTemplateArgs != 0),
+                  PDiag(diag::note_function_template_spec_matched));
+  if (Result == Candidates.end())
+    return true;
+
+  // Ignore access information;  it doesn't figure into redeclaration checking.
+  FunctionDecl *Specialization = cast<FunctionDecl>(*Result);
+
+  FunctionTemplateSpecializationInfo *SpecInfo
+    = Specialization->getTemplateSpecializationInfo();
+  assert(SpecInfo && "Function template specialization info missing?");
+
+  // Note: do not overwrite location info if previous template
+  // specialization kind was explicit.
+  TemplateSpecializationKind TSK = SpecInfo->getTemplateSpecializationKind();
+  if (TSK == TSK_Undeclared || TSK == TSK_ImplicitInstantiation) {
+    Specialization->setLocation(FD->getLocation());
+    // C++11 [dcl.constexpr]p1: An explicit specialization of a constexpr
+    // function can differ from the template declaration with respect to
+    // the constexpr specifier.
+    Specialization->setConstexpr(FD->isConstexpr());
+  }
+
+  // FIXME: Check if the prior specialization has a point of instantiation.
+  // If so, we have run afoul of .
+
+  // If this is a friend declaration, then we're not really declaring
+  // an explicit specialization.
+  bool isFriend = (FD->getFriendObjectKind() != Decl::FOK_None);
+
+  // Check the scope of this explicit specialization.
+  if (!isFriend &&
+      CheckTemplateSpecializationScope(*this,
+                                       Specialization->getPrimaryTemplate(),
+                                       Specialization, FD->getLocation(),
+                                       false))
+    return true;
+
+  // C++ [temp.expl.spec]p6:
+  //   If a template, a member template or the member of a class template is
+  //   explicitly specialized then that specialization shall be declared
+  //   before the first use of that specialization that would cause an implicit
+  //   instantiation to take place, in every translation unit in which such a
+  //   use occurs; no diagnostic is required.
+  bool HasNoEffect = false;
+  if (!isFriend &&
+      CheckSpecializationInstantiationRedecl(FD->getLocation(),
+                                             TSK_ExplicitSpecialization,
+                                             Specialization,
+                                   SpecInfo->getTemplateSpecializationKind(),
+                                         SpecInfo->getPointOfInstantiation(),
+                                             HasNoEffect))
+    return true;
+  
+  // Mark the prior declaration as an explicit specialization, so that later
+  // clients know that this is an explicit specialization.
+  if (!isFriend) {
+    SpecInfo->setTemplateSpecializationKind(TSK_ExplicitSpecialization);
+    MarkUnusedFileScopedDecl(Specialization);
+  }
+
+  // Turn the given function declaration into a function template
+  // specialization, with the template arguments from the previous
+  // specialization.
+  // Take copies of (semantic and syntactic) template argument lists.
+  const TemplateArgumentList* TemplArgs = new (Context)
+    TemplateArgumentList(Specialization->getTemplateSpecializationArgs());
+  FD->setFunctionTemplateSpecialization(Specialization->getPrimaryTemplate(),
+                                        TemplArgs, /*InsertPos=*/0,
+                                    SpecInfo->getTemplateSpecializationKind(),
+                                        ExplicitTemplateArgs);
+  FD->setStorageClass(Specialization->getStorageClass());
+  
+  // The "previous declaration" for this function template specialization is
+  // the prior function template specialization.
+  Previous.clear();
+  Previous.addDecl(Specialization);
+  return false;
+}
+
+/// \brief Perform semantic analysis for the given non-template member
+/// specialization.
+///
+/// This routine performs all of the semantic analysis required for an
+/// explicit member function specialization. On successful completion,
+/// the function declaration \p FD will become a member function
+/// specialization.
+///
+/// \param Member the member declaration, which will be updated to become a
+/// specialization.
+///
+/// \param Previous the set of declarations, one of which may be specialized
+/// by this function specialization;  the set will be modified to contain the
+/// redeclared member.
+bool
+Sema::CheckMemberSpecialization(NamedDecl *Member, LookupResult &Previous) {
+  assert(!isa<TemplateDecl>(Member) && "Only for non-template members");
+
+  // Try to find the member we are instantiating.
+  NamedDecl *Instantiation = 0;
+  NamedDecl *InstantiatedFrom = 0;
+  MemberSpecializationInfo *MSInfo = 0;
+
+  if (Previous.empty()) {
+    // Nowhere to look anyway.
+  } else if (FunctionDecl *Function = dyn_cast<FunctionDecl>(Member)) {
+    for (LookupResult::iterator I = Previous.begin(), E = Previous.end();
+           I != E; ++I) {
+      NamedDecl *D = (*I)->getUnderlyingDecl();
+      if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(D)) {
+        if (Context.hasSameType(Function->getType(), Method->getType())) {
+          Instantiation = Method;
+          InstantiatedFrom = Method->getInstantiatedFromMemberFunction();
+          MSInfo = Method->getMemberSpecializationInfo();
+          break;
+        }
+      }
+    }
+  } else if (isa<VarDecl>(Member)) {
+    VarDecl *PrevVar;
+    if (Previous.isSingleResult() &&
+        (PrevVar = dyn_cast<VarDecl>(Previous.getFoundDecl())))
+      if (PrevVar->isStaticDataMember()) {
+        Instantiation = PrevVar;
+        InstantiatedFrom = PrevVar->getInstantiatedFromStaticDataMember();
+        MSInfo = PrevVar->getMemberSpecializationInfo();
+      }
+  } else if (isa<RecordDecl>(Member)) {
+    CXXRecordDecl *PrevRecord;
+    if (Previous.isSingleResult() &&
+        (PrevRecord = dyn_cast<CXXRecordDecl>(Previous.getFoundDecl()))) {
+      Instantiation = PrevRecord;
+      InstantiatedFrom = PrevRecord->getInstantiatedFromMemberClass();
+      MSInfo = PrevRecord->getMemberSpecializationInfo();
+    }
+  } else if (isa<EnumDecl>(Member)) {
+    EnumDecl *PrevEnum;
+    if (Previous.isSingleResult() &&
+        (PrevEnum = dyn_cast<EnumDecl>(Previous.getFoundDecl()))) {
+      Instantiation = PrevEnum;
+      InstantiatedFrom = PrevEnum->getInstantiatedFromMemberEnum();
+      MSInfo = PrevEnum->getMemberSpecializationInfo();
+    }
+  }
+
+  if (!Instantiation) {
+    // There is no previous declaration that matches. Since member
+    // specializations are always out-of-line, the caller will complain about
+    // this mismatch later.
+    return false;
+  }
+
+  // If this is a friend, just bail out here before we start turning
+  // things into explicit specializations.
+  if (Member->getFriendObjectKind() != Decl::FOK_None) {
+    // Preserve instantiation information.
+    if (InstantiatedFrom && isa<CXXMethodDecl>(Member)) {
+      cast<CXXMethodDecl>(Member)->setInstantiationOfMemberFunction(
+                                      cast<CXXMethodDecl>(InstantiatedFrom),
+        cast<CXXMethodDecl>(Instantiation)->getTemplateSpecializationKind());
+    } else if (InstantiatedFrom && isa<CXXRecordDecl>(Member)) {
+      cast<CXXRecordDecl>(Member)->setInstantiationOfMemberClass(
+                                      cast<CXXRecordDecl>(InstantiatedFrom),
+        cast<CXXRecordDecl>(Instantiation)->getTemplateSpecializationKind());
+    }
+
+    Previous.clear();
+    Previous.addDecl(Instantiation);
+    return false;
+  }
+
+  // Make sure that this is a specialization of a member.
+  if (!InstantiatedFrom) {
+    Diag(Member->getLocation(), diag::err_spec_member_not_instantiated)
+      << Member;
+    Diag(Instantiation->getLocation(), diag::note_specialized_decl);
+    return true;
+  }
+
+  // C++ [temp.expl.spec]p6:
+  //   If a template, a member template or the member of a class template is
+  //   explicitly specialized then that specialization shall be declared
+  //   before the first use of that specialization that would cause an implicit
+  //   instantiation to take place, in every translation unit in which such a
+  //   use occurs; no diagnostic is required.
+  assert(MSInfo && "Member specialization info missing?");
+
+  bool HasNoEffect = false;
+  if (CheckSpecializationInstantiationRedecl(Member->getLocation(),
+                                             TSK_ExplicitSpecialization,
+                                             Instantiation,
+                                     MSInfo->getTemplateSpecializationKind(),
+                                           MSInfo->getPointOfInstantiation(),
+                                             HasNoEffect))
+    return true;
+
+  // Check the scope of this explicit specialization.
+  if (CheckTemplateSpecializationScope(*this,
+                                       InstantiatedFrom,
+                                       Instantiation, Member->getLocation(),
+                                       false))
+    return true;
+
+  // Note that this is an explicit instantiation of a member.
+  // the original declaration to note that it is an explicit specialization
+  // (if it was previously an implicit instantiation). This latter step
+  // makes bookkeeping easier.
+  if (isa<FunctionDecl>(Member)) {
+    FunctionDecl *InstantiationFunction = cast<FunctionDecl>(Instantiation);
+    if (InstantiationFunction->getTemplateSpecializationKind() ==
+          TSK_ImplicitInstantiation) {
+      InstantiationFunction->setTemplateSpecializationKind(
+                                                  TSK_ExplicitSpecialization);
+      InstantiationFunction->setLocation(Member->getLocation());
+    }
+
+    cast<FunctionDecl>(Member)->setInstantiationOfMemberFunction(
+                                        cast<CXXMethodDecl>(InstantiatedFrom),
+                                                  TSK_ExplicitSpecialization);
+    MarkUnusedFileScopedDecl(InstantiationFunction);
+  } else if (isa<VarDecl>(Member)) {
+    VarDecl *InstantiationVar = cast<VarDecl>(Instantiation);
+    if (InstantiationVar->getTemplateSpecializationKind() ==
+          TSK_ImplicitInstantiation) {
+      InstantiationVar->setTemplateSpecializationKind(
+                                                  TSK_ExplicitSpecialization);
+      InstantiationVar->setLocation(Member->getLocation());
+    }
+
+    Context.setInstantiatedFromStaticDataMember(cast<VarDecl>(Member),
+                                                cast<VarDecl>(InstantiatedFrom),
+                                                TSK_ExplicitSpecialization);
+    MarkUnusedFileScopedDecl(InstantiationVar);
+  } else if (isa<CXXRecordDecl>(Member)) {
+    CXXRecordDecl *InstantiationClass = cast<CXXRecordDecl>(Instantiation);
+    if (InstantiationClass->getTemplateSpecializationKind() ==
+          TSK_ImplicitInstantiation) {
+      InstantiationClass->setTemplateSpecializationKind(
+                                                   TSK_ExplicitSpecialization);
+      InstantiationClass->setLocation(Member->getLocation());
+    }
+
+    cast<CXXRecordDecl>(Member)->setInstantiationOfMemberClass(
+                                        cast<CXXRecordDecl>(InstantiatedFrom),
+                                                   TSK_ExplicitSpecialization);
+  } else {
+    assert(isa<EnumDecl>(Member) && "Only member enums remain");
+    EnumDecl *InstantiationEnum = cast<EnumDecl>(Instantiation);
+    if (InstantiationEnum->getTemplateSpecializationKind() ==
+          TSK_ImplicitInstantiation) {
+      InstantiationEnum->setTemplateSpecializationKind(
+                                                   TSK_ExplicitSpecialization);
+      InstantiationEnum->setLocation(Member->getLocation());
+    }
+
+    cast<EnumDecl>(Member)->setInstantiationOfMemberEnum(
+        cast<EnumDecl>(InstantiatedFrom), TSK_ExplicitSpecialization);
+  }
+
+  // Save the caller the trouble of having to figure out which declaration
+  // this specialization matches.
+  Previous.clear();
+  Previous.addDecl(Instantiation);
+  return false;
+}
+
+/// \brief Check the scope of an explicit instantiation.
+///
+/// \returns true if a serious error occurs, false otherwise.
+static bool CheckExplicitInstantiationScope(Sema &S, NamedDecl *D,
+                                            SourceLocation InstLoc,
+                                            bool WasQualifiedName) {
+  DeclContext *OrigContext= D->getDeclContext()->getEnclosingNamespaceContext();
+  DeclContext *CurContext = S.CurContext->getRedeclContext();
+
+  if (CurContext->isRecord()) {
+    S.Diag(InstLoc, diag::err_explicit_instantiation_in_class)
+      << D;
+    return true;
+  }
+
+  // C++11 [temp.explicit]p3:
+  //   An explicit instantiation shall appear in an enclosing namespace of its
+  //   template. If the name declared in the explicit instantiation is an
+  //   unqualified name, the explicit instantiation shall appear in the
+  //   namespace where its template is declared or, if that namespace is inline
+  //   (7.3.1), any namespace from its enclosing namespace set.
+  //
+  // This is DR275, which we do not retroactively apply to C++98/03.
+  if (WasQualifiedName) {
+    if (CurContext->Encloses(OrigContext))
+      return false;
+  } else {
+    if (CurContext->InEnclosingNamespaceSetOf(OrigContext))
+      return false;
+  }
+
+  if (NamespaceDecl *NS = dyn_cast<NamespaceDecl>(OrigContext)) {
+    if (WasQualifiedName)
+      S.Diag(InstLoc,
+             S.getLangOpts().CPlusPlus0x?
+               diag::err_explicit_instantiation_out_of_scope :
+               diag::warn_explicit_instantiation_out_of_scope_0x)
+        << D << NS;
+    else
+      S.Diag(InstLoc,
+             S.getLangOpts().CPlusPlus0x?
+               diag::err_explicit_instantiation_unqualified_wrong_namespace :
+               diag::warn_explicit_instantiation_unqualified_wrong_namespace_0x)
+        << D << NS;
+  } else
+    S.Diag(InstLoc,
+           S.getLangOpts().CPlusPlus0x?
+             diag::err_explicit_instantiation_must_be_global :
+             diag::warn_explicit_instantiation_must_be_global_0x)
+      << D;
+  S.Diag(D->getLocation(), diag::note_explicit_instantiation_here);
+  return false;
+}
+
+/// \brief Determine whether the given scope specifier has a template-id in it.
+static bool ScopeSpecifierHasTemplateId(const CXXScopeSpec &SS) {
+  if (!SS.isSet())
+    return false;
+
+  // C++11 [temp.explicit]p3:
+  //   If the explicit instantiation is for a member function, a member class
+  //   or a static data member of a class template specialization, the name of
+  //   the class template specialization in the qualified-id for the member
+  //   name shall be a simple-template-id.
+  //
+  // C++98 has the same restriction, just worded differently.
+  for (NestedNameSpecifier *NNS = (NestedNameSpecifier *)SS.getScopeRep();
+       NNS; NNS = NNS->getPrefix())
+    if (const Type *T = NNS->getAsType())
+      if (isa<TemplateSpecializationType>(T))
+        return true;
+
+  return false;
+}
+
+// Explicit instantiation of a class template specialization
+DeclResult
+Sema::ActOnExplicitInstantiation(Scope *S,
+                                 SourceLocation ExternLoc,
+                                 SourceLocation TemplateLoc,
+                                 unsigned TagSpec,
+                                 SourceLocation KWLoc,
+                                 const CXXScopeSpec &SS,
+                                 TemplateTy TemplateD,
+                                 SourceLocation TemplateNameLoc,
+                                 SourceLocation LAngleLoc,
+                                 ASTTemplateArgsPtr TemplateArgsIn,
+                                 SourceLocation RAngleLoc,
+                                 AttributeList *Attr) {
+  // Find the class template we're specializing
+  TemplateName Name = TemplateD.getAsVal<TemplateName>();
+  ClassTemplateDecl *ClassTemplate
+    = cast<ClassTemplateDecl>(Name.getAsTemplateDecl());
+
+  // Check that the specialization uses the same tag kind as the
+  // original template.
+  TagTypeKind Kind = TypeWithKeyword::getTagTypeKindForTypeSpec(TagSpec);
+  assert(Kind != TTK_Enum &&
+         "Invalid enum tag in class template explicit instantiation!");
+  if (!isAcceptableTagRedeclaration(ClassTemplate->getTemplatedDecl(),
+                                    Kind, /*isDefinition*/false, KWLoc,
+                                    *ClassTemplate->getIdentifier())) {
+    Diag(KWLoc, diag::err_use_with_wrong_tag)
+      << ClassTemplate
+      << FixItHint::CreateReplacement(KWLoc,
+                            ClassTemplate->getTemplatedDecl()->getKindName());
+    Diag(ClassTemplate->getTemplatedDecl()->getLocation(),
+         diag::note_previous_use);
+    Kind = ClassTemplate->getTemplatedDecl()->getTagKind();
+  }
+
+  // C++0x [temp.explicit]p2:
+  //   There are two forms of explicit instantiation: an explicit instantiation
+  //   definition and an explicit instantiation declaration. An explicit
+  //   instantiation declaration begins with the extern keyword. [...]
+  TemplateSpecializationKind TSK
+    = ExternLoc.isInvalid()? TSK_ExplicitInstantiationDefinition
+                           : TSK_ExplicitInstantiationDeclaration;
+
+  // Translate the parser's template argument list in our AST format.
+  TemplateArgumentListInfo TemplateArgs(LAngleLoc, RAngleLoc);
+  translateTemplateArguments(TemplateArgsIn, TemplateArgs);
+
+  // Check that the template argument list is well-formed for this
+  // template.
+  SmallVector<TemplateArgument, 4> Converted;
+  if (CheckTemplateArgumentList(ClassTemplate, TemplateNameLoc,
+                                TemplateArgs, false, Converted))
+    return true;
+
+  // Find the class template specialization declaration that
+  // corresponds to these arguments.
+  void *InsertPos = 0;
+  ClassTemplateSpecializationDecl *PrevDecl
+    = ClassTemplate->findSpecialization(Converted.data(),
+                                        Converted.size(), InsertPos);
+
+  TemplateSpecializationKind PrevDecl_TSK
+    = PrevDecl ? PrevDecl->getTemplateSpecializationKind() : TSK_Undeclared;
+
+  // C++0x [temp.explicit]p2:
+  //   [...] An explicit instantiation shall appear in an enclosing
+  //   namespace of its template. [...]
+  //
+  // This is C++ DR 275.
+  if (CheckExplicitInstantiationScope(*this, ClassTemplate, TemplateNameLoc,
+                                      SS.isSet()))
+    return true;
+
+  ClassTemplateSpecializationDecl *Specialization = 0;
+
+  bool HasNoEffect = false;
+  if (PrevDecl) {
+    if (CheckSpecializationInstantiationRedecl(TemplateNameLoc, TSK,
+                                               PrevDecl, PrevDecl_TSK,
+                                            PrevDecl->getPointOfInstantiation(),
+                                               HasNoEffect))
+      return PrevDecl;
+
+    // Even though HasNoEffect == true means that this explicit instantiation
+    // has no effect on semantics, we go on to put its syntax in the AST.
+
+    if (PrevDecl_TSK == TSK_ImplicitInstantiation ||
+        PrevDecl_TSK == TSK_Undeclared) {
+      // Since the only prior class template specialization with these
+      // arguments was referenced but not declared, reuse that
+      // declaration node as our own, updating the source location
+      // for the template name to reflect our new declaration.
+      // (Other source locations will be updated later.)
+      Specialization = PrevDecl;
+      Specialization->setLocation(TemplateNameLoc);
+      PrevDecl = 0;
+    }
+  }
+
+  if (!Specialization) {
+    // Create a new class template specialization declaration node for
+    // this explicit specialization.
+    Specialization
+      = ClassTemplateSpecializationDecl::Create(Context, Kind,
+                                             ClassTemplate->getDeclContext(),
+                                                KWLoc, TemplateNameLoc,
+                                                ClassTemplate,
+                                                Converted.data(),
+                                                Converted.size(),
+                                                PrevDecl);
+    SetNestedNameSpecifier(Specialization, SS);
+
+    if (!HasNoEffect && !PrevDecl) {
+      // Insert the new specialization.
+      ClassTemplate->AddSpecialization(Specialization, InsertPos);
+    }
+  }
+
+  // Build the fully-sugared type for this explicit instantiation as
+  // the user wrote in the explicit instantiation itself. This means
+  // that we'll pretty-print the type retrieved from the
+  // specialization's declaration the way that the user actually wrote
+  // the explicit instantiation, rather than formatting the name based
+  // on the "canonical" representation used to store the template
+  // arguments in the specialization.
+  TypeSourceInfo *WrittenTy
+    = Context.getTemplateSpecializationTypeInfo(Name, TemplateNameLoc,
+                                                TemplateArgs,
+                                  Context.getTypeDeclType(Specialization));
+  Specialization->setTypeAsWritten(WrittenTy);
+  TemplateArgsIn.release();
+
+  // Set source locations for keywords.
+  Specialization->setExternLoc(ExternLoc);
+  Specialization->setTemplateKeywordLoc(TemplateLoc);
+
+  if (Attr)
+    ProcessDeclAttributeList(S, Specialization, Attr);
+
+  // Add the explicit instantiation into its lexical context. However,
+  // since explicit instantiations are never found by name lookup, we
+  // just put it into the declaration context directly.
+  Specialization->setLexicalDeclContext(CurContext);
+  CurContext->addDecl(Specialization);
+
+  // Syntax is now OK, so return if it has no other effect on semantics.
+  if (HasNoEffect) {
+    // Set the template specialization kind.
+    Specialization->setTemplateSpecializationKind(TSK);
+    return Specialization;
+  }
+
+  // C++ [temp.explicit]p3:
+  //   A definition of a class template or class member template
+  //   shall be in scope at the point of the explicit instantiation of
+  //   the class template or class member template.
+  //
+  // This check comes when we actually try to perform the
+  // instantiation.
+  ClassTemplateSpecializationDecl *Def
+    = cast_or_null<ClassTemplateSpecializationDecl>(
+                                              Specialization->getDefinition());
+  if (!Def)
+    InstantiateClassTemplateSpecialization(TemplateNameLoc, Specialization, TSK);
+  else if (TSK == TSK_ExplicitInstantiationDefinition) {
+    MarkVTableUsed(TemplateNameLoc, Specialization, true);
+    Specialization->setPointOfInstantiation(Def->getPointOfInstantiation());
+  }
+
+  // Instantiate the members of this class template specialization.
+  Def = cast_or_null<ClassTemplateSpecializationDecl>(
+                                       Specialization->getDefinition());
+  if (Def) {
+    TemplateSpecializationKind Old_TSK = Def->getTemplateSpecializationKind();
+
+    // Fix a TSK_ExplicitInstantiationDeclaration followed by a
+    // TSK_ExplicitInstantiationDefinition
+    if (Old_TSK == TSK_ExplicitInstantiationDeclaration &&
+        TSK == TSK_ExplicitInstantiationDefinition)
+      Def->setTemplateSpecializationKind(TSK);
+
+    InstantiateClassTemplateSpecializationMembers(TemplateNameLoc, Def, TSK);
+  }
+
+  // Set the template specialization kind.
+  Specialization->setTemplateSpecializationKind(TSK);
+  return Specialization;
+}
+
+// Explicit instantiation of a member class of a class template.
+DeclResult
+Sema::ActOnExplicitInstantiation(Scope *S,
+                                 SourceLocation ExternLoc,
+                                 SourceLocation TemplateLoc,
+                                 unsigned TagSpec,
+                                 SourceLocation KWLoc,
+                                 CXXScopeSpec &SS,
+                                 IdentifierInfo *Name,
+                                 SourceLocation NameLoc,
+                                 AttributeList *Attr) {
+
+  bool Owned = false;
+  bool IsDependent = false;
+  Decl *TagD = ActOnTag(S, TagSpec, Sema::TUK_Reference,
+                        KWLoc, SS, Name, NameLoc, Attr, AS_none,
+                        /*ModulePrivateLoc=*/SourceLocation(),
+                        MultiTemplateParamsArg(*this, 0, 0),
+                        Owned, IsDependent, SourceLocation(), false,
+                        TypeResult());
+  assert(!IsDependent && "explicit instantiation of dependent name not yet handled");
+
+  if (!TagD)
+    return true;
+
+  TagDecl *Tag = cast<TagDecl>(TagD);
+  assert(!Tag->isEnum() && "shouldn't see enumerations here");
+
+  if (Tag->isInvalidDecl())
+    return true;
+
+  CXXRecordDecl *Record = cast<CXXRecordDecl>(Tag);
+  CXXRecordDecl *Pattern = Record->getInstantiatedFromMemberClass();
+  if (!Pattern) {
+    Diag(TemplateLoc, diag::err_explicit_instantiation_nontemplate_type)
+      << Context.getTypeDeclType(Record);
+    Diag(Record->getLocation(), diag::note_nontemplate_decl_here);
+    return true;
+  }
+
+  // C++0x [temp.explicit]p2:
+  //   If the explicit instantiation is for a class or member class, the
+  //   elaborated-type-specifier in the declaration shall include a
+  //   simple-template-id.
+  //
+  // C++98 has the same restriction, just worded differently.
+  if (!ScopeSpecifierHasTemplateId(SS))
+    Diag(TemplateLoc, diag::ext_explicit_instantiation_without_qualified_id)
+      << Record << SS.getRange();
+
+  // C++0x [temp.explicit]p2:
+  //   There are two forms of explicit instantiation: an explicit instantiation
+  //   definition and an explicit instantiation declaration. An explicit
+  //   instantiation declaration begins with the extern keyword. [...]
+  TemplateSpecializationKind TSK
+    = ExternLoc.isInvalid()? TSK_ExplicitInstantiationDefinition
+                           : TSK_ExplicitInstantiationDeclaration;
+
+  // C++0x [temp.explicit]p2:
+  //   [...] An explicit instantiation shall appear in an enclosing
+  //   namespace of its template. [...]
+  //
+  // This is C++ DR 275.
+  CheckExplicitInstantiationScope(*this, Record, NameLoc, true);
+
+  // Verify that it is okay to explicitly instantiate here.
+  CXXRecordDecl *PrevDecl
+    = cast_or_null<CXXRecordDecl>(Record->getPreviousDecl());
+  if (!PrevDecl && Record->getDefinition())
+    PrevDecl = Record;
+  if (PrevDecl) {
+    MemberSpecializationInfo *MSInfo = PrevDecl->getMemberSpecializationInfo();
+    bool HasNoEffect = false;
+    assert(MSInfo && "No member specialization information?");
+    if (CheckSpecializationInstantiationRedecl(TemplateLoc, TSK,
+                                               PrevDecl,
+                                        MSInfo->getTemplateSpecializationKind(),
+                                             MSInfo->getPointOfInstantiation(),
+                                               HasNoEffect))
+      return true;
+    if (HasNoEffect)
+      return TagD;
+  }
+
+  CXXRecordDecl *RecordDef
+    = cast_or_null<CXXRecordDecl>(Record->getDefinition());
+  if (!RecordDef) {
+    // C++ [temp.explicit]p3:
+    //   A definition of a member class of a class template shall be in scope
+    //   at the point of an explicit instantiation of the member class.
+    CXXRecordDecl *Def
+      = cast_or_null<CXXRecordDecl>(Pattern->getDefinition());
+    if (!Def) {
+      Diag(TemplateLoc, diag::err_explicit_instantiation_undefined_member)
+        << 0 << Record->getDeclName() << Record->getDeclContext();
+      Diag(Pattern->getLocation(), diag::note_forward_declaration)
+        << Pattern;
+      return true;
+    } else {
+      if (InstantiateClass(NameLoc, Record, Def,
+                           getTemplateInstantiationArgs(Record),
+                           TSK))
+        return true;
+
+      RecordDef = cast_or_null<CXXRecordDecl>(Record->getDefinition());
+      if (!RecordDef)
+        return true;
+    }
+  }
+
+  // Instantiate all of the members of the class.
+  InstantiateClassMembers(NameLoc, RecordDef,
+                          getTemplateInstantiationArgs(Record), TSK);
+
+  if (TSK == TSK_ExplicitInstantiationDefinition)
+    MarkVTableUsed(NameLoc, RecordDef, true);
+
+  // FIXME: We don't have any representation for explicit instantiations of
+  // member classes. Such a representation is not needed for compilation, but it
+  // should be available for clients that want to see all of the declarations in
+  // the source code.
+  return TagD;
+}
+
+DeclResult Sema::ActOnExplicitInstantiation(Scope *S,
+                                            SourceLocation ExternLoc,
+                                            SourceLocation TemplateLoc,
+                                            Declarator &D) {
+  // Explicit instantiations always require a name.
+  // TODO: check if/when DNInfo should replace Name.
+  DeclarationNameInfo NameInfo = GetNameForDeclarator(D);
+  DeclarationName Name = NameInfo.getName();
+  if (!Name) {
+    if (!D.isInvalidType())
+      Diag(D.getDeclSpec().getLocStart(),
+           diag::err_explicit_instantiation_requires_name)
+        << D.getDeclSpec().getSourceRange()
+        << D.getSourceRange();
+
+    return true;
+  }
+
+  // The scope passed in may not be a decl scope.  Zip up the scope tree until
+  // we find one that is.
+  while ((S->getFlags() & Scope::DeclScope) == 0 ||
+         (S->getFlags() & Scope::TemplateParamScope) != 0)
+    S = S->getParent();
+
+  // Determine the type of the declaration.
+  TypeSourceInfo *T = GetTypeForDeclarator(D, S);
+  QualType R = T->getType();
+  if (R.isNull())
+    return true;
+
+  // C++ [dcl.stc]p1:
+  //   A storage-class-specifier shall not be specified in [...] an explicit 
+  //   instantiation (14.7.2) directive.
+  if (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_typedef) {
+    Diag(D.getIdentifierLoc(), diag::err_explicit_instantiation_of_typedef)
+      << Name;
+    return true;
+  } else if (D.getDeclSpec().getStorageClassSpec() 
+                                                != DeclSpec::SCS_unspecified) {
+    // Complain about then remove the storage class specifier.
+    Diag(D.getIdentifierLoc(), diag::err_explicit_instantiation_storage_class)
+      << FixItHint::CreateRemoval(D.getDeclSpec().getStorageClassSpecLoc());
+    
+    D.getMutableDeclSpec().ClearStorageClassSpecs();
+  }
+
+  // C++0x [temp.explicit]p1:
+  //   [...] An explicit instantiation of a function template shall not use the
+  //   inline or constexpr specifiers.
+  // Presumably, this also applies to member functions of class templates as
+  // well.
+  if (D.getDeclSpec().isInlineSpecified())
+    Diag(D.getDeclSpec().getInlineSpecLoc(),
+         getLangOpts().CPlusPlus0x ?
+           diag::err_explicit_instantiation_inline :
+           diag::warn_explicit_instantiation_inline_0x)
+      << FixItHint::CreateRemoval(D.getDeclSpec().getInlineSpecLoc());
+  if (D.getDeclSpec().isConstexprSpecified())
+    // FIXME: Add a fix-it to remove the 'constexpr' and add a 'const' if one is
+    // not already specified.
+    Diag(D.getDeclSpec().getConstexprSpecLoc(),
+         diag::err_explicit_instantiation_constexpr);
+
+  // C++0x [temp.explicit]p2:
+  //   There are two forms of explicit instantiation: an explicit instantiation
+  //   definition and an explicit instantiation declaration. An explicit
+  //   instantiation declaration begins with the extern keyword. [...]
+  TemplateSpecializationKind TSK
+    = ExternLoc.isInvalid()? TSK_ExplicitInstantiationDefinition
+                           : TSK_ExplicitInstantiationDeclaration;
+
+  LookupResult Previous(*this, NameInfo, LookupOrdinaryName);
+  LookupParsedName(Previous, S, &D.getCXXScopeSpec());
+
+  if (!R->isFunctionType()) {
+    // C++ [temp.explicit]p1:
+    //   A [...] static data member of a class template can be explicitly
+    //   instantiated from the member definition associated with its class
+    //   template.
+    if (Previous.isAmbiguous())
+      return true;
+
+    VarDecl *Prev = Previous.getAsSingle<VarDecl>();
+    if (!Prev || !Prev->isStaticDataMember()) {
+      // We expect to see a data data member here.
+      Diag(D.getIdentifierLoc(), diag::err_explicit_instantiation_not_known)
+        << Name;
+      for (LookupResult::iterator P = Previous.begin(), PEnd = Previous.end();
+           P != PEnd; ++P)
+        Diag((*P)->getLocation(), diag::note_explicit_instantiation_here);
+      return true;
+    }
+
+    if (!Prev->getInstantiatedFromStaticDataMember()) {
+      // FIXME: Check for explicit specialization?
+      Diag(D.getIdentifierLoc(),
+           diag::err_explicit_instantiation_data_member_not_instantiated)
+        << Prev;
+      Diag(Prev->getLocation(), diag::note_explicit_instantiation_here);
+      // FIXME: Can we provide a note showing where this was declared?
+      return true;
+    }
+
+    // C++0x [temp.explicit]p2:
+    //   If the explicit instantiation is for a member function, a member class
+    //   or a static data member of a class template specialization, the name of
+    //   the class template specialization in the qualified-id for the member
+    //   name shall be a simple-template-id.
+    //
+    // C++98 has the same restriction, just worded differently.
+    if (!ScopeSpecifierHasTemplateId(D.getCXXScopeSpec()))
+      Diag(D.getIdentifierLoc(),
+           diag::ext_explicit_instantiation_without_qualified_id)
+        << Prev << D.getCXXScopeSpec().getRange();
+
+    // Check the scope of this explicit instantiation.
+    CheckExplicitInstantiationScope(*this, Prev, D.getIdentifierLoc(), true);
+
+    // Verify that it is okay to explicitly instantiate here.
+    MemberSpecializationInfo *MSInfo = Prev->getMemberSpecializationInfo();
+    assert(MSInfo && "Missing static data member specialization info?");
+    bool HasNoEffect = false;
+    if (CheckSpecializationInstantiationRedecl(D.getIdentifierLoc(), TSK, Prev,
+                                        MSInfo->getTemplateSpecializationKind(),
+                                              MSInfo->getPointOfInstantiation(),
+                                               HasNoEffect))
+      return true;
+    if (HasNoEffect)
+      return (Decl*) 0;
+
+    // Instantiate static data member.
+    Prev->setTemplateSpecializationKind(TSK, D.getIdentifierLoc());
+    if (TSK == TSK_ExplicitInstantiationDefinition)
+      InstantiateStaticDataMemberDefinition(D.getIdentifierLoc(), Prev);
+
+    // FIXME: Create an ExplicitInstantiation node?
+    return (Decl*) 0;
+  }
+
+  // If the declarator is a template-id, translate the parser's template
+  // argument list into our AST format.
+  bool HasExplicitTemplateArgs = false;
+  TemplateArgumentListInfo TemplateArgs;
+  if (D.getName().getKind() == UnqualifiedId::IK_TemplateId) {
+    TemplateIdAnnotation *TemplateId = D.getName().TemplateId;
+    TemplateArgs.setLAngleLoc(TemplateId->LAngleLoc);
+    TemplateArgs.setRAngleLoc(TemplateId->RAngleLoc);
+    ASTTemplateArgsPtr TemplateArgsPtr(*this,
+                                       TemplateId->getTemplateArgs(),
+                                       TemplateId->NumArgs);
+    translateTemplateArguments(TemplateArgsPtr, TemplateArgs);
+    HasExplicitTemplateArgs = true;
+    TemplateArgsPtr.release();
+  }
+
+  // C++ [temp.explicit]p1:
+  //   A [...] function [...] can be explicitly instantiated from its template.
+  //   A member function [...] of a class template can be explicitly
+  //  instantiated from the member definition associated with its class
+  //  template.
+  UnresolvedSet<8> Matches;
+  for (LookupResult::iterator P = Previous.begin(), PEnd = Previous.end();
+       P != PEnd; ++P) {
+    NamedDecl *Prev = *P;
+    if (!HasExplicitTemplateArgs) {
+      if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(Prev)) {
+        if (Context.hasSameUnqualifiedType(Method->getType(), R)) {
+          Matches.clear();
+
+          Matches.addDecl(Method, P.getAccess());
+          if (Method->getTemplateSpecializationKind() == TSK_Undeclared)
+            break;
+        }
+      }
+    }
+
+    FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(Prev);
+    if (!FunTmpl)
+      continue;
+
+    TemplateDeductionInfo Info(Context, D.getIdentifierLoc());
+    FunctionDecl *Specialization = 0;
+    if (TemplateDeductionResult TDK
+          = DeduceTemplateArguments(FunTmpl,
+                               (HasExplicitTemplateArgs ? &TemplateArgs : 0),
+                                    R, Specialization, Info)) {
+      // FIXME: Keep track of almost-matches?
+      (void)TDK;
+      continue;
+    }
+
+    Matches.addDecl(Specialization, P.getAccess());
+  }
+
+  // Find the most specialized function template specialization.
+  UnresolvedSetIterator Result
+    = getMostSpecialized(Matches.begin(), Matches.end(), TPOC_Other, 0,
+                         D.getIdentifierLoc(),
+                     PDiag(diag::err_explicit_instantiation_not_known) << Name,
+                     PDiag(diag::err_explicit_instantiation_ambiguous) << Name,
+                         PDiag(diag::note_explicit_instantiation_candidate));
+
+  if (Result == Matches.end())
+    return true;
+
+  // Ignore access control bits, we don't need them for redeclaration checking.
+  FunctionDecl *Specialization = cast<FunctionDecl>(*Result);
+
+  if (Specialization->getTemplateSpecializationKind() == TSK_Undeclared) {
+    Diag(D.getIdentifierLoc(),
+         diag::err_explicit_instantiation_member_function_not_instantiated)
+      << Specialization
+      << (Specialization->getTemplateSpecializationKind() ==
+          TSK_ExplicitSpecialization);
+    Diag(Specialization->getLocation(), diag::note_explicit_instantiation_here);
+    return true;
+  }
+
+  FunctionDecl *PrevDecl = Specialization->getPreviousDecl();
+  if (!PrevDecl && Specialization->isThisDeclarationADefinition())
+    PrevDecl = Specialization;
+
+  if (PrevDecl) {
+    bool HasNoEffect = false;
+    if (CheckSpecializationInstantiationRedecl(D.getIdentifierLoc(), TSK,
+                                               PrevDecl,
+                                     PrevDecl->getTemplateSpecializationKind(),
+                                          PrevDecl->getPointOfInstantiation(),
+                                               HasNoEffect))
+      return true;
+
+    // FIXME: We may still want to build some representation of this
+    // explicit specialization.
+    if (HasNoEffect)
+      return (Decl*) 0;
+  }
+
+  Specialization->setTemplateSpecializationKind(TSK, D.getIdentifierLoc());
+  AttributeList *Attr = D.getDeclSpec().getAttributes().getList();
+  if (Attr)
+    ProcessDeclAttributeList(S, Specialization, Attr);
+
+  if (TSK == TSK_ExplicitInstantiationDefinition)
+    InstantiateFunctionDefinition(D.getIdentifierLoc(), Specialization);
+
+  // C++0x [temp.explicit]p2:
+  //   If the explicit instantiation is for a member function, a member class
+  //   or a static data member of a class template specialization, the name of
+  //   the class template specialization in the qualified-id for the member
+  //   name shall be a simple-template-id.
+  //
+  // C++98 has the same restriction, just worded differently.
+  FunctionTemplateDecl *FunTmpl = Specialization->getPrimaryTemplate();
+  if (D.getName().getKind() != UnqualifiedId::IK_TemplateId && !FunTmpl &&
+      D.getCXXScopeSpec().isSet() &&
+      !ScopeSpecifierHasTemplateId(D.getCXXScopeSpec()))
+    Diag(D.getIdentifierLoc(),
+         diag::ext_explicit_instantiation_without_qualified_id)
+    << Specialization << D.getCXXScopeSpec().getRange();
+
+  CheckExplicitInstantiationScope(*this,
+                   FunTmpl? (NamedDecl *)FunTmpl
+                          : Specialization->getInstantiatedFromMemberFunction(),
+                                  D.getIdentifierLoc(),
+                                  D.getCXXScopeSpec().isSet());
+
+  // FIXME: Create some kind of ExplicitInstantiationDecl here.
+  return (Decl*) 0;
+}
+
+TypeResult
+Sema::ActOnDependentTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
+                        const CXXScopeSpec &SS, IdentifierInfo *Name,
+                        SourceLocation TagLoc, SourceLocation NameLoc) {
+  // This has to hold, because SS is expected to be defined.
+  assert(Name && "Expected a name in a dependent tag");
+
+  NestedNameSpecifier *NNS
+    = static_cast<NestedNameSpecifier *>(SS.getScopeRep());
+  if (!NNS)
+    return true;
+
+  TagTypeKind Kind = TypeWithKeyword::getTagTypeKindForTypeSpec(TagSpec);
+
+  if (TUK == TUK_Declaration || TUK == TUK_Definition) {
+    Diag(NameLoc, diag::err_dependent_tag_decl)
+      << (TUK == TUK_Definition) << Kind << SS.getRange();
+    return true;
+  }
+
+  // Create the resulting type.
+  ElaboratedTypeKeyword Kwd = TypeWithKeyword::getKeywordForTagTypeKind(Kind);
+  QualType Result = Context.getDependentNameType(Kwd, NNS, Name);
+  
+  // Create type-source location information for this type.
+  TypeLocBuilder TLB;
+  DependentNameTypeLoc TL = TLB.push<DependentNameTypeLoc>(Result);
+  TL.setElaboratedKeywordLoc(TagLoc);
+  TL.setQualifierLoc(SS.getWithLocInContext(Context));
+  TL.setNameLoc(NameLoc);
+  return CreateParsedType(Result, TLB.getTypeSourceInfo(Context, Result));
+}
+
+TypeResult
+Sema::ActOnTypenameType(Scope *S, SourceLocation TypenameLoc,
+                        const CXXScopeSpec &SS, const IdentifierInfo &II,
+                        SourceLocation IdLoc) {
+  if (SS.isInvalid())
+    return true;
+  
+  if (TypenameLoc.isValid() && S && !S->getTemplateParamParent())
+    Diag(TypenameLoc,
+         getLangOpts().CPlusPlus0x ?
+           diag::warn_cxx98_compat_typename_outside_of_template :
+           diag::ext_typename_outside_of_template)
+      << FixItHint::CreateRemoval(TypenameLoc);
+
+  NestedNameSpecifierLoc QualifierLoc = SS.getWithLocInContext(Context);
+  QualType T = CheckTypenameType(TypenameLoc.isValid()? ETK_Typename : ETK_None,
+                                 TypenameLoc, QualifierLoc, II, IdLoc);
+  if (T.isNull())
+    return true;
+
+  TypeSourceInfo *TSI = Context.CreateTypeSourceInfo(T);
+  if (isa<DependentNameType>(T)) {
+    DependentNameTypeLoc TL = cast<DependentNameTypeLoc>(TSI->getTypeLoc());
+    TL.setElaboratedKeywordLoc(TypenameLoc);
+    TL.setQualifierLoc(QualifierLoc);
+    TL.setNameLoc(IdLoc);
+  } else {
+    ElaboratedTypeLoc TL = cast<ElaboratedTypeLoc>(TSI->getTypeLoc());
+    TL.setElaboratedKeywordLoc(TypenameLoc);
+    TL.setQualifierLoc(QualifierLoc);
+    cast<TypeSpecTypeLoc>(TL.getNamedTypeLoc()).setNameLoc(IdLoc);
+  }
+
+  return CreateParsedType(T, TSI);
+}
+
+TypeResult
+Sema::ActOnTypenameType(Scope *S,
+                        SourceLocation TypenameLoc,
+                        const CXXScopeSpec &SS,
+                        SourceLocation TemplateKWLoc,
+                        TemplateTy TemplateIn,
+                        SourceLocation TemplateNameLoc,
+                        SourceLocation LAngleLoc,
+                        ASTTemplateArgsPtr TemplateArgsIn,
+                        SourceLocation RAngleLoc) {
+  if (TypenameLoc.isValid() && S && !S->getTemplateParamParent())
+    Diag(TypenameLoc,
+         getLangOpts().CPlusPlus0x ?
+           diag::warn_cxx98_compat_typename_outside_of_template :
+           diag::ext_typename_outside_of_template)
+      << FixItHint::CreateRemoval(TypenameLoc);
+  
+  // Translate the parser's template argument list in our AST format.
+  TemplateArgumentListInfo TemplateArgs(LAngleLoc, RAngleLoc);
+  translateTemplateArguments(TemplateArgsIn, TemplateArgs);
+  
+  TemplateName Template = TemplateIn.get();
+  if (DependentTemplateName *DTN = Template.getAsDependentTemplateName()) {
+    // Construct a dependent template specialization type.
+    assert(DTN && "dependent template has non-dependent name?");
+    assert(DTN->getQualifier()
+           == static_cast<NestedNameSpecifier*>(SS.getScopeRep()));
+    QualType T = Context.getDependentTemplateSpecializationType(ETK_Typename,
+                                                          DTN->getQualifier(),
+                                                          DTN->getIdentifier(),
+                                                                TemplateArgs);
+    
+    // Create source-location information for this type.
+    TypeLocBuilder Builder;
+    DependentTemplateSpecializationTypeLoc SpecTL 
+    = Builder.push<DependentTemplateSpecializationTypeLoc>(T);
+    SpecTL.setElaboratedKeywordLoc(TypenameLoc);
+    SpecTL.setQualifierLoc(SS.getWithLocInContext(Context));
+    SpecTL.setTemplateKeywordLoc(TemplateKWLoc);
+    SpecTL.setTemplateNameLoc(TemplateNameLoc);
+    SpecTL.setLAngleLoc(LAngleLoc);
+    SpecTL.setRAngleLoc(RAngleLoc);
+    for (unsigned I = 0, N = TemplateArgs.size(); I != N; ++I)
+      SpecTL.setArgLocInfo(I, TemplateArgs[I].getLocInfo());
+    return CreateParsedType(T, Builder.getTypeSourceInfo(Context, T));
+  }
+  
+  QualType T = CheckTemplateIdType(Template, TemplateNameLoc, TemplateArgs);
+  if (T.isNull())
+    return true;
+  
+  // Provide source-location information for the template specialization type.
+  TypeLocBuilder Builder;
+  TemplateSpecializationTypeLoc SpecTL
+    = Builder.push<TemplateSpecializationTypeLoc>(T);
+  SpecTL.setTemplateKeywordLoc(TemplateKWLoc);
+  SpecTL.setTemplateNameLoc(TemplateNameLoc);
+  SpecTL.setLAngleLoc(LAngleLoc);
+  SpecTL.setRAngleLoc(RAngleLoc);
+  for (unsigned I = 0, N = TemplateArgs.size(); I != N; ++I)
+    SpecTL.setArgLocInfo(I, TemplateArgs[I].getLocInfo());
+  
+  T = Context.getElaboratedType(ETK_Typename, SS.getScopeRep(), T);
+  ElaboratedTypeLoc TL = Builder.push<ElaboratedTypeLoc>(T);
+  TL.setElaboratedKeywordLoc(TypenameLoc);
+  TL.setQualifierLoc(SS.getWithLocInContext(Context));
+  
+  TypeSourceInfo *TSI = Builder.getTypeSourceInfo(Context, T);
+  return CreateParsedType(T, TSI);
+}
+
+
+/// \brief Build the type that describes a C++ typename specifier,
+/// e.g., "typename T::type".
+QualType
+Sema::CheckTypenameType(ElaboratedTypeKeyword Keyword, 
+                        SourceLocation KeywordLoc,
+                        NestedNameSpecifierLoc QualifierLoc, 
+                        const IdentifierInfo &II,
+                        SourceLocation IILoc) {
+  CXXScopeSpec SS;
+  SS.Adopt(QualifierLoc);
+
+  DeclContext *Ctx = computeDeclContext(SS);
+  if (!Ctx) {
+    // If the nested-name-specifier is dependent and couldn't be
+    // resolved to a type, build a typename type.
+    assert(QualifierLoc.getNestedNameSpecifier()->isDependent());
+    return Context.getDependentNameType(Keyword, 
+                                        QualifierLoc.getNestedNameSpecifier(), 
+                                        &II);
+  }
+
+  // If the nested-name-specifier refers to the current instantiation,
+  // the "typename" keyword itself is superfluous. In C++03, the
+  // program is actually ill-formed. However, DR 382 (in C++0x CD1)
+  // allows such extraneous "typename" keywords, and we retroactively
+  // apply this DR to C++03 code with only a warning. In any case we continue.
+
+  if (RequireCompleteDeclContext(SS, Ctx))
+    return QualType();
+
+  DeclarationName Name(&II);
+  LookupResult Result(*this, Name, IILoc, LookupOrdinaryName);
+  LookupQualifiedName(Result, Ctx);
+  unsigned DiagID = 0;
+  Decl *Referenced = 0;
+  switch (Result.getResultKind()) {
+  case LookupResult::NotFound:
+    DiagID = diag::err_typename_nested_not_found;
+    break;
+
+  case LookupResult::FoundUnresolvedValue: {
+    // We found a using declaration that is a value. Most likely, the using
+    // declaration itself is meant to have the 'typename' keyword.
+    SourceRange FullRange(KeywordLoc.isValid() ? KeywordLoc : SS.getBeginLoc(),
+                          IILoc);
+    Diag(IILoc, diag::err_typename_refers_to_using_value_decl)
+      << Name << Ctx << FullRange;
+    if (UnresolvedUsingValueDecl *Using
+          = dyn_cast<UnresolvedUsingValueDecl>(Result.getRepresentativeDecl())){
+      SourceLocation Loc = Using->getQualifierLoc().getBeginLoc();
+      Diag(Loc, diag::note_using_value_decl_missing_typename)
+        << FixItHint::CreateInsertion(Loc, "typename ");
+    }
+  }
+  // Fall through to create a dependent typename type, from which we can recover
+  // better.
+
+  case LookupResult::NotFoundInCurrentInstantiation:
+    // Okay, it's a member of an unknown instantiation.
+    return Context.getDependentNameType(Keyword, 
+                                        QualifierLoc.getNestedNameSpecifier(), 
+                                        &II);
+
+  case LookupResult::Found:
+    if (TypeDecl *Type = dyn_cast<TypeDecl>(Result.getFoundDecl())) {
+      // We found a type. Build an ElaboratedType, since the
+      // typename-specifier was just sugar.
+      return Context.getElaboratedType(ETK_Typename, 
+                                       QualifierLoc.getNestedNameSpecifier(),
+                                       Context.getTypeDeclType(Type));
+    }
+
+    DiagID = diag::err_typename_nested_not_type;
+    Referenced = Result.getFoundDecl();
+    break;
+
+  case LookupResult::FoundOverloaded:
+    DiagID = diag::err_typename_nested_not_type;
+    Referenced = *Result.begin();
+    break;
+
+  case LookupResult::Ambiguous:
+    return QualType();
+  }
+
+  // If we get here, it's because name lookup did not find a
+  // type. Emit an appropriate diagnostic and return an error.
+  SourceRange FullRange(KeywordLoc.isValid() ? KeywordLoc : SS.getBeginLoc(),
+                        IILoc);
+  Diag(IILoc, DiagID) << FullRange << Name << Ctx;
+  if (Referenced)
+    Diag(Referenced->getLocation(), diag::note_typename_refers_here)
+      << Name;
+  return QualType();
+}
+
+namespace {
+  // See Sema::RebuildTypeInCurrentInstantiation
+  class CurrentInstantiationRebuilder
+    : public TreeTransform<CurrentInstantiationRebuilder> {
+    SourceLocation Loc;
+    DeclarationName Entity;
+
+  public:
+    typedef TreeTransform<CurrentInstantiationRebuilder> inherited;
+
+    CurrentInstantiationRebuilder(Sema &SemaRef,
+                                  SourceLocation Loc,
+                                  DeclarationName Entity)
+    : TreeTransform<CurrentInstantiationRebuilder>(SemaRef),
+      Loc(Loc), Entity(Entity) { }
+
+    /// \brief Determine whether the given type \p T has already been
+    /// transformed.
+    ///
+    /// For the purposes of type reconstruction, a type has already been
+    /// transformed if it is NULL or if it is not dependent.
+    bool AlreadyTransformed(QualType T) {
+      return T.isNull() || !T->isDependentType();
+    }
+
+    /// \brief Returns the location of the entity whose type is being
+    /// rebuilt.
+    SourceLocation getBaseLocation() { return Loc; }
+
+    /// \brief Returns the name of the entity whose type is being rebuilt.
+    DeclarationName getBaseEntity() { return Entity; }
+
+    /// \brief Sets the "base" location and entity when that
+    /// information is known based on another transformation.
+    void setBase(SourceLocation Loc, DeclarationName Entity) {
+      this->Loc = Loc;
+      this->Entity = Entity;
+    }
+      
+    ExprResult TransformLambdaExpr(LambdaExpr *E) {
+      // Lambdas never need to be transformed.
+      return E;
+    }
+  };
+}
+
+/// \brief Rebuilds a type within the context of the current instantiation.
+///
+/// The type \p T is part of the type of an out-of-line member definition of
+/// a class template (or class template partial specialization) that was parsed
+/// and constructed before we entered the scope of the class template (or
+/// partial specialization thereof). This routine will rebuild that type now
+/// that we have entered the declarator's scope, which may produce different
+/// canonical types, e.g.,
+///
+/// \code
+/// template<typename T>
+/// struct X {
+///   typedef T* pointer;
+///   pointer data();
+/// };
+///
+/// template<typename T>
+/// typename X<T>::pointer X<T>::data() { ... }
+/// \endcode
+///
+/// Here, the type "typename X<T>::pointer" will be created as a DependentNameType,
+/// since we do not know that we can look into X<T> when we parsed the type.
+/// This function will rebuild the type, performing the lookup of "pointer"
+/// in X<T> and returning an ElaboratedType whose canonical type is the same
+/// as the canonical type of T*, allowing the return types of the out-of-line
+/// definition and the declaration to match.
+TypeSourceInfo *Sema::RebuildTypeInCurrentInstantiation(TypeSourceInfo *T,
+                                                        SourceLocation Loc,
+                                                        DeclarationName Name) {
+  if (!T || !T->getType()->isDependentType())
+    return T;
+
+  CurrentInstantiationRebuilder Rebuilder(*this, Loc, Name);
+  return Rebuilder.TransformType(T);
+}
+
+ExprResult Sema::RebuildExprInCurrentInstantiation(Expr *E) {
+  CurrentInstantiationRebuilder Rebuilder(*this, E->getExprLoc(),
+                                          DeclarationName());
+  return Rebuilder.TransformExpr(E);
+}
+
+bool Sema::RebuildNestedNameSpecifierInCurrentInstantiation(CXXScopeSpec &SS) {
+  if (SS.isInvalid()) 
+    return true;
+
+  NestedNameSpecifierLoc QualifierLoc = SS.getWithLocInContext(Context);
+  CurrentInstantiationRebuilder Rebuilder(*this, SS.getRange().getBegin(),
+                                          DeclarationName());
+  NestedNameSpecifierLoc Rebuilt 
+    = Rebuilder.TransformNestedNameSpecifierLoc(QualifierLoc);
+  if (!Rebuilt) 
+    return true;
+
+  SS.Adopt(Rebuilt);
+  return false;
+}
+
+/// \brief Rebuild the template parameters now that we know we're in a current
+/// instantiation.
+bool Sema::RebuildTemplateParamsInCurrentInstantiation(
+                                               TemplateParameterList *Params) {
+  for (unsigned I = 0, N = Params->size(); I != N; ++I) {
+    Decl *Param = Params->getParam(I);
+    
+    // There is nothing to rebuild in a type parameter.
+    if (isa<TemplateTypeParmDecl>(Param))
+      continue;
+    
+    // Rebuild the template parameter list of a template template parameter.
+    if (TemplateTemplateParmDecl *TTP 
+        = dyn_cast<TemplateTemplateParmDecl>(Param)) {
+      if (RebuildTemplateParamsInCurrentInstantiation(
+            TTP->getTemplateParameters()))
+        return true;
+      
+      continue;
+    }
+    
+    // Rebuild the type of a non-type template parameter.
+    NonTypeTemplateParmDecl *NTTP = cast<NonTypeTemplateParmDecl>(Param);
+    TypeSourceInfo *NewTSI 
+      = RebuildTypeInCurrentInstantiation(NTTP->getTypeSourceInfo(), 
+                                          NTTP->getLocation(), 
+                                          NTTP->getDeclName());
+    if (!NewTSI)
+      return true;
+    
+    if (NewTSI != NTTP->getTypeSourceInfo()) {
+      NTTP->setTypeSourceInfo(NewTSI);
+      NTTP->setType(NewTSI->getType());
+    }
+  }
+  
+  return false;
+}
+
+/// \brief Produces a formatted string that describes the binding of
+/// template parameters to template arguments.
+std::string
+Sema::getTemplateArgumentBindingsText(const TemplateParameterList *Params,
+                                      const TemplateArgumentList &Args) {
+  return getTemplateArgumentBindingsText(Params, Args.data(), Args.size());
+}
+
+std::string
+Sema::getTemplateArgumentBindingsText(const TemplateParameterList *Params,
+                                      const TemplateArgument *Args,
+                                      unsigned NumArgs) {
+  SmallString<128> Str;
+  llvm::raw_svector_ostream Out(Str);
+
+  if (!Params || Params->size() == 0 || NumArgs == 0)
+    return std::string();
+
+  for (unsigned I = 0, N = Params->size(); I != N; ++I) {
+    if (I >= NumArgs)
+      break;
+
+    if (I == 0)
+      Out << "[with ";
+    else
+      Out << ", ";
+
+    if (const IdentifierInfo *Id = Params->getParam(I)->getIdentifier()) {
+      Out << Id->getName();
+    } else {
+      Out << '$' << I;
+    }
+
+    Out << " = ";
+    Args[I].print(getPrintingPolicy(), Out);
+  }
+
+  Out << ']';
+  return Out.str();
+}
+
+void Sema::MarkAsLateParsedTemplate(FunctionDecl *FD, bool Flag) {
+  if (!FD)
+    return;
+  FD->setLateTemplateParsed(Flag);
+} 
+
+bool Sema::IsInsideALocalClassWithinATemplateFunction() {
+  DeclContext *DC = CurContext;
+
+  while (DC) {
+    if (CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(CurContext)) {
+      const FunctionDecl *FD = RD->isLocalClass();
+      return (FD && FD->getTemplatedKind() != FunctionDecl::TK_NonTemplate);
+    } else if (DC->isTranslationUnit() || DC->isNamespace())
+      return false;
+
+    DC = DC->getParent();
+  }
+  return false;
+}
diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp
new file mode 100644
index 0000000..d68e464
--- /dev/null
+++ b/clang/lib/Sema/SemaTemplateDeduction.cpp
@@ -0,0 +1,4515 @@
+//===------- SemaTemplateDeduction.cpp - Template Argument Deduction ------===/
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//===----------------------------------------------------------------------===/
+//
+//  This file implements C++ template argument deduction.
+//
+//===----------------------------------------------------------------------===/
+
+#include "clang/Sema/Sema.h"
+#include "clang/Sema/DeclSpec.h"
+#include "clang/Sema/Template.h"
+#include "clang/Sema/TemplateDeduction.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/AST/DeclTemplate.h"
+#include "clang/AST/StmtVisitor.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/ExprCXX.h"
+#include "llvm/ADT/SmallBitVector.h"
+#include "TreeTransform.h"
+#include <algorithm>
+
+namespace clang {
+  using namespace sema;
+
+  /// \brief Various flags that control template argument deduction.
+  ///
+  /// These flags can be bitwise-OR'd together.
+  enum TemplateDeductionFlags {
+    /// \brief No template argument deduction flags, which indicates the
+    /// strictest results for template argument deduction (as used for, e.g.,
+    /// matching class template partial specializations).
+    TDF_None = 0,
+    /// \brief Within template argument deduction from a function call, we are
+    /// matching with a parameter type for which the original parameter was
+    /// a reference.
+    TDF_ParamWithReferenceType = 0x1,
+    /// \brief Within template argument deduction from a function call, we
+    /// are matching in a case where we ignore cv-qualifiers.
+    TDF_IgnoreQualifiers = 0x02,
+    /// \brief Within template argument deduction from a function call,
+    /// we are matching in a case where we can perform template argument
+    /// deduction from a template-id of a derived class of the argument type.
+    TDF_DerivedClass = 0x04,
+    /// \brief Allow non-dependent types to differ, e.g., when performing
+    /// template argument deduction from a function call where conversions
+    /// may apply.
+    TDF_SkipNonDependent = 0x08,
+    /// \brief Whether we are performing template argument deduction for
+    /// parameters and arguments in a top-level template argument
+    TDF_TopLevelParameterTypeList = 0x10
+  };
+}
+
+using namespace clang;
+
+/// \brief Compare two APSInts, extending and switching the sign as
+/// necessary to compare their values regardless of underlying type.
+static bool hasSameExtendedValue(llvm::APSInt X, llvm::APSInt Y) {
+  if (Y.getBitWidth() > X.getBitWidth())
+    X = X.extend(Y.getBitWidth());
+  else if (Y.getBitWidth() < X.getBitWidth())
+    Y = Y.extend(X.getBitWidth());
+
+  // If there is a signedness mismatch, correct it.
+  if (X.isSigned() != Y.isSigned()) {
+    // If the signed value is negative, then the values cannot be the same.
+    if ((Y.isSigned() && Y.isNegative()) || (X.isSigned() && X.isNegative()))
+      return false;
+
+    Y.setIsSigned(true);
+    X.setIsSigned(true);
+  }
+
+  return X == Y;
+}
+
+static Sema::TemplateDeductionResult
+DeduceTemplateArguments(Sema &S,
+                        TemplateParameterList *TemplateParams,
+                        const TemplateArgument &Param,
+                        TemplateArgument Arg,
+                        TemplateDeductionInfo &Info,
+                      SmallVectorImpl<DeducedTemplateArgument> &Deduced);
+
+/// \brief Whether template argument deduction for two reference parameters
+/// resulted in the argument type, parameter type, or neither type being more
+/// qualified than the other.
+enum DeductionQualifierComparison {
+  NeitherMoreQualified = 0,
+  ParamMoreQualified,
+  ArgMoreQualified
+};
+
+/// \brief Stores the result of comparing two reference parameters while
+/// performing template argument deduction for partial ordering of function
+/// templates.
+struct RefParamPartialOrderingComparison {
+  /// \brief Whether the parameter type is an rvalue reference type.
+  bool ParamIsRvalueRef;
+  /// \brief Whether the argument type is an rvalue reference type.
+  bool ArgIsRvalueRef;
+
+  /// \brief Whether the parameter or argument (or neither) is more qualified.
+  DeductionQualifierComparison Qualifiers;
+};
+
+
+
+static Sema::TemplateDeductionResult
+DeduceTemplateArgumentsByTypeMatch(Sema &S,
+                                   TemplateParameterList *TemplateParams,
+                                   QualType Param,
+                                   QualType Arg,
+                                   TemplateDeductionInfo &Info,
+                                   SmallVectorImpl<DeducedTemplateArgument> &
+                                                      Deduced,
+                                   unsigned TDF,
+                                   bool PartialOrdering = false,
+                            SmallVectorImpl<RefParamPartialOrderingComparison> *
+                                                      RefParamComparisons = 0);
+
+static Sema::TemplateDeductionResult
+DeduceTemplateArguments(Sema &S,
+                        TemplateParameterList *TemplateParams,
+                        const TemplateArgument *Params, unsigned NumParams,
+                        const TemplateArgument *Args, unsigned NumArgs,
+                        TemplateDeductionInfo &Info,
+                        SmallVectorImpl<DeducedTemplateArgument> &Deduced,
+                        bool NumberOfArgumentsMustMatch = true);
+
+/// \brief If the given expression is of a form that permits the deduction
+/// of a non-type template parameter, return the declaration of that
+/// non-type template parameter.
+static NonTypeTemplateParmDecl *getDeducedParameterFromExpr(Expr *E) {
+  if (ImplicitCastExpr *IC = dyn_cast<ImplicitCastExpr>(E))
+    E = IC->getSubExpr();
+
+  if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E))
+    return dyn_cast<NonTypeTemplateParmDecl>(DRE->getDecl());
+
+  return 0;
+}
+
+/// \brief Determine whether two declaration pointers refer to the same
+/// declaration.
+static bool isSameDeclaration(Decl *X, Decl *Y) {
+  if (!X || !Y)
+    return !X && !Y;
+
+  if (NamedDecl *NX = dyn_cast<NamedDecl>(X))
+    X = NX->getUnderlyingDecl();
+  if (NamedDecl *NY = dyn_cast<NamedDecl>(Y))
+    Y = NY->getUnderlyingDecl();
+
+  return X->getCanonicalDecl() == Y->getCanonicalDecl();
+}
+
+/// \brief Verify that the given, deduced template arguments are compatible.
+///
+/// \returns The deduced template argument, or a NULL template argument if
+/// the deduced template arguments were incompatible.
+static DeducedTemplateArgument
+checkDeducedTemplateArguments(ASTContext &Context,
+                              const DeducedTemplateArgument &X,
+                              const DeducedTemplateArgument &Y) {
+  // We have no deduction for one or both of the arguments; they're compatible.
+  if (X.isNull())
+    return Y;
+  if (Y.isNull())
+    return X;
+
+  switch (X.getKind()) {
+  case TemplateArgument::Null:
+    llvm_unreachable("Non-deduced template arguments handled above");
+
+  case TemplateArgument::Type:
+    // If two template type arguments have the same type, they're compatible.
+    if (Y.getKind() == TemplateArgument::Type &&
+        Context.hasSameType(X.getAsType(), Y.getAsType()))
+      return X;
+
+    return DeducedTemplateArgument();
+
+  case TemplateArgument::Integral:
+    // If we deduced a constant in one case and either a dependent expression or
+    // declaration in another case, keep the integral constant.
+    // If both are integral constants with the same value, keep that value.
+    if (Y.getKind() == TemplateArgument::Expression ||
+        Y.getKind() == TemplateArgument::Declaration ||
+        (Y.getKind() == TemplateArgument::Integral &&
+         hasSameExtendedValue(*X.getAsIntegral(), *Y.getAsIntegral())))
+      return DeducedTemplateArgument(X,
+                                     X.wasDeducedFromArrayBound() &&
+                                     Y.wasDeducedFromArrayBound());
+
+    // All other combinations are incompatible.
+    return DeducedTemplateArgument();
+
+  case TemplateArgument::Template:
+    if (Y.getKind() == TemplateArgument::Template &&
+        Context.hasSameTemplateName(X.getAsTemplate(), Y.getAsTemplate()))
+      return X;
+
+    // All other combinations are incompatible.
+    return DeducedTemplateArgument();
+
+  case TemplateArgument::TemplateExpansion:
+    if (Y.getKind() == TemplateArgument::TemplateExpansion &&
+        Context.hasSameTemplateName(X.getAsTemplateOrTemplatePattern(),
+                                    Y.getAsTemplateOrTemplatePattern()))
+      return X;
+
+    // All other combinations are incompatible.
+    return DeducedTemplateArgument();
+
+  case TemplateArgument::Expression:
+    // If we deduced a dependent expression in one case and either an integral
+    // constant or a declaration in another case, keep the integral constant
+    // or declaration.
+    if (Y.getKind() == TemplateArgument::Integral ||
+        Y.getKind() == TemplateArgument::Declaration)
+      return DeducedTemplateArgument(Y, X.wasDeducedFromArrayBound() &&
+                                     Y.wasDeducedFromArrayBound());
+
+    if (Y.getKind() == TemplateArgument::Expression) {
+      // Compare the expressions for equality
+      llvm::FoldingSetNodeID ID1, ID2;
+      X.getAsExpr()->Profile(ID1, Context, true);
+      Y.getAsExpr()->Profile(ID2, Context, true);
+      if (ID1 == ID2)
+        return X;
+    }
+
+    // All other combinations are incompatible.
+    return DeducedTemplateArgument();
+
+  case TemplateArgument::Declaration:
+    // If we deduced a declaration and a dependent expression, keep the
+    // declaration.
+    if (Y.getKind() == TemplateArgument::Expression)
+      return X;
+
+    // If we deduced a declaration and an integral constant, keep the
+    // integral constant.
+    if (Y.getKind() == TemplateArgument::Integral)
+      return Y;
+
+    // If we deduced two declarations, make sure they they refer to the
+    // same declaration.
+    if (Y.getKind() == TemplateArgument::Declaration &&
+        isSameDeclaration(X.getAsDecl(), Y.getAsDecl()))
+      return X;
+
+    // All other combinations are incompatible.
+    return DeducedTemplateArgument();
+
+  case TemplateArgument::Pack:
+    if (Y.getKind() != TemplateArgument::Pack ||
+        X.pack_size() != Y.pack_size())
+      return DeducedTemplateArgument();
+
+    for (TemplateArgument::pack_iterator XA = X.pack_begin(),
+                                      XAEnd = X.pack_end(),
+                                         YA = Y.pack_begin();
+         XA != XAEnd; ++XA, ++YA) {
+      if (checkDeducedTemplateArguments(Context,
+                    DeducedTemplateArgument(*XA, X.wasDeducedFromArrayBound()),
+                    DeducedTemplateArgument(*YA, Y.wasDeducedFromArrayBound()))
+            .isNull())
+        return DeducedTemplateArgument();
+    }
+
+    return X;
+  }
+
+  llvm_unreachable("Invalid TemplateArgument Kind!");
+}
+
+/// \brief Deduce the value of the given non-type template parameter
+/// from the given constant.
+static Sema::TemplateDeductionResult
+DeduceNonTypeTemplateArgument(Sema &S,
+                              NonTypeTemplateParmDecl *NTTP,
+                              llvm::APSInt Value, QualType ValueType,
+                              bool DeducedFromArrayBound,
+                              TemplateDeductionInfo &Info,
+                    SmallVectorImpl<DeducedTemplateArgument> &Deduced) {
+  assert(NTTP->getDepth() == 0 &&
+         "Cannot deduce non-type template argument with depth > 0");
+
+  DeducedTemplateArgument NewDeduced(Value, ValueType, DeducedFromArrayBound);
+  DeducedTemplateArgument Result = checkDeducedTemplateArguments(S.Context,
+                                                     Deduced[NTTP->getIndex()],
+                                                                 NewDeduced);
+  if (Result.isNull()) {
+    Info.Param = NTTP;
+    Info.FirstArg = Deduced[NTTP->getIndex()];
+    Info.SecondArg = NewDeduced;
+    return Sema::TDK_Inconsistent;
+  }
+
+  Deduced[NTTP->getIndex()] = Result;
+  return Sema::TDK_Success;
+}
+
+/// \brief Deduce the value of the given non-type template parameter
+/// from the given type- or value-dependent expression.
+///
+/// \returns true if deduction succeeded, false otherwise.
+static Sema::TemplateDeductionResult
+DeduceNonTypeTemplateArgument(Sema &S,
+                              NonTypeTemplateParmDecl *NTTP,
+                              Expr *Value,
+                              TemplateDeductionInfo &Info,
+                    SmallVectorImpl<DeducedTemplateArgument> &Deduced) {
+  assert(NTTP->getDepth() == 0 &&
+         "Cannot deduce non-type template argument with depth > 0");
+  assert((Value->isTypeDependent() || Value->isValueDependent()) &&
+         "Expression template argument must be type- or value-dependent.");
+
+  DeducedTemplateArgument NewDeduced(Value);
+  DeducedTemplateArgument Result = checkDeducedTemplateArguments(S.Context,
+                                                     Deduced[NTTP->getIndex()],
+                                                                 NewDeduced);
+
+  if (Result.isNull()) {
+    Info.Param = NTTP;
+    Info.FirstArg = Deduced[NTTP->getIndex()];
+    Info.SecondArg = NewDeduced;
+    return Sema::TDK_Inconsistent;
+  }
+
+  Deduced[NTTP->getIndex()] = Result;
+  return Sema::TDK_Success;
+}
+
+/// \brief Deduce the value of the given non-type template parameter
+/// from the given declaration.
+///
+/// \returns true if deduction succeeded, false otherwise.
+static Sema::TemplateDeductionResult
+DeduceNonTypeTemplateArgument(Sema &S,
+                              NonTypeTemplateParmDecl *NTTP,
+                              Decl *D,
+                              TemplateDeductionInfo &Info,
+                    SmallVectorImpl<DeducedTemplateArgument> &Deduced) {
+  assert(NTTP->getDepth() == 0 &&
+         "Cannot deduce non-type template argument with depth > 0");
+
+  DeducedTemplateArgument NewDeduced(D? D->getCanonicalDecl() : 0);
+  DeducedTemplateArgument Result = checkDeducedTemplateArguments(S.Context,
+                                                     Deduced[NTTP->getIndex()],
+                                                                 NewDeduced);
+  if (Result.isNull()) {
+    Info.Param = NTTP;
+    Info.FirstArg = Deduced[NTTP->getIndex()];
+    Info.SecondArg = NewDeduced;
+    return Sema::TDK_Inconsistent;
+  }
+
+  Deduced[NTTP->getIndex()] = Result;
+  return Sema::TDK_Success;
+}
+
+static Sema::TemplateDeductionResult
+DeduceTemplateArguments(Sema &S,
+                        TemplateParameterList *TemplateParams,
+                        TemplateName Param,
+                        TemplateName Arg,
+                        TemplateDeductionInfo &Info,
+                    SmallVectorImpl<DeducedTemplateArgument> &Deduced) {
+  TemplateDecl *ParamDecl = Param.getAsTemplateDecl();
+  if (!ParamDecl) {
+    // The parameter type is dependent and is not a template template parameter,
+    // so there is nothing that we can deduce.
+    return Sema::TDK_Success;
+  }
+
+  if (TemplateTemplateParmDecl *TempParam
+        = dyn_cast<TemplateTemplateParmDecl>(ParamDecl)) {
+    DeducedTemplateArgument NewDeduced(S.Context.getCanonicalTemplateName(Arg));
+    DeducedTemplateArgument Result = checkDeducedTemplateArguments(S.Context,
+                                                 Deduced[TempParam->getIndex()],
+                                                                   NewDeduced);
+    if (Result.isNull()) {
+      Info.Param = TempParam;
+      Info.FirstArg = Deduced[TempParam->getIndex()];
+      Info.SecondArg = NewDeduced;
+      return Sema::TDK_Inconsistent;
+    }
+
+    Deduced[TempParam->getIndex()] = Result;
+    return Sema::TDK_Success;
+  }
+
+  // Verify that the two template names are equivalent.
+  if (S.Context.hasSameTemplateName(Param, Arg))
+    return Sema::TDK_Success;
+
+  // Mismatch of non-dependent template parameter to argument.
+  Info.FirstArg = TemplateArgument(Param);
+  Info.SecondArg = TemplateArgument(Arg);
+  return Sema::TDK_NonDeducedMismatch;
+}
+
+/// \brief Deduce the template arguments by comparing the template parameter
+/// type (which is a template-id) with the template argument type.
+///
+/// \param S the Sema
+///
+/// \param TemplateParams the template parameters that we are deducing
+///
+/// \param Param the parameter type
+///
+/// \param Arg the argument type
+///
+/// \param Info information about the template argument deduction itself
+///
+/// \param Deduced the deduced template arguments
+///
+/// \returns the result of template argument deduction so far. Note that a
+/// "success" result means that template argument deduction has not yet failed,
+/// but it may still fail, later, for other reasons.
+static Sema::TemplateDeductionResult
+DeduceTemplateArguments(Sema &S,
+                        TemplateParameterList *TemplateParams,
+                        const TemplateSpecializationType *Param,
+                        QualType Arg,
+                        TemplateDeductionInfo &Info,
+                    SmallVectorImpl<DeducedTemplateArgument> &Deduced) {
+  assert(Arg.isCanonical() && "Argument type must be canonical");
+
+  // Check whether the template argument is a dependent template-id.
+  if (const TemplateSpecializationType *SpecArg
+        = dyn_cast<TemplateSpecializationType>(Arg)) {
+    // Perform template argument deduction for the template name.
+    if (Sema::TemplateDeductionResult Result
+          = DeduceTemplateArguments(S, TemplateParams,
+                                    Param->getTemplateName(),
+                                    SpecArg->getTemplateName(),
+                                    Info, Deduced))
+      return Result;
+
+
+    // Perform template argument deduction on each template
+    // argument. Ignore any missing/extra arguments, since they could be
+    // filled in by default arguments.
+    return DeduceTemplateArguments(S, TemplateParams,
+                                   Param->getArgs(), Param->getNumArgs(),
+                                   SpecArg->getArgs(), SpecArg->getNumArgs(),
+                                   Info, Deduced,
+                                   /*NumberOfArgumentsMustMatch=*/false);
+  }
+
+  // If the argument type is a class template specialization, we
+  // perform template argument deduction using its template
+  // arguments.
+  const RecordType *RecordArg = dyn_cast<RecordType>(Arg);
+  if (!RecordArg)
+    return Sema::TDK_NonDeducedMismatch;
+
+  ClassTemplateSpecializationDecl *SpecArg
+    = dyn_cast<ClassTemplateSpecializationDecl>(RecordArg->getDecl());
+  if (!SpecArg)
+    return Sema::TDK_NonDeducedMismatch;
+
+  // Perform template argument deduction for the template name.
+  if (Sema::TemplateDeductionResult Result
+        = DeduceTemplateArguments(S,
+                                  TemplateParams,
+                                  Param->getTemplateName(),
+                               TemplateName(SpecArg->getSpecializedTemplate()),
+                                  Info, Deduced))
+    return Result;
+
+  // Perform template argument deduction for the template arguments.
+  return DeduceTemplateArguments(S, TemplateParams,
+                                 Param->getArgs(), Param->getNumArgs(),
+                                 SpecArg->getTemplateArgs().data(),
+                                 SpecArg->getTemplateArgs().size(),
+                                 Info, Deduced);
+}
+
+/// \brief Determines whether the given type is an opaque type that
+/// might be more qualified when instantiated.
+static bool IsPossiblyOpaquelyQualifiedType(QualType T) {
+  switch (T->getTypeClass()) {
+  case Type::TypeOfExpr:
+  case Type::TypeOf:
+  case Type::DependentName:
+  case Type::Decltype:
+  case Type::UnresolvedUsing:
+  case Type::TemplateTypeParm:
+    return true;
+
+  case Type::ConstantArray:
+  case Type::IncompleteArray:
+  case Type::VariableArray:
+  case Type::DependentSizedArray:
+    return IsPossiblyOpaquelyQualifiedType(
+                                      cast<ArrayType>(T)->getElementType());
+
+  default:
+    return false;
+  }
+}
+
+/// \brief Retrieve the depth and index of a template parameter.
+static std::pair<unsigned, unsigned>
+getDepthAndIndex(NamedDecl *ND) {
+  if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(ND))
+    return std::make_pair(TTP->getDepth(), TTP->getIndex());
+
+  if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(ND))
+    return std::make_pair(NTTP->getDepth(), NTTP->getIndex());
+
+  TemplateTemplateParmDecl *TTP = cast<TemplateTemplateParmDecl>(ND);
+  return std::make_pair(TTP->getDepth(), TTP->getIndex());
+}
+
+/// \brief Retrieve the depth and index of an unexpanded parameter pack.
+static std::pair<unsigned, unsigned>
+getDepthAndIndex(UnexpandedParameterPack UPP) {
+  if (const TemplateTypeParmType *TTP
+                          = UPP.first.dyn_cast<const TemplateTypeParmType *>())
+    return std::make_pair(TTP->getDepth(), TTP->getIndex());
+
+  return getDepthAndIndex(UPP.first.get<NamedDecl *>());
+}
+
+/// \brief Helper function to build a TemplateParameter when we don't
+/// know its type statically.
+static TemplateParameter makeTemplateParameter(Decl *D) {
+  if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(D))
+    return TemplateParameter(TTP);
+  else if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(D))
+    return TemplateParameter(NTTP);
+
+  return TemplateParameter(cast<TemplateTemplateParmDecl>(D));
+}
+
+/// \brief Prepare to perform template argument deduction for all of the
+/// arguments in a set of argument packs.
+static void PrepareArgumentPackDeduction(Sema &S,
+                       SmallVectorImpl<DeducedTemplateArgument> &Deduced,
+                                           ArrayRef<unsigned> PackIndices,
+                     SmallVectorImpl<DeducedTemplateArgument> &SavedPacks,
+         SmallVectorImpl<
+           SmallVector<DeducedTemplateArgument, 4> > &NewlyDeducedPacks) {
+  // Save the deduced template arguments for each parameter pack expanded
+  // by this pack expansion, then clear out the deduction.
+  for (unsigned I = 0, N = PackIndices.size(); I != N; ++I) {
+    // Save the previously-deduced argument pack, then clear it out so that we
+    // can deduce a new argument pack.
+    SavedPacks[I] = Deduced[PackIndices[I]];
+    Deduced[PackIndices[I]] = TemplateArgument();
+
+    // If the template arugment pack was explicitly specified, add that to
+    // the set of deduced arguments.
+    const TemplateArgument *ExplicitArgs;
+    unsigned NumExplicitArgs;
+    if (NamedDecl *PartiallySubstitutedPack
+        = S.CurrentInstantiationScope->getPartiallySubstitutedPack(
+                                                           &ExplicitArgs,
+                                                           &NumExplicitArgs)) {
+      if (getDepthAndIndex(PartiallySubstitutedPack).second == PackIndices[I])
+        NewlyDeducedPacks[I].append(ExplicitArgs,
+                                    ExplicitArgs + NumExplicitArgs);
+    }
+  }
+}
+
+/// \brief Finish template argument deduction for a set of argument packs,
+/// producing the argument packs and checking for consistency with prior
+/// deductions.
+static Sema::TemplateDeductionResult
+FinishArgumentPackDeduction(Sema &S,
+                            TemplateParameterList *TemplateParams,
+                            bool HasAnyArguments,
+                        SmallVectorImpl<DeducedTemplateArgument> &Deduced,
+                            ArrayRef<unsigned> PackIndices,
+                    SmallVectorImpl<DeducedTemplateArgument> &SavedPacks,
+        SmallVectorImpl<
+          SmallVector<DeducedTemplateArgument, 4> > &NewlyDeducedPacks,
+                            TemplateDeductionInfo &Info) {
+  // Build argument packs for each of the parameter packs expanded by this
+  // pack expansion.
+  for (unsigned I = 0, N = PackIndices.size(); I != N; ++I) {
+    if (HasAnyArguments && NewlyDeducedPacks[I].empty()) {
+      // We were not able to deduce anything for this parameter pack,
+      // so just restore the saved argument pack.
+      Deduced[PackIndices[I]] = SavedPacks[I];
+      continue;
+    }
+
+    DeducedTemplateArgument NewPack;
+
+    if (NewlyDeducedPacks[I].empty()) {
+      // If we deduced an empty argument pack, create it now.
+      NewPack = DeducedTemplateArgument(TemplateArgument(0, 0));
+    } else {
+      TemplateArgument *ArgumentPack
+        = new (S.Context) TemplateArgument [NewlyDeducedPacks[I].size()];
+      std::copy(NewlyDeducedPacks[I].begin(), NewlyDeducedPacks[I].end(),
+                ArgumentPack);
+      NewPack
+        = DeducedTemplateArgument(TemplateArgument(ArgumentPack,
+                                                   NewlyDeducedPacks[I].size()),
+                            NewlyDeducedPacks[I][0].wasDeducedFromArrayBound());
+    }
+
+    DeducedTemplateArgument Result
+      = checkDeducedTemplateArguments(S.Context, SavedPacks[I], NewPack);
+    if (Result.isNull()) {
+      Info.Param
+        = makeTemplateParameter(TemplateParams->getParam(PackIndices[I]));
+      Info.FirstArg = SavedPacks[I];
+      Info.SecondArg = NewPack;
+      return Sema::TDK_Inconsistent;
+    }
+
+    Deduced[PackIndices[I]] = Result;
+  }
+
+  return Sema::TDK_Success;
+}
+
+/// \brief Deduce the template arguments by comparing the list of parameter
+/// types to the list of argument types, as in the parameter-type-lists of
+/// function types (C++ [temp.deduct.type]p10).
+///
+/// \param S The semantic analysis object within which we are deducing
+///
+/// \param TemplateParams The template parameters that we are deducing
+///
+/// \param Params The list of parameter types
+///
+/// \param NumParams The number of types in \c Params
+///
+/// \param Args The list of argument types
+///
+/// \param NumArgs The number of types in \c Args
+///
+/// \param Info information about the template argument deduction itself
+///
+/// \param Deduced the deduced template arguments
+///
+/// \param TDF bitwise OR of the TemplateDeductionFlags bits that describe
+/// how template argument deduction is performed.
+///
+/// \param PartialOrdering If true, we are performing template argument
+/// deduction for during partial ordering for a call
+/// (C++0x [temp.deduct.partial]).
+///
+/// \param RefParamComparisons If we're performing template argument deduction
+/// in the context of partial ordering, the set of qualifier comparisons.
+///
+/// \returns the result of template argument deduction so far. Note that a
+/// "success" result means that template argument deduction has not yet failed,
+/// but it may still fail, later, for other reasons.
+static Sema::TemplateDeductionResult
+DeduceTemplateArguments(Sema &S,
+                        TemplateParameterList *TemplateParams,
+                        const QualType *Params, unsigned NumParams,
+                        const QualType *Args, unsigned NumArgs,
+                        TemplateDeductionInfo &Info,
+                      SmallVectorImpl<DeducedTemplateArgument> &Deduced,
+                        unsigned TDF,
+                        bool PartialOrdering = false,
+                        SmallVectorImpl<RefParamPartialOrderingComparison> *
+                                                     RefParamComparisons = 0) {
+  // Fast-path check to see if we have too many/too few arguments.
+  if (NumParams != NumArgs &&
+      !(NumParams && isa<PackExpansionType>(Params[NumParams - 1])) &&
+      !(NumArgs && isa<PackExpansionType>(Args[NumArgs - 1])))
+    return Sema::TDK_NonDeducedMismatch;
+
+  // C++0x [temp.deduct.type]p10:
+  //   Similarly, if P has a form that contains (T), then each parameter type
+  //   Pi of the respective parameter-type- list of P is compared with the
+  //   corresponding parameter type Ai of the corresponding parameter-type-list
+  //   of A. [...]
+  unsigned ArgIdx = 0, ParamIdx = 0;
+  for (; ParamIdx != NumParams; ++ParamIdx) {
+    // Check argument types.
+    const PackExpansionType *Expansion
+                                = dyn_cast<PackExpansionType>(Params[ParamIdx]);
+    if (!Expansion) {
+      // Simple case: compare the parameter and argument types at this point.
+
+      // Make sure we have an argument.
+      if (ArgIdx >= NumArgs)
+        return Sema::TDK_NonDeducedMismatch;
+
+      if (isa<PackExpansionType>(Args[ArgIdx])) {
+        // C++0x [temp.deduct.type]p22:
+        //   If the original function parameter associated with A is a function
+        //   parameter pack and the function parameter associated with P is not
+        //   a function parameter pack, then template argument deduction fails.
+        return Sema::TDK_NonDeducedMismatch;
+      }
+
+      if (Sema::TemplateDeductionResult Result
+            = DeduceTemplateArgumentsByTypeMatch(S, TemplateParams,
+                                                 Params[ParamIdx], Args[ArgIdx],
+                                                 Info, Deduced, TDF,
+                                                 PartialOrdering,
+                                                 RefParamComparisons))
+        return Result;
+
+      ++ArgIdx;
+      continue;
+    }
+
+    // C++0x [temp.deduct.type]p5:
+    //   The non-deduced contexts are:
+    //     - A function parameter pack that does not occur at the end of the
+    //       parameter-declaration-clause.
+    if (ParamIdx + 1 < NumParams)
+      return Sema::TDK_Success;
+
+    // C++0x [temp.deduct.type]p10:
+    //   If the parameter-declaration corresponding to Pi is a function
+    //   parameter pack, then the type of its declarator- id is compared with
+    //   each remaining parameter type in the parameter-type-list of A. Each
+    //   comparison deduces template arguments for subsequent positions in the
+    //   template parameter packs expanded by the function parameter pack.
+
+    // Compute the set of template parameter indices that correspond to
+    // parameter packs expanded by the pack expansion.
+    SmallVector<unsigned, 2> PackIndices;
+    QualType Pattern = Expansion->getPattern();
+    {
+      llvm::SmallBitVector SawIndices(TemplateParams->size());
+      SmallVector<UnexpandedParameterPack, 2> Unexpanded;
+      S.collectUnexpandedParameterPacks(Pattern, Unexpanded);
+      for (unsigned I = 0, N = Unexpanded.size(); I != N; ++I) {
+        unsigned Depth, Index;
+        llvm::tie(Depth, Index) = getDepthAndIndex(Unexpanded[I]);
+        if (Depth == 0 && !SawIndices[Index]) {
+          SawIndices[Index] = true;
+          PackIndices.push_back(Index);
+        }
+      }
+    }
+    assert(!PackIndices.empty() && "Pack expansion without unexpanded packs?");
+
+    // Keep track of the deduced template arguments for each parameter pack
+    // expanded by this pack expansion (the outer index) and for each
+    // template argument (the inner SmallVectors).
+    SmallVector<SmallVector<DeducedTemplateArgument, 4>, 2>
+      NewlyDeducedPacks(PackIndices.size());
+    SmallVector<DeducedTemplateArgument, 2>
+      SavedPacks(PackIndices.size());
+    PrepareArgumentPackDeduction(S, Deduced, PackIndices, SavedPacks,
+                                 NewlyDeducedPacks);
+
+    bool HasAnyArguments = false;
+    for (; ArgIdx < NumArgs; ++ArgIdx) {
+      HasAnyArguments = true;
+
+      // Deduce template arguments from the pattern.
+      if (Sema::TemplateDeductionResult Result
+            = DeduceTemplateArgumentsByTypeMatch(S, TemplateParams, Pattern,
+                                                 Args[ArgIdx], Info, Deduced,
+                                                 TDF, PartialOrdering,
+                                                 RefParamComparisons))
+        return Result;
+
+      // Capture the deduced template arguments for each parameter pack expanded
+      // by this pack expansion, add them to the list of arguments we've deduced
+      // for that pack, then clear out the deduced argument.
+      for (unsigned I = 0, N = PackIndices.size(); I != N; ++I) {
+        DeducedTemplateArgument &DeducedArg = Deduced[PackIndices[I]];
+        if (!DeducedArg.isNull()) {
+          NewlyDeducedPacks[I].push_back(DeducedArg);
+          DeducedArg = DeducedTemplateArgument();
+        }
+      }
+    }
+
+    // Build argument packs for each of the parameter packs expanded by this
+    // pack expansion.
+    if (Sema::TemplateDeductionResult Result
+          = FinishArgumentPackDeduction(S, TemplateParams, HasAnyArguments,
+                                        Deduced, PackIndices, SavedPacks,
+                                        NewlyDeducedPacks, Info))
+      return Result;
+  }
+
+  // Make sure we don't have any extra arguments.
+  if (ArgIdx < NumArgs)
+    return Sema::TDK_NonDeducedMismatch;
+
+  return Sema::TDK_Success;
+}
+
+/// \brief Determine whether the parameter has qualifiers that are either
+/// inconsistent with or a superset of the argument's qualifiers.
+static bool hasInconsistentOrSupersetQualifiersOf(QualType ParamType,
+                                                  QualType ArgType) {
+  Qualifiers ParamQs = ParamType.getQualifiers();
+  Qualifiers ArgQs = ArgType.getQualifiers();
+
+  if (ParamQs == ArgQs)
+    return false;
+       
+  // Mismatched (but not missing) Objective-C GC attributes.
+  if (ParamQs.getObjCGCAttr() != ArgQs.getObjCGCAttr() && 
+      ParamQs.hasObjCGCAttr())
+    return true;
+  
+  // Mismatched (but not missing) address spaces.
+  if (ParamQs.getAddressSpace() != ArgQs.getAddressSpace() &&
+      ParamQs.hasAddressSpace())
+    return true;
+
+  // Mismatched (but not missing) Objective-C lifetime qualifiers.
+  if (ParamQs.getObjCLifetime() != ArgQs.getObjCLifetime() &&
+      ParamQs.hasObjCLifetime())
+    return true;
+  
+  // CVR qualifier superset.
+  return (ParamQs.getCVRQualifiers() != ArgQs.getCVRQualifiers()) &&
+      ((ParamQs.getCVRQualifiers() | ArgQs.getCVRQualifiers())
+                                                == ParamQs.getCVRQualifiers());
+}
+
+/// \brief Deduce the template arguments by comparing the parameter type and
+/// the argument type (C++ [temp.deduct.type]).
+///
+/// \param S the semantic analysis object within which we are deducing
+///
+/// \param TemplateParams the template parameters that we are deducing
+///
+/// \param ParamIn the parameter type
+///
+/// \param ArgIn the argument type
+///
+/// \param Info information about the template argument deduction itself
+///
+/// \param Deduced the deduced template arguments
+///
+/// \param TDF bitwise OR of the TemplateDeductionFlags bits that describe
+/// how template argument deduction is performed.
+///
+/// \param PartialOrdering Whether we're performing template argument deduction
+/// in the context of partial ordering (C++0x [temp.deduct.partial]).
+///
+/// \param RefParamComparisons If we're performing template argument deduction
+/// in the context of partial ordering, the set of qualifier comparisons.
+///
+/// \returns the result of template argument deduction so far. Note that a
+/// "success" result means that template argument deduction has not yet failed,
+/// but it may still fail, later, for other reasons.
+static Sema::TemplateDeductionResult
+DeduceTemplateArgumentsByTypeMatch(Sema &S,
+                                   TemplateParameterList *TemplateParams,
+                                   QualType ParamIn, QualType ArgIn,
+                                   TemplateDeductionInfo &Info,
+                            SmallVectorImpl<DeducedTemplateArgument> &Deduced,
+                                   unsigned TDF,
+                                   bool PartialOrdering,
+                            SmallVectorImpl<RefParamPartialOrderingComparison> *
+                                                          RefParamComparisons) {
+  // We only want to look at the canonical types, since typedefs and
+  // sugar are not part of template argument deduction.
+  QualType Param = S.Context.getCanonicalType(ParamIn);
+  QualType Arg = S.Context.getCanonicalType(ArgIn);
+
+  // If the argument type is a pack expansion, look at its pattern.
+  // This isn't explicitly called out
+  if (const PackExpansionType *ArgExpansion
+                                            = dyn_cast<PackExpansionType>(Arg))
+    Arg = ArgExpansion->getPattern();
+
+  if (PartialOrdering) {
+    // C++0x [temp.deduct.partial]p5:
+    //   Before the partial ordering is done, certain transformations are
+    //   performed on the types used for partial ordering:
+    //     - If P is a reference type, P is replaced by the type referred to.
+    const ReferenceType *ParamRef = Param->getAs<ReferenceType>();
+    if (ParamRef)
+      Param = ParamRef->getPointeeType();
+
+    //     - If A is a reference type, A is replaced by the type referred to.
+    const ReferenceType *ArgRef = Arg->getAs<ReferenceType>();
+    if (ArgRef)
+      Arg = ArgRef->getPointeeType();
+
+    if (RefParamComparisons && ParamRef && ArgRef) {
+      // C++0x [temp.deduct.partial]p6:
+      //   If both P and A were reference types (before being replaced with the
+      //   type referred to above), determine which of the two types (if any) is
+      //   more cv-qualified than the other; otherwise the types are considered
+      //   to be equally cv-qualified for partial ordering purposes. The result
+      //   of this determination will be used below.
+      //
+      // We save this information for later, using it only when deduction
+      // succeeds in both directions.
+      RefParamPartialOrderingComparison Comparison;
+      Comparison.ParamIsRvalueRef = ParamRef->getAs<RValueReferenceType>();
+      Comparison.ArgIsRvalueRef = ArgRef->getAs<RValueReferenceType>();
+      Comparison.Qualifiers = NeitherMoreQualified;
+      
+      Qualifiers ParamQuals = Param.getQualifiers();
+      Qualifiers ArgQuals = Arg.getQualifiers();
+      if (ParamQuals.isStrictSupersetOf(ArgQuals))
+        Comparison.Qualifiers = ParamMoreQualified;
+      else if (ArgQuals.isStrictSupersetOf(ParamQuals))
+        Comparison.Qualifiers = ArgMoreQualified;
+      RefParamComparisons->push_back(Comparison);
+    }
+
+    // C++0x [temp.deduct.partial]p7:
+    //   Remove any top-level cv-qualifiers:
+    //     - If P is a cv-qualified type, P is replaced by the cv-unqualified
+    //       version of P.
+    Param = Param.getUnqualifiedType();
+    //     - If A is a cv-qualified type, A is replaced by the cv-unqualified
+    //       version of A.
+    Arg = Arg.getUnqualifiedType();
+  } else {
+    // C++0x [temp.deduct.call]p4 bullet 1:
+    //   - If the original P is a reference type, the deduced A (i.e., the type
+    //     referred to by the reference) can be more cv-qualified than the
+    //     transformed A.
+    if (TDF & TDF_ParamWithReferenceType) {
+      Qualifiers Quals;
+      QualType UnqualParam = S.Context.getUnqualifiedArrayType(Param, Quals);
+      Quals.setCVRQualifiers(Quals.getCVRQualifiers() &
+                             Arg.getCVRQualifiers());
+      Param = S.Context.getQualifiedType(UnqualParam, Quals);
+    }
+
+    if ((TDF & TDF_TopLevelParameterTypeList) && !Param->isFunctionType()) {
+      // C++0x [temp.deduct.type]p10:
+      //   If P and A are function types that originated from deduction when
+      //   taking the address of a function template (14.8.2.2) or when deducing
+      //   template arguments from a function declaration (14.8.2.6) and Pi and
+      //   Ai are parameters of the top-level parameter-type-list of P and A,
+      //   respectively, Pi is adjusted if it is an rvalue reference to a
+      //   cv-unqualified template parameter and Ai is an lvalue reference, in
+      //   which case the type of Pi is changed to be the template parameter
+      //   type (i.e., T&& is changed to simply T). [ Note: As a result, when
+      //   Pi is T&& and Ai is X&, the adjusted Pi will be T, causing T to be
+      //   deduced as X&. - end note ]
+      TDF &= ~TDF_TopLevelParameterTypeList;
+
+      if (const RValueReferenceType *ParamRef
+                                        = Param->getAs<RValueReferenceType>()) {
+        if (isa<TemplateTypeParmType>(ParamRef->getPointeeType()) &&
+            !ParamRef->getPointeeType().getQualifiers())
+          if (Arg->isLValueReferenceType())
+            Param = ParamRef->getPointeeType();
+      }
+    }
+  }
+
+  // C++ [temp.deduct.type]p9:
+  //   A template type argument T, a template template argument TT or a
+  //   template non-type argument i can be deduced if P and A have one of
+  //   the following forms:
+  //
+  //     T
+  //     cv-list T
+  if (const TemplateTypeParmType *TemplateTypeParm
+        = Param->getAs<TemplateTypeParmType>()) {
+    // Just skip any attempts to deduce from a placeholder type.
+    if (Arg->isPlaceholderType())
+      return Sema::TDK_Success;
+    
+    unsigned Index = TemplateTypeParm->getIndex();
+    bool RecanonicalizeArg = false;
+
+    // If the argument type is an array type, move the qualifiers up to the
+    // top level, so they can be matched with the qualifiers on the parameter.
+    if (isa<ArrayType>(Arg)) {
+      Qualifiers Quals;
+      Arg = S.Context.getUnqualifiedArrayType(Arg, Quals);
+      if (Quals) {
+        Arg = S.Context.getQualifiedType(Arg, Quals);
+        RecanonicalizeArg = true;
+      }
+    }
+
+    // The argument type can not be less qualified than the parameter
+    // type.
+    if (!(TDF & TDF_IgnoreQualifiers) &&
+        hasInconsistentOrSupersetQualifiersOf(Param, Arg)) {
+      Info.Param = cast<TemplateTypeParmDecl>(TemplateParams->getParam(Index));
+      Info.FirstArg = TemplateArgument(Param);
+      Info.SecondArg = TemplateArgument(Arg);
+      return Sema::TDK_Underqualified;
+    }
+
+    assert(TemplateTypeParm->getDepth() == 0 && "Can't deduce with depth > 0");
+    assert(Arg != S.Context.OverloadTy && "Unresolved overloaded function");
+    QualType DeducedType = Arg;
+
+    // Remove any qualifiers on the parameter from the deduced type.
+    // We checked the qualifiers for consistency above.
+    Qualifiers DeducedQs = DeducedType.getQualifiers();
+    Qualifiers ParamQs = Param.getQualifiers();
+    DeducedQs.removeCVRQualifiers(ParamQs.getCVRQualifiers());
+    if (ParamQs.hasObjCGCAttr())
+      DeducedQs.removeObjCGCAttr();
+    if (ParamQs.hasAddressSpace())
+      DeducedQs.removeAddressSpace();
+    if (ParamQs.hasObjCLifetime())
+      DeducedQs.removeObjCLifetime();
+    
+    // Objective-C ARC:
+    //   If template deduction would produce a lifetime qualifier on a type
+    //   that is not a lifetime type, template argument deduction fails.
+    if (ParamQs.hasObjCLifetime() && !DeducedType->isObjCLifetimeType() &&
+        !DeducedType->isDependentType()) {
+      Info.Param = cast<TemplateTypeParmDecl>(TemplateParams->getParam(Index));
+      Info.FirstArg = TemplateArgument(Param);
+      Info.SecondArg = TemplateArgument(Arg);
+      return Sema::TDK_Underqualified;      
+    }
+    
+    // Objective-C ARC:
+    //   If template deduction would produce an argument type with lifetime type
+    //   but no lifetime qualifier, the __strong lifetime qualifier is inferred.
+    if (S.getLangOpts().ObjCAutoRefCount &&
+        DeducedType->isObjCLifetimeType() &&
+        !DeducedQs.hasObjCLifetime())
+      DeducedQs.setObjCLifetime(Qualifiers::OCL_Strong);
+    
+    DeducedType = S.Context.getQualifiedType(DeducedType.getUnqualifiedType(),
+                                             DeducedQs);
+    
+    if (RecanonicalizeArg)
+      DeducedType = S.Context.getCanonicalType(DeducedType);
+
+    DeducedTemplateArgument NewDeduced(DeducedType);
+    DeducedTemplateArgument Result = checkDeducedTemplateArguments(S.Context,
+                                                                 Deduced[Index],
+                                                                   NewDeduced);
+    if (Result.isNull()) {
+      Info.Param = cast<TemplateTypeParmDecl>(TemplateParams->getParam(Index));
+      Info.FirstArg = Deduced[Index];
+      Info.SecondArg = NewDeduced;
+      return Sema::TDK_Inconsistent;
+    }
+
+    Deduced[Index] = Result;
+    return Sema::TDK_Success;
+  }
+
+  // Set up the template argument deduction information for a failure.
+  Info.FirstArg = TemplateArgument(ParamIn);
+  Info.SecondArg = TemplateArgument(ArgIn);
+
+  // If the parameter is an already-substituted template parameter
+  // pack, do nothing: we don't know which of its arguments to look
+  // at, so we have to wait until all of the parameter packs in this
+  // expansion have arguments.
+  if (isa<SubstTemplateTypeParmPackType>(Param))
+    return Sema::TDK_Success;
+
+  // Check the cv-qualifiers on the parameter and argument types.
+  if (!(TDF & TDF_IgnoreQualifiers)) {
+    if (TDF & TDF_ParamWithReferenceType) {
+      if (hasInconsistentOrSupersetQualifiersOf(Param, Arg))
+        return Sema::TDK_NonDeducedMismatch;
+    } else if (!IsPossiblyOpaquelyQualifiedType(Param)) {
+      if (Param.getCVRQualifiers() != Arg.getCVRQualifiers())
+        return Sema::TDK_NonDeducedMismatch;
+    }
+    
+    // If the parameter type is not dependent, there is nothing to deduce.
+    if (!Param->isDependentType()) {
+      if (!(TDF & TDF_SkipNonDependent) && Param != Arg)
+        return Sema::TDK_NonDeducedMismatch;
+      
+      return Sema::TDK_Success;
+    }
+  } else if (!Param->isDependentType() &&
+             Param.getUnqualifiedType() == Arg.getUnqualifiedType()) {
+    return Sema::TDK_Success;
+  }
+
+  switch (Param->getTypeClass()) {
+    // Non-canonical types cannot appear here.
+#define NON_CANONICAL_TYPE(Class, Base) \
+  case Type::Class: llvm_unreachable("deducing non-canonical type: " #Class);
+#define TYPE(Class, Base)
+#include "clang/AST/TypeNodes.def"
+      
+    case Type::TemplateTypeParm:
+    case Type::SubstTemplateTypeParmPack:
+      llvm_unreachable("Type nodes handled above");
+
+    // These types cannot be dependent, so simply check whether the types are
+    // the same.
+    case Type::Builtin:
+    case Type::VariableArray:
+    case Type::Vector:
+    case Type::FunctionNoProto:
+    case Type::Record:
+    case Type::Enum:
+    case Type::ObjCObject:
+    case Type::ObjCInterface:
+    case Type::ObjCObjectPointer: {
+      if (TDF & TDF_SkipNonDependent)
+        return Sema::TDK_Success;
+      
+      if (TDF & TDF_IgnoreQualifiers) {
+        Param = Param.getUnqualifiedType();
+        Arg = Arg.getUnqualifiedType();
+      }
+            
+      return Param == Arg? Sema::TDK_Success : Sema::TDK_NonDeducedMismatch;
+    }
+      
+    //     _Complex T   [placeholder extension]  
+    case Type::Complex:
+      if (const ComplexType *ComplexArg = Arg->getAs<ComplexType>())
+        return DeduceTemplateArgumentsByTypeMatch(S, TemplateParams, 
+                                    cast<ComplexType>(Param)->getElementType(), 
+                                    ComplexArg->getElementType(),
+                                    Info, Deduced, TDF);
+
+      return Sema::TDK_NonDeducedMismatch;
+
+    //     _Atomic T   [extension]
+    case Type::Atomic:
+      if (const AtomicType *AtomicArg = Arg->getAs<AtomicType>())
+        return DeduceTemplateArgumentsByTypeMatch(S, TemplateParams,
+                                       cast<AtomicType>(Param)->getValueType(),
+                                       AtomicArg->getValueType(),
+                                       Info, Deduced, TDF);
+
+      return Sema::TDK_NonDeducedMismatch;
+
+    //     T *
+    case Type::Pointer: {
+      QualType PointeeType;
+      if (const PointerType *PointerArg = Arg->getAs<PointerType>()) {
+        PointeeType = PointerArg->getPointeeType();
+      } else if (const ObjCObjectPointerType *PointerArg
+                   = Arg->getAs<ObjCObjectPointerType>()) {
+        PointeeType = PointerArg->getPointeeType();
+      } else {
+        return Sema::TDK_NonDeducedMismatch;
+      }
+
+      unsigned SubTDF = TDF & (TDF_IgnoreQualifiers | TDF_DerivedClass);
+      return DeduceTemplateArgumentsByTypeMatch(S, TemplateParams,
+                                     cast<PointerType>(Param)->getPointeeType(),
+                                     PointeeType,
+                                     Info, Deduced, SubTDF);
+    }
+
+    //     T &
+    case Type::LValueReference: {
+      const LValueReferenceType *ReferenceArg = Arg->getAs<LValueReferenceType>();
+      if (!ReferenceArg)
+        return Sema::TDK_NonDeducedMismatch;
+
+      return DeduceTemplateArgumentsByTypeMatch(S, TemplateParams,
+                           cast<LValueReferenceType>(Param)->getPointeeType(),
+                           ReferenceArg->getPointeeType(), Info, Deduced, 0);
+    }
+
+    //     T && [C++0x]
+    case Type::RValueReference: {
+      const RValueReferenceType *ReferenceArg = Arg->getAs<RValueReferenceType>();
+      if (!ReferenceArg)
+        return Sema::TDK_NonDeducedMismatch;
+
+      return DeduceTemplateArgumentsByTypeMatch(S, TemplateParams,
+                             cast<RValueReferenceType>(Param)->getPointeeType(),
+                             ReferenceArg->getPointeeType(),
+                             Info, Deduced, 0);
+    }
+
+    //     T [] (implied, but not stated explicitly)
+    case Type::IncompleteArray: {
+      const IncompleteArrayType *IncompleteArrayArg =
+        S.Context.getAsIncompleteArrayType(Arg);
+      if (!IncompleteArrayArg)
+        return Sema::TDK_NonDeducedMismatch;
+
+      unsigned SubTDF = TDF & TDF_IgnoreQualifiers;
+      return DeduceTemplateArgumentsByTypeMatch(S, TemplateParams,
+                    S.Context.getAsIncompleteArrayType(Param)->getElementType(),
+                    IncompleteArrayArg->getElementType(),
+                    Info, Deduced, SubTDF);
+    }
+
+    //     T [integer-constant]
+    case Type::ConstantArray: {
+      const ConstantArrayType *ConstantArrayArg =
+        S.Context.getAsConstantArrayType(Arg);
+      if (!ConstantArrayArg)
+        return Sema::TDK_NonDeducedMismatch;
+
+      const ConstantArrayType *ConstantArrayParm =
+        S.Context.getAsConstantArrayType(Param);
+      if (ConstantArrayArg->getSize() != ConstantArrayParm->getSize())
+        return Sema::TDK_NonDeducedMismatch;
+
+      unsigned SubTDF = TDF & TDF_IgnoreQualifiers;
+      return DeduceTemplateArgumentsByTypeMatch(S, TemplateParams,
+                                           ConstantArrayParm->getElementType(),
+                                           ConstantArrayArg->getElementType(),
+                                           Info, Deduced, SubTDF);
+    }
+
+    //     type [i]
+    case Type::DependentSizedArray: {
+      const ArrayType *ArrayArg = S.Context.getAsArrayType(Arg);
+      if (!ArrayArg)
+        return Sema::TDK_NonDeducedMismatch;
+
+      unsigned SubTDF = TDF & TDF_IgnoreQualifiers;
+
+      // Check the element type of the arrays
+      const DependentSizedArrayType *DependentArrayParm
+        = S.Context.getAsDependentSizedArrayType(Param);
+      if (Sema::TemplateDeductionResult Result
+            = DeduceTemplateArgumentsByTypeMatch(S, TemplateParams,
+                                          DependentArrayParm->getElementType(),
+                                          ArrayArg->getElementType(),
+                                          Info, Deduced, SubTDF))
+        return Result;
+
+      // Determine the array bound is something we can deduce.
+      NonTypeTemplateParmDecl *NTTP
+        = getDeducedParameterFromExpr(DependentArrayParm->getSizeExpr());
+      if (!NTTP)
+        return Sema::TDK_Success;
+
+      // We can perform template argument deduction for the given non-type
+      // template parameter.
+      assert(NTTP->getDepth() == 0 &&
+             "Cannot deduce non-type template argument at depth > 0");
+      if (const ConstantArrayType *ConstantArrayArg
+            = dyn_cast<ConstantArrayType>(ArrayArg)) {
+        llvm::APSInt Size(ConstantArrayArg->getSize());
+        return DeduceNonTypeTemplateArgument(S, NTTP, Size,
+                                             S.Context.getSizeType(),
+                                             /*ArrayBound=*/true,
+                                             Info, Deduced);
+      }
+      if (const DependentSizedArrayType *DependentArrayArg
+            = dyn_cast<DependentSizedArrayType>(ArrayArg))
+        if (DependentArrayArg->getSizeExpr())
+          return DeduceNonTypeTemplateArgument(S, NTTP,
+                                               DependentArrayArg->getSizeExpr(),
+                                               Info, Deduced);
+
+      // Incomplete type does not match a dependently-sized array type
+      return Sema::TDK_NonDeducedMismatch;
+    }
+
+    //     type(*)(T)
+    //     T(*)()
+    //     T(*)(T)
+    case Type::FunctionProto: {
+      unsigned SubTDF = TDF & TDF_TopLevelParameterTypeList;
+      const FunctionProtoType *FunctionProtoArg =
+        dyn_cast<FunctionProtoType>(Arg);
+      if (!FunctionProtoArg)
+        return Sema::TDK_NonDeducedMismatch;
+
+      const FunctionProtoType *FunctionProtoParam =
+        cast<FunctionProtoType>(Param);
+
+      if (FunctionProtoParam->getTypeQuals()
+            != FunctionProtoArg->getTypeQuals() ||
+          FunctionProtoParam->getRefQualifier()
+            != FunctionProtoArg->getRefQualifier() ||
+          FunctionProtoParam->isVariadic() != FunctionProtoArg->isVariadic())
+        return Sema::TDK_NonDeducedMismatch;
+
+      // Check return types.
+      if (Sema::TemplateDeductionResult Result
+            = DeduceTemplateArgumentsByTypeMatch(S, TemplateParams,
+                                            FunctionProtoParam->getResultType(),
+                                            FunctionProtoArg->getResultType(),
+                                            Info, Deduced, 0))
+        return Result;
+
+      return DeduceTemplateArguments(S, TemplateParams,
+                                     FunctionProtoParam->arg_type_begin(),
+                                     FunctionProtoParam->getNumArgs(),
+                                     FunctionProtoArg->arg_type_begin(),
+                                     FunctionProtoArg->getNumArgs(),
+                                     Info, Deduced, SubTDF);
+    }
+
+    case Type::InjectedClassName: {
+      // Treat a template's injected-class-name as if the template
+      // specialization type had been used.
+      Param = cast<InjectedClassNameType>(Param)
+        ->getInjectedSpecializationType();
+      assert(isa<TemplateSpecializationType>(Param) &&
+             "injected class name is not a template specialization type");
+      // fall through
+    }
+
+    //     template-name<T> (where template-name refers to a class template)
+    //     template-name<i>
+    //     TT<T>
+    //     TT<i>
+    //     TT<>
+    case Type::TemplateSpecialization: {
+      const TemplateSpecializationType *SpecParam
+        = cast<TemplateSpecializationType>(Param);
+
+      // Try to deduce template arguments from the template-id.
+      Sema::TemplateDeductionResult Result
+        = DeduceTemplateArguments(S, TemplateParams, SpecParam, Arg,
+                                  Info, Deduced);
+
+      if (Result && (TDF & TDF_DerivedClass)) {
+        // C++ [temp.deduct.call]p3b3:
+        //   If P is a class, and P has the form template-id, then A can be a
+        //   derived class of the deduced A. Likewise, if P is a pointer to a
+        //   class of the form template-id, A can be a pointer to a derived
+        //   class pointed to by the deduced A.
+        //
+        // More importantly:
+        //   These alternatives are considered only if type deduction would
+        //   otherwise fail.
+        if (const RecordType *RecordT = Arg->getAs<RecordType>()) {
+          // We cannot inspect base classes as part of deduction when the type
+          // is incomplete, so either instantiate any templates necessary to
+          // complete the type, or skip over it if it cannot be completed.
+          if (S.RequireCompleteType(Info.getLocation(), Arg, 0))
+            return Result;
+
+          // Use data recursion to crawl through the list of base classes.
+          // Visited contains the set of nodes we have already visited, while
+          // ToVisit is our stack of records that we still need to visit.
+          llvm::SmallPtrSet<const RecordType *, 8> Visited;
+          SmallVector<const RecordType *, 8> ToVisit;
+          ToVisit.push_back(RecordT);
+          bool Successful = false;
+          SmallVector<DeducedTemplateArgument, 8> DeducedOrig(Deduced.begin(),
+                                                              Deduced.end());
+          while (!ToVisit.empty()) {
+            // Retrieve the next class in the inheritance hierarchy.
+            const RecordType *NextT = ToVisit.back();
+            ToVisit.pop_back();
+
+            // If we have already seen this type, skip it.
+            if (!Visited.insert(NextT))
+              continue;
+
+            // If this is a base class, try to perform template argument
+            // deduction from it.
+            if (NextT != RecordT) {
+              Sema::TemplateDeductionResult BaseResult
+                = DeduceTemplateArguments(S, TemplateParams, SpecParam,
+                                          QualType(NextT, 0), Info, Deduced);
+
+              // If template argument deduction for this base was successful,
+              // note that we had some success. Otherwise, ignore any deductions
+              // from this base class.
+              if (BaseResult == Sema::TDK_Success) {
+                Successful = true;
+                DeducedOrig.clear();
+                DeducedOrig.append(Deduced.begin(), Deduced.end());
+              }
+              else
+                Deduced = DeducedOrig;
+            }
+
+            // Visit base classes
+            CXXRecordDecl *Next = cast<CXXRecordDecl>(NextT->getDecl());
+            for (CXXRecordDecl::base_class_iterator Base = Next->bases_begin(),
+                                                 BaseEnd = Next->bases_end();
+                 Base != BaseEnd; ++Base) {
+              assert(Base->getType()->isRecordType() &&
+                     "Base class that isn't a record?");
+              ToVisit.push_back(Base->getType()->getAs<RecordType>());
+            }
+          }
+
+          if (Successful)
+            return Sema::TDK_Success;
+        }
+
+      }
+
+      return Result;
+    }
+
+    //     T type::*
+    //     T T::*
+    //     T (type::*)()
+    //     type (T::*)()
+    //     type (type::*)(T)
+    //     type (T::*)(T)
+    //     T (type::*)(T)
+    //     T (T::*)()
+    //     T (T::*)(T)
+    case Type::MemberPointer: {
+      const MemberPointerType *MemPtrParam = cast<MemberPointerType>(Param);
+      const MemberPointerType *MemPtrArg = dyn_cast<MemberPointerType>(Arg);
+      if (!MemPtrArg)
+        return Sema::TDK_NonDeducedMismatch;
+
+      if (Sema::TemplateDeductionResult Result
+            = DeduceTemplateArgumentsByTypeMatch(S, TemplateParams,
+                                                 MemPtrParam->getPointeeType(),
+                                                 MemPtrArg->getPointeeType(),
+                                                 Info, Deduced,
+                                                 TDF & TDF_IgnoreQualifiers))
+        return Result;
+
+      return DeduceTemplateArgumentsByTypeMatch(S, TemplateParams,
+                                           QualType(MemPtrParam->getClass(), 0),
+                                           QualType(MemPtrArg->getClass(), 0),
+                                           Info, Deduced, 
+                                           TDF & TDF_IgnoreQualifiers);
+    }
+
+    //     (clang extension)
+    //
+    //     type(^)(T)
+    //     T(^)()
+    //     T(^)(T)
+    case Type::BlockPointer: {
+      const BlockPointerType *BlockPtrParam = cast<BlockPointerType>(Param);
+      const BlockPointerType *BlockPtrArg = dyn_cast<BlockPointerType>(Arg);
+
+      if (!BlockPtrArg)
+        return Sema::TDK_NonDeducedMismatch;
+
+      return DeduceTemplateArgumentsByTypeMatch(S, TemplateParams,
+                                                BlockPtrParam->getPointeeType(),
+                                                BlockPtrArg->getPointeeType(),
+                                                Info, Deduced, 0);
+    }
+
+    //     (clang extension)
+    //
+    //     T __attribute__(((ext_vector_type(<integral constant>))))
+    case Type::ExtVector: {
+      const ExtVectorType *VectorParam = cast<ExtVectorType>(Param);
+      if (const ExtVectorType *VectorArg = dyn_cast<ExtVectorType>(Arg)) {
+        // Make sure that the vectors have the same number of elements.
+        if (VectorParam->getNumElements() != VectorArg->getNumElements())
+          return Sema::TDK_NonDeducedMismatch;
+        
+        // Perform deduction on the element types.
+        return DeduceTemplateArgumentsByTypeMatch(S, TemplateParams,
+                                                  VectorParam->getElementType(),
+                                                  VectorArg->getElementType(),
+                                                  Info, Deduced, TDF);
+      }
+      
+      if (const DependentSizedExtVectorType *VectorArg 
+                                = dyn_cast<DependentSizedExtVectorType>(Arg)) {
+        // We can't check the number of elements, since the argument has a
+        // dependent number of elements. This can only occur during partial
+        // ordering.
+
+        // Perform deduction on the element types.
+        return DeduceTemplateArgumentsByTypeMatch(S, TemplateParams,
+                                                  VectorParam->getElementType(),
+                                                  VectorArg->getElementType(),
+                                                  Info, Deduced, TDF);
+      }
+      
+      return Sema::TDK_NonDeducedMismatch;
+    }
+      
+    //     (clang extension)
+    //
+    //     T __attribute__(((ext_vector_type(N))))
+    case Type::DependentSizedExtVector: {
+      const DependentSizedExtVectorType *VectorParam
+        = cast<DependentSizedExtVectorType>(Param);
+
+      if (const ExtVectorType *VectorArg = dyn_cast<ExtVectorType>(Arg)) {
+        // Perform deduction on the element types.
+        if (Sema::TemplateDeductionResult Result
+              = DeduceTemplateArgumentsByTypeMatch(S, TemplateParams,
+                                                  VectorParam->getElementType(),
+                                                   VectorArg->getElementType(),
+                                                   Info, Deduced, TDF))
+          return Result;
+        
+        // Perform deduction on the vector size, if we can.
+        NonTypeTemplateParmDecl *NTTP
+          = getDeducedParameterFromExpr(VectorParam->getSizeExpr());
+        if (!NTTP)
+          return Sema::TDK_Success;
+
+        llvm::APSInt ArgSize(S.Context.getTypeSize(S.Context.IntTy), false);
+        ArgSize = VectorArg->getNumElements();
+        return DeduceNonTypeTemplateArgument(S, NTTP, ArgSize, S.Context.IntTy,
+                                             false, Info, Deduced);
+      }
+      
+      if (const DependentSizedExtVectorType *VectorArg 
+                                = dyn_cast<DependentSizedExtVectorType>(Arg)) {
+        // Perform deduction on the element types.
+        if (Sema::TemplateDeductionResult Result
+            = DeduceTemplateArgumentsByTypeMatch(S, TemplateParams,
+                                                 VectorParam->getElementType(),
+                                                 VectorArg->getElementType(),
+                                                 Info, Deduced, TDF))
+          return Result;
+        
+        // Perform deduction on the vector size, if we can.
+        NonTypeTemplateParmDecl *NTTP
+          = getDeducedParameterFromExpr(VectorParam->getSizeExpr());
+        if (!NTTP)
+          return Sema::TDK_Success;
+        
+        return DeduceNonTypeTemplateArgument(S, NTTP, VectorArg->getSizeExpr(),
+                                             Info, Deduced);
+      }
+      
+      return Sema::TDK_NonDeducedMismatch;
+    }
+      
+    case Type::TypeOfExpr:
+    case Type::TypeOf:
+    case Type::DependentName:
+    case Type::UnresolvedUsing:
+    case Type::Decltype:
+    case Type::UnaryTransform:
+    case Type::Auto:
+    case Type::DependentTemplateSpecialization:
+    case Type::PackExpansion:
+      // No template argument deduction for these types
+      return Sema::TDK_Success;
+  }
+
+  llvm_unreachable("Invalid Type Class!");
+}
+
+static Sema::TemplateDeductionResult
+DeduceTemplateArguments(Sema &S,
+                        TemplateParameterList *TemplateParams,
+                        const TemplateArgument &Param,
+                        TemplateArgument Arg,
+                        TemplateDeductionInfo &Info,
+                    SmallVectorImpl<DeducedTemplateArgument> &Deduced) {
+  // If the template argument is a pack expansion, perform template argument
+  // deduction against the pattern of that expansion. This only occurs during
+  // partial ordering.
+  if (Arg.isPackExpansion())
+    Arg = Arg.getPackExpansionPattern();
+
+  switch (Param.getKind()) {
+  case TemplateArgument::Null:
+    llvm_unreachable("Null template argument in parameter list");
+
+  case TemplateArgument::Type:
+    if (Arg.getKind() == TemplateArgument::Type)
+      return DeduceTemplateArgumentsByTypeMatch(S, TemplateParams,
+                                                Param.getAsType(),
+                                                Arg.getAsType(),
+                                                Info, Deduced, 0);
+    Info.FirstArg = Param;
+    Info.SecondArg = Arg;
+    return Sema::TDK_NonDeducedMismatch;
+
+  case TemplateArgument::Template:
+    if (Arg.getKind() == TemplateArgument::Template)
+      return DeduceTemplateArguments(S, TemplateParams,
+                                     Param.getAsTemplate(),
+                                     Arg.getAsTemplate(), Info, Deduced);
+    Info.FirstArg = Param;
+    Info.SecondArg = Arg;
+    return Sema::TDK_NonDeducedMismatch;
+
+  case TemplateArgument::TemplateExpansion:
+    llvm_unreachable("caller should handle pack expansions");
+
+  case TemplateArgument::Declaration:
+    if (Arg.getKind() == TemplateArgument::Declaration &&
+        isSameDeclaration(Param.getAsDecl(), Arg.getAsDecl()))
+      return Sema::TDK_Success;
+
+    Info.FirstArg = Param;
+    Info.SecondArg = Arg;
+    return Sema::TDK_NonDeducedMismatch;
+
+  case TemplateArgument::Integral:
+    if (Arg.getKind() == TemplateArgument::Integral) {
+      if (hasSameExtendedValue(*Param.getAsIntegral(), *Arg.getAsIntegral()))
+        return Sema::TDK_Success;
+
+      Info.FirstArg = Param;
+      Info.SecondArg = Arg;
+      return Sema::TDK_NonDeducedMismatch;
+    }
+
+    if (Arg.getKind() == TemplateArgument::Expression) {
+      Info.FirstArg = Param;
+      Info.SecondArg = Arg;
+      return Sema::TDK_NonDeducedMismatch;
+    }
+
+    Info.FirstArg = Param;
+    Info.SecondArg = Arg;
+    return Sema::TDK_NonDeducedMismatch;
+
+  case TemplateArgument::Expression: {
+    if (NonTypeTemplateParmDecl *NTTP
+          = getDeducedParameterFromExpr(Param.getAsExpr())) {
+      if (Arg.getKind() == TemplateArgument::Integral)
+        return DeduceNonTypeTemplateArgument(S, NTTP,
+                                             *Arg.getAsIntegral(),
+                                             Arg.getIntegralType(),
+                                             /*ArrayBound=*/false,
+                                             Info, Deduced);
+      if (Arg.getKind() == TemplateArgument::Expression)
+        return DeduceNonTypeTemplateArgument(S, NTTP, Arg.getAsExpr(),
+                                             Info, Deduced);
+      if (Arg.getKind() == TemplateArgument::Declaration)
+        return DeduceNonTypeTemplateArgument(S, NTTP, Arg.getAsDecl(),
+                                             Info, Deduced);
+
+      Info.FirstArg = Param;
+      Info.SecondArg = Arg;
+      return Sema::TDK_NonDeducedMismatch;
+    }
+
+    // Can't deduce anything, but that's okay.
+    return Sema::TDK_Success;
+  }
+  case TemplateArgument::Pack:
+    llvm_unreachable("Argument packs should be expanded by the caller!");
+  }
+
+  llvm_unreachable("Invalid TemplateArgument Kind!");
+}
+
+/// \brief Determine whether there is a template argument to be used for
+/// deduction.
+///
+/// This routine "expands" argument packs in-place, overriding its input
+/// parameters so that \c Args[ArgIdx] will be the available template argument.
+///
+/// \returns true if there is another template argument (which will be at
+/// \c Args[ArgIdx]), false otherwise.
+static bool hasTemplateArgumentForDeduction(const TemplateArgument *&Args,
+                                            unsigned &ArgIdx,
+                                            unsigned &NumArgs) {
+  if (ArgIdx == NumArgs)
+    return false;
+
+  const TemplateArgument &Arg = Args[ArgIdx];
+  if (Arg.getKind() != TemplateArgument::Pack)
+    return true;
+
+  assert(ArgIdx == NumArgs - 1 && "Pack not at the end of argument list?");
+  Args = Arg.pack_begin();
+  NumArgs = Arg.pack_size();
+  ArgIdx = 0;
+  return ArgIdx < NumArgs;
+}
+
+/// \brief Determine whether the given set of template arguments has a pack
+/// expansion that is not the last template argument.
+static bool hasPackExpansionBeforeEnd(const TemplateArgument *Args,
+                                      unsigned NumArgs) {
+  unsigned ArgIdx = 0;
+  while (ArgIdx < NumArgs) {
+    const TemplateArgument &Arg = Args[ArgIdx];
+
+    // Unwrap argument packs.
+    if (Args[ArgIdx].getKind() == TemplateArgument::Pack) {
+      Args = Arg.pack_begin();
+      NumArgs = Arg.pack_size();
+      ArgIdx = 0;
+      continue;
+    }
+
+    ++ArgIdx;
+    if (ArgIdx == NumArgs)
+      return false;
+
+    if (Arg.isPackExpansion())
+      return true;
+  }
+
+  return false;
+}
+
+static Sema::TemplateDeductionResult
+DeduceTemplateArguments(Sema &S,
+                        TemplateParameterList *TemplateParams,
+                        const TemplateArgument *Params, unsigned NumParams,
+                        const TemplateArgument *Args, unsigned NumArgs,
+                        TemplateDeductionInfo &Info,
+                    SmallVectorImpl<DeducedTemplateArgument> &Deduced,
+                        bool NumberOfArgumentsMustMatch) {
+  // C++0x [temp.deduct.type]p9:
+  //   If the template argument list of P contains a pack expansion that is not
+  //   the last template argument, the entire template argument list is a
+  //   non-deduced context.
+  if (hasPackExpansionBeforeEnd(Params, NumParams))
+    return Sema::TDK_Success;
+
+  // C++0x [temp.deduct.type]p9:
+  //   If P has a form that contains <T> or <i>, then each argument Pi of the
+  //   respective template argument list P is compared with the corresponding
+  //   argument Ai of the corresponding template argument list of A.
+  unsigned ArgIdx = 0, ParamIdx = 0;
+  for (; hasTemplateArgumentForDeduction(Params, ParamIdx, NumParams);
+       ++ParamIdx) {
+    if (!Params[ParamIdx].isPackExpansion()) {
+      // The simple case: deduce template arguments by matching Pi and Ai.
+
+      // Check whether we have enough arguments.
+      if (!hasTemplateArgumentForDeduction(Args, ArgIdx, NumArgs))
+        return NumberOfArgumentsMustMatch? Sema::TDK_NonDeducedMismatch
+                                         : Sema::TDK_Success;
+
+      if (Args[ArgIdx].isPackExpansion()) {
+        // FIXME: We follow the logic of C++0x [temp.deduct.type]p22 here,
+        // but applied to pack expansions that are template arguments.
+        return Sema::TDK_NonDeducedMismatch;
+      }
+
+      // Perform deduction for this Pi/Ai pair.
+      if (Sema::TemplateDeductionResult Result
+            = DeduceTemplateArguments(S, TemplateParams,
+                                      Params[ParamIdx], Args[ArgIdx],
+                                      Info, Deduced))
+        return Result;
+
+      // Move to the next argument.
+      ++ArgIdx;
+      continue;
+    }
+
+    // The parameter is a pack expansion.
+
+    // C++0x [temp.deduct.type]p9:
+    //   If Pi is a pack expansion, then the pattern of Pi is compared with
+    //   each remaining argument in the template argument list of A. Each
+    //   comparison deduces template arguments for subsequent positions in the
+    //   template parameter packs expanded by Pi.
+    TemplateArgument Pattern = Params[ParamIdx].getPackExpansionPattern();
+
+    // Compute the set of template parameter indices that correspond to
+    // parameter packs expanded by the pack expansion.
+    SmallVector<unsigned, 2> PackIndices;
+    {
+      llvm::SmallBitVector SawIndices(TemplateParams->size());
+      SmallVector<UnexpandedParameterPack, 2> Unexpanded;
+      S.collectUnexpandedParameterPacks(Pattern, Unexpanded);
+      for (unsigned I = 0, N = Unexpanded.size(); I != N; ++I) {
+        unsigned Depth, Index;
+        llvm::tie(Depth, Index) = getDepthAndIndex(Unexpanded[I]);
+        if (Depth == 0 && !SawIndices[Index]) {
+          SawIndices[Index] = true;
+          PackIndices.push_back(Index);
+        }
+      }
+    }
+    assert(!PackIndices.empty() && "Pack expansion without unexpanded packs?");
+
+    // FIXME: If there are no remaining arguments, we can bail out early
+    // and set any deduced parameter packs to an empty argument pack.
+    // The latter part of this is a (minor) correctness issue.
+
+    // Save the deduced template arguments for each parameter pack expanded
+    // by this pack expansion, then clear out the deduction.
+    SmallVector<DeducedTemplateArgument, 2>
+      SavedPacks(PackIndices.size());
+    SmallVector<SmallVector<DeducedTemplateArgument, 4>, 2>
+      NewlyDeducedPacks(PackIndices.size());
+    PrepareArgumentPackDeduction(S, Deduced, PackIndices, SavedPacks,
+                                 NewlyDeducedPacks);
+
+    // Keep track of the deduced template arguments for each parameter pack
+    // expanded by this pack expansion (the outer index) and for each
+    // template argument (the inner SmallVectors).
+    bool HasAnyArguments = false;
+    while (hasTemplateArgumentForDeduction(Args, ArgIdx, NumArgs)) {
+      HasAnyArguments = true;
+
+      // Deduce template arguments from the pattern.
+      if (Sema::TemplateDeductionResult Result
+            = DeduceTemplateArguments(S, TemplateParams, Pattern, Args[ArgIdx],
+                                      Info, Deduced))
+        return Result;
+
+      // Capture the deduced template arguments for each parameter pack expanded
+      // by this pack expansion, add them to the list of arguments we've deduced
+      // for that pack, then clear out the deduced argument.
+      for (unsigned I = 0, N = PackIndices.size(); I != N; ++I) {
+        DeducedTemplateArgument &DeducedArg = Deduced[PackIndices[I]];
+        if (!DeducedArg.isNull()) {
+          NewlyDeducedPacks[I].push_back(DeducedArg);
+          DeducedArg = DeducedTemplateArgument();
+        }
+      }
+
+      ++ArgIdx;
+    }
+
+    // Build argument packs for each of the parameter packs expanded by this
+    // pack expansion.
+    if (Sema::TemplateDeductionResult Result
+          = FinishArgumentPackDeduction(S, TemplateParams, HasAnyArguments,
+                                        Deduced, PackIndices, SavedPacks,
+                                        NewlyDeducedPacks, Info))
+      return Result;
+  }
+
+  // If there is an argument remaining, then we had too many arguments.
+  if (NumberOfArgumentsMustMatch &&
+      hasTemplateArgumentForDeduction(Args, ArgIdx, NumArgs))
+    return Sema::TDK_NonDeducedMismatch;
+
+  return Sema::TDK_Success;
+}
+
+static Sema::TemplateDeductionResult
+DeduceTemplateArguments(Sema &S,
+                        TemplateParameterList *TemplateParams,
+                        const TemplateArgumentList &ParamList,
+                        const TemplateArgumentList &ArgList,
+                        TemplateDeductionInfo &Info,
+                    SmallVectorImpl<DeducedTemplateArgument> &Deduced) {
+  return DeduceTemplateArguments(S, TemplateParams,
+                                 ParamList.data(), ParamList.size(),
+                                 ArgList.data(), ArgList.size(),
+                                 Info, Deduced);
+}
+
+/// \brief Determine whether two template arguments are the same.
+static bool isSameTemplateArg(ASTContext &Context,
+                              const TemplateArgument &X,
+                              const TemplateArgument &Y) {
+  if (X.getKind() != Y.getKind())
+    return false;
+
+  switch (X.getKind()) {
+    case TemplateArgument::Null:
+      llvm_unreachable("Comparing NULL template argument");
+
+    case TemplateArgument::Type:
+      return Context.getCanonicalType(X.getAsType()) ==
+             Context.getCanonicalType(Y.getAsType());
+
+    case TemplateArgument::Declaration:
+      return isSameDeclaration(X.getAsDecl(), Y.getAsDecl());
+
+    case TemplateArgument::Template:
+    case TemplateArgument::TemplateExpansion:
+      return Context.getCanonicalTemplateName(
+                    X.getAsTemplateOrTemplatePattern()).getAsVoidPointer() ==
+             Context.getCanonicalTemplateName(
+                    Y.getAsTemplateOrTemplatePattern()).getAsVoidPointer();
+
+    case TemplateArgument::Integral:
+      return *X.getAsIntegral() == *Y.getAsIntegral();
+
+    case TemplateArgument::Expression: {
+      llvm::FoldingSetNodeID XID, YID;
+      X.getAsExpr()->Profile(XID, Context, true);
+      Y.getAsExpr()->Profile(YID, Context, true);
+      return XID == YID;
+    }
+
+    case TemplateArgument::Pack:
+      if (X.pack_size() != Y.pack_size())
+        return false;
+
+      for (TemplateArgument::pack_iterator XP = X.pack_begin(),
+                                        XPEnd = X.pack_end(),
+                                           YP = Y.pack_begin();
+           XP != XPEnd; ++XP, ++YP)
+        if (!isSameTemplateArg(Context, *XP, *YP))
+          return false;
+
+      return true;
+  }
+
+  llvm_unreachable("Invalid TemplateArgument Kind!");
+}
+
+/// \brief Allocate a TemplateArgumentLoc where all locations have
+/// been initialized to the given location.
+///
+/// \param S The semantic analysis object.
+///
+/// \param The template argument we are producing template argument
+/// location information for.
+///
+/// \param NTTPType For a declaration template argument, the type of
+/// the non-type template parameter that corresponds to this template
+/// argument.
+///
+/// \param Loc The source location to use for the resulting template
+/// argument.
+static TemplateArgumentLoc
+getTrivialTemplateArgumentLoc(Sema &S,
+                              const TemplateArgument &Arg,
+                              QualType NTTPType,
+                              SourceLocation Loc) {
+  switch (Arg.getKind()) {
+  case TemplateArgument::Null:
+    llvm_unreachable("Can't get a NULL template argument here");
+
+  case TemplateArgument::Type:
+    return TemplateArgumentLoc(Arg,
+                     S.Context.getTrivialTypeSourceInfo(Arg.getAsType(), Loc));
+
+  case TemplateArgument::Declaration: {
+    Expr *E
+      = S.BuildExpressionFromDeclTemplateArgument(Arg, NTTPType, Loc)
+          .takeAs<Expr>();
+    return TemplateArgumentLoc(TemplateArgument(E), E);
+  }
+
+  case TemplateArgument::Integral: {
+    Expr *E
+      = S.BuildExpressionFromIntegralTemplateArgument(Arg, Loc).takeAs<Expr>();
+    return TemplateArgumentLoc(TemplateArgument(E), E);
+  }
+
+    case TemplateArgument::Template:
+    case TemplateArgument::TemplateExpansion: {
+      NestedNameSpecifierLocBuilder Builder;
+      TemplateName Template = Arg.getAsTemplate();
+      if (DependentTemplateName *DTN = Template.getAsDependentTemplateName())
+        Builder.MakeTrivial(S.Context, DTN->getQualifier(), Loc);
+      else if (QualifiedTemplateName *QTN = Template.getAsQualifiedTemplateName())
+        Builder.MakeTrivial(S.Context, QTN->getQualifier(), Loc);
+      
+      if (Arg.getKind() == TemplateArgument::Template)
+        return TemplateArgumentLoc(Arg, 
+                                   Builder.getWithLocInContext(S.Context),
+                                   Loc);
+      
+      
+      return TemplateArgumentLoc(Arg, Builder.getWithLocInContext(S.Context),
+                                 Loc, Loc);
+    }
+
+  case TemplateArgument::Expression:
+    return TemplateArgumentLoc(Arg, Arg.getAsExpr());
+
+  case TemplateArgument::Pack:
+    return TemplateArgumentLoc(Arg, TemplateArgumentLocInfo());
+  }
+
+  llvm_unreachable("Invalid TemplateArgument Kind!");
+}
+
+
+/// \brief Convert the given deduced template argument and add it to the set of
+/// fully-converted template arguments.
+static bool ConvertDeducedTemplateArgument(Sema &S, NamedDecl *Param,
+                                           DeducedTemplateArgument Arg,
+                                           NamedDecl *Template,
+                                           QualType NTTPType,
+                                           unsigned ArgumentPackIndex,
+                                           TemplateDeductionInfo &Info,
+                                           bool InFunctionTemplate,
+                             SmallVectorImpl<TemplateArgument> &Output) {
+  if (Arg.getKind() == TemplateArgument::Pack) {
+    // This is a template argument pack, so check each of its arguments against
+    // the template parameter.
+    SmallVector<TemplateArgument, 2> PackedArgsBuilder;
+    for (TemplateArgument::pack_iterator PA = Arg.pack_begin(),
+                                      PAEnd = Arg.pack_end();
+         PA != PAEnd; ++PA) {
+      // When converting the deduced template argument, append it to the
+      // general output list. We need to do this so that the template argument
+      // checking logic has all of the prior template arguments available.
+      DeducedTemplateArgument InnerArg(*PA);
+      InnerArg.setDeducedFromArrayBound(Arg.wasDeducedFromArrayBound());
+      if (ConvertDeducedTemplateArgument(S, Param, InnerArg, Template,
+                                         NTTPType, PackedArgsBuilder.size(),
+                                         Info, InFunctionTemplate, Output))
+        return true;
+
+      // Move the converted template argument into our argument pack.
+      PackedArgsBuilder.push_back(Output.back());
+      Output.pop_back();
+    }
+
+    // Create the resulting argument pack.
+    Output.push_back(TemplateArgument::CreatePackCopy(S.Context,
+                                                      PackedArgsBuilder.data(),
+                                                     PackedArgsBuilder.size()));
+    return false;
+  }
+
+  // Convert the deduced template argument into a template
+  // argument that we can check, almost as if the user had written
+  // the template argument explicitly.
+  TemplateArgumentLoc ArgLoc = getTrivialTemplateArgumentLoc(S, Arg, NTTPType,
+                                                             Info.getLocation());
+
+  // Check the template argument, converting it as necessary.
+  return S.CheckTemplateArgument(Param, ArgLoc,
+                                 Template,
+                                 Template->getLocation(),
+                                 Template->getSourceRange().getEnd(),
+                                 ArgumentPackIndex,
+                                 Output,
+                                 InFunctionTemplate
+                                  ? (Arg.wasDeducedFromArrayBound()
+                                       ? Sema::CTAK_DeducedFromArrayBound
+                                       : Sema::CTAK_Deduced)
+                                 : Sema::CTAK_Specified);
+}
+
+/// Complete template argument deduction for a class template partial
+/// specialization.
+static Sema::TemplateDeductionResult
+FinishTemplateArgumentDeduction(Sema &S,
+                                ClassTemplatePartialSpecializationDecl *Partial,
+                                const TemplateArgumentList &TemplateArgs,
+                      SmallVectorImpl<DeducedTemplateArgument> &Deduced,
+                                TemplateDeductionInfo &Info) {
+  // Unevaluated SFINAE context.
+  EnterExpressionEvaluationContext Unevaluated(S, Sema::Unevaluated);
+  Sema::SFINAETrap Trap(S);
+
+  Sema::ContextRAII SavedContext(S, Partial);
+
+  // C++ [temp.deduct.type]p2:
+  //   [...] or if any template argument remains neither deduced nor
+  //   explicitly specified, template argument deduction fails.
+  SmallVector<TemplateArgument, 4> Builder;
+  TemplateParameterList *PartialParams = Partial->getTemplateParameters();
+  for (unsigned I = 0, N = PartialParams->size(); I != N; ++I) {
+    NamedDecl *Param = PartialParams->getParam(I);
+    if (Deduced[I].isNull()) {
+      Info.Param = makeTemplateParameter(Param);
+      return Sema::TDK_Incomplete;
+    }
+
+    // We have deduced this argument, so it still needs to be
+    // checked and converted.
+
+    // First, for a non-type template parameter type that is
+    // initialized by a declaration, we need the type of the
+    // corresponding non-type template parameter.
+    QualType NTTPType;
+    if (NonTypeTemplateParmDecl *NTTP
+                                  = dyn_cast<NonTypeTemplateParmDecl>(Param)) {
+      NTTPType = NTTP->getType();
+      if (NTTPType->isDependentType()) {
+        TemplateArgumentList TemplateArgs(TemplateArgumentList::OnStack,
+                                          Builder.data(), Builder.size());
+        NTTPType = S.SubstType(NTTPType,
+                               MultiLevelTemplateArgumentList(TemplateArgs),
+                               NTTP->getLocation(),
+                               NTTP->getDeclName());
+        if (NTTPType.isNull()) {
+          Info.Param = makeTemplateParameter(Param);
+          // FIXME: These template arguments are temporary. Free them!
+          Info.reset(TemplateArgumentList::CreateCopy(S.Context,
+                                                      Builder.data(),
+                                                      Builder.size()));
+          return Sema::TDK_SubstitutionFailure;
+        }
+      }
+    }
+
+    if (ConvertDeducedTemplateArgument(S, Param, Deduced[I],
+                                       Partial, NTTPType, 0, Info, false,
+                                       Builder)) {
+      Info.Param = makeTemplateParameter(Param);
+      // FIXME: These template arguments are temporary. Free them!
+      Info.reset(TemplateArgumentList::CreateCopy(S.Context, Builder.data(),
+                                                  Builder.size()));
+      return Sema::TDK_SubstitutionFailure;
+    }
+  }
+
+  // Form the template argument list from the deduced template arguments.
+  TemplateArgumentList *DeducedArgumentList
+    = TemplateArgumentList::CreateCopy(S.Context, Builder.data(),
+                                       Builder.size());
+
+  Info.reset(DeducedArgumentList);
+
+  // Substitute the deduced template arguments into the template
+  // arguments of the class template partial specialization, and
+  // verify that the instantiated template arguments are both valid
+  // and are equivalent to the template arguments originally provided
+  // to the class template.
+  LocalInstantiationScope InstScope(S);
+  ClassTemplateDecl *ClassTemplate = Partial->getSpecializedTemplate();
+  const TemplateArgumentLoc *PartialTemplateArgs
+    = Partial->getTemplateArgsAsWritten();
+
+  // Note that we don't provide the langle and rangle locations.
+  TemplateArgumentListInfo InstArgs;
+
+  if (S.Subst(PartialTemplateArgs,
+              Partial->getNumTemplateArgsAsWritten(),
+              InstArgs, MultiLevelTemplateArgumentList(*DeducedArgumentList))) {
+    unsigned ArgIdx = InstArgs.size(), ParamIdx = ArgIdx;
+    if (ParamIdx >= Partial->getTemplateParameters()->size())
+      ParamIdx = Partial->getTemplateParameters()->size() - 1;
+
+    Decl *Param
+      = const_cast<NamedDecl *>(
+                          Partial->getTemplateParameters()->getParam(ParamIdx));
+    Info.Param = makeTemplateParameter(Param);
+    Info.FirstArg = PartialTemplateArgs[ArgIdx].getArgument();
+    return Sema::TDK_SubstitutionFailure;
+  }
+
+  SmallVector<TemplateArgument, 4> ConvertedInstArgs;
+  if (S.CheckTemplateArgumentList(ClassTemplate, Partial->getLocation(),
+                                  InstArgs, false, ConvertedInstArgs))
+    return Sema::TDK_SubstitutionFailure;
+
+  TemplateParameterList *TemplateParams
+    = ClassTemplate->getTemplateParameters();
+  for (unsigned I = 0, E = TemplateParams->size(); I != E; ++I) {
+    TemplateArgument InstArg = ConvertedInstArgs.data()[I];
+    if (!isSameTemplateArg(S.Context, TemplateArgs[I], InstArg)) {
+      Info.Param = makeTemplateParameter(TemplateParams->getParam(I));
+      Info.FirstArg = TemplateArgs[I];
+      Info.SecondArg = InstArg;
+      return Sema::TDK_NonDeducedMismatch;
+    }
+  }
+
+  if (Trap.hasErrorOccurred())
+    return Sema::TDK_SubstitutionFailure;
+
+  return Sema::TDK_Success;
+}
+
+/// \brief Perform template argument deduction to determine whether
+/// the given template arguments match the given class template
+/// partial specialization per C++ [temp.class.spec.match].
+Sema::TemplateDeductionResult
+Sema::DeduceTemplateArguments(ClassTemplatePartialSpecializationDecl *Partial,
+                              const TemplateArgumentList &TemplateArgs,
+                              TemplateDeductionInfo &Info) {
+  // C++ [temp.class.spec.match]p2:
+  //   A partial specialization matches a given actual template
+  //   argument list if the template arguments of the partial
+  //   specialization can be deduced from the actual template argument
+  //   list (14.8.2).
+
+  // Unevaluated SFINAE context.
+  EnterExpressionEvaluationContext Unevaluated(*this, Sema::Unevaluated);
+  SFINAETrap Trap(*this);
+
+  SmallVector<DeducedTemplateArgument, 4> Deduced;
+  Deduced.resize(Partial->getTemplateParameters()->size());
+  if (TemplateDeductionResult Result
+        = ::DeduceTemplateArguments(*this,
+                                    Partial->getTemplateParameters(),
+                                    Partial->getTemplateArgs(),
+                                    TemplateArgs, Info, Deduced))
+    return Result;
+
+  InstantiatingTemplate Inst(*this, Partial->getLocation(), Partial,
+                             Deduced.data(), Deduced.size(), Info);
+  if (Inst)
+    return TDK_InstantiationDepth;
+
+  if (Trap.hasErrorOccurred())
+    return Sema::TDK_SubstitutionFailure;
+
+  return ::FinishTemplateArgumentDeduction(*this, Partial, TemplateArgs,
+                                           Deduced, Info);
+}
+
+/// \brief Determine whether the given type T is a simple-template-id type.
+static bool isSimpleTemplateIdType(QualType T) {
+  if (const TemplateSpecializationType *Spec
+        = T->getAs<TemplateSpecializationType>())
+    return Spec->getTemplateName().getAsTemplateDecl() != 0;
+
+  return false;
+}
+
+/// \brief Substitute the explicitly-provided template arguments into the
+/// given function template according to C++ [temp.arg.explicit].
+///
+/// \param FunctionTemplate the function template into which the explicit
+/// template arguments will be substituted.
+///
+/// \param ExplicitTemplateArguments the explicitly-specified template
+/// arguments.
+///
+/// \param Deduced the deduced template arguments, which will be populated
+/// with the converted and checked explicit template arguments.
+///
+/// \param ParamTypes will be populated with the instantiated function
+/// parameters.
+///
+/// \param FunctionType if non-NULL, the result type of the function template
+/// will also be instantiated and the pointed-to value will be updated with
+/// the instantiated function type.
+///
+/// \param Info if substitution fails for any reason, this object will be
+/// populated with more information about the failure.
+///
+/// \returns TDK_Success if substitution was successful, or some failure
+/// condition.
+Sema::TemplateDeductionResult
+Sema::SubstituteExplicitTemplateArguments(
+                                      FunctionTemplateDecl *FunctionTemplate,
+                               TemplateArgumentListInfo &ExplicitTemplateArgs,
+                       SmallVectorImpl<DeducedTemplateArgument> &Deduced,
+                                 SmallVectorImpl<QualType> &ParamTypes,
+                                          QualType *FunctionType,
+                                          TemplateDeductionInfo &Info) {
+  FunctionDecl *Function = FunctionTemplate->getTemplatedDecl();
+  TemplateParameterList *TemplateParams
+    = FunctionTemplate->getTemplateParameters();
+
+  if (ExplicitTemplateArgs.size() == 0) {
+    // No arguments to substitute; just copy over the parameter types and
+    // fill in the function type.
+    for (FunctionDecl::param_iterator P = Function->param_begin(),
+                                   PEnd = Function->param_end();
+         P != PEnd;
+         ++P)
+      ParamTypes.push_back((*P)->getType());
+
+    if (FunctionType)
+      *FunctionType = Function->getType();
+    return TDK_Success;
+  }
+
+  // Unevaluated SFINAE context.
+  EnterExpressionEvaluationContext Unevaluated(*this, Sema::Unevaluated);
+  SFINAETrap Trap(*this);
+
+  // C++ [temp.arg.explicit]p3:
+  //   Template arguments that are present shall be specified in the
+  //   declaration order of their corresponding template-parameters. The
+  //   template argument list shall not specify more template-arguments than
+  //   there are corresponding template-parameters.
+  SmallVector<TemplateArgument, 4> Builder;
+
+  // Enter a new template instantiation context where we check the
+  // explicitly-specified template arguments against this function template,
+  // and then substitute them into the function parameter types.
+  InstantiatingTemplate Inst(*this, FunctionTemplate->getLocation(),
+                             FunctionTemplate, Deduced.data(), Deduced.size(),
+           ActiveTemplateInstantiation::ExplicitTemplateArgumentSubstitution,
+                             Info);
+  if (Inst)
+    return TDK_InstantiationDepth;
+
+  if (CheckTemplateArgumentList(FunctionTemplate,
+                                SourceLocation(),
+                                ExplicitTemplateArgs,
+                                true,
+                                Builder) || Trap.hasErrorOccurred()) {
+    unsigned Index = Builder.size();
+    if (Index >= TemplateParams->size())
+      Index = TemplateParams->size() - 1;
+    Info.Param = makeTemplateParameter(TemplateParams->getParam(Index));
+    return TDK_InvalidExplicitArguments;
+  }
+
+  // Form the template argument list from the explicitly-specified
+  // template arguments.
+  TemplateArgumentList *ExplicitArgumentList
+    = TemplateArgumentList::CreateCopy(Context, Builder.data(), Builder.size());
+  Info.reset(ExplicitArgumentList);
+
+  // Template argument deduction and the final substitution should be
+  // done in the context of the templated declaration.  Explicit
+  // argument substitution, on the other hand, needs to happen in the
+  // calling context.
+  ContextRAII SavedContext(*this, FunctionTemplate->getTemplatedDecl());
+
+  // If we deduced template arguments for a template parameter pack,
+  // note that the template argument pack is partially substituted and record
+  // the explicit template arguments. They'll be used as part of deduction
+  // for this template parameter pack.
+  for (unsigned I = 0, N = Builder.size(); I != N; ++I) {
+    const TemplateArgument &Arg = Builder[I];
+    if (Arg.getKind() == TemplateArgument::Pack) {
+      CurrentInstantiationScope->SetPartiallySubstitutedPack(
+                                                 TemplateParams->getParam(I),
+                                                             Arg.pack_begin(),
+                                                             Arg.pack_size());
+      break;
+    }
+  }
+
+  const FunctionProtoType *Proto
+    = Function->getType()->getAs<FunctionProtoType>();
+  assert(Proto && "Function template does not have a prototype?");
+
+  // Instantiate the types of each of the function parameters given the
+  // explicitly-specified template arguments. If the function has a trailing
+  // return type, substitute it after the arguments to ensure we substitute
+  // in lexical order.
+  if (Proto->hasTrailingReturn()) {
+    if (SubstParmTypes(Function->getLocation(),
+                       Function->param_begin(), Function->getNumParams(),
+                       MultiLevelTemplateArgumentList(*ExplicitArgumentList),
+                       ParamTypes))
+      return TDK_SubstitutionFailure;
+  }
+  
+  // Instantiate the return type.
+  // FIXME: exception-specifications?
+  QualType ResultType;
+  {
+    // C++11 [expr.prim.general]p3:
+    //   If a declaration declares a member function or member function 
+    //   template of a class X, the expression this is a prvalue of type 
+    //   "pointer to cv-qualifier-seq X" between the optional cv-qualifer-seq
+    //   and the end of the function-definition, member-declarator, or 
+    //   declarator.
+    unsigned ThisTypeQuals = 0;
+    CXXRecordDecl *ThisContext = 0;
+    if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(Function)) {
+      ThisContext = Method->getParent();
+      ThisTypeQuals = Method->getTypeQualifiers();
+    }
+      
+    CXXThisScopeRAII ThisScope(*this, ThisContext, ThisTypeQuals,
+                               getLangOpts().CPlusPlus0x);
+    
+    ResultType = SubstType(Proto->getResultType(),
+                   MultiLevelTemplateArgumentList(*ExplicitArgumentList),
+                   Function->getTypeSpecStartLoc(),
+                   Function->getDeclName());
+    if (ResultType.isNull() || Trap.hasErrorOccurred())
+      return TDK_SubstitutionFailure;
+  }
+  
+  // Instantiate the types of each of the function parameters given the
+  // explicitly-specified template arguments if we didn't do so earlier.
+  if (!Proto->hasTrailingReturn() &&
+      SubstParmTypes(Function->getLocation(),
+                     Function->param_begin(), Function->getNumParams(),
+                     MultiLevelTemplateArgumentList(*ExplicitArgumentList),
+                     ParamTypes))
+    return TDK_SubstitutionFailure;
+
+  if (FunctionType) {
+    *FunctionType = BuildFunctionType(ResultType,
+                                      ParamTypes.data(), ParamTypes.size(),
+                                      Proto->isVariadic(),
+                                      Proto->hasTrailingReturn(),
+                                      Proto->getTypeQuals(),
+                                      Proto->getRefQualifier(),
+                                      Function->getLocation(),
+                                      Function->getDeclName(),
+                                      Proto->getExtInfo());
+    if (FunctionType->isNull() || Trap.hasErrorOccurred())
+      return TDK_SubstitutionFailure;
+  }
+
+  // C++ [temp.arg.explicit]p2:
+  //   Trailing template arguments that can be deduced (14.8.2) may be
+  //   omitted from the list of explicit template-arguments. If all of the
+  //   template arguments can be deduced, they may all be omitted; in this
+  //   case, the empty template argument list <> itself may also be omitted.
+  //
+  // Take all of the explicitly-specified arguments and put them into
+  // the set of deduced template arguments. Explicitly-specified
+  // parameter packs, however, will be set to NULL since the deduction
+  // mechanisms handle explicitly-specified argument packs directly.
+  Deduced.reserve(TemplateParams->size());
+  for (unsigned I = 0, N = ExplicitArgumentList->size(); I != N; ++I) {
+    const TemplateArgument &Arg = ExplicitArgumentList->get(I);
+    if (Arg.getKind() == TemplateArgument::Pack)
+      Deduced.push_back(DeducedTemplateArgument());
+    else
+      Deduced.push_back(Arg);
+  }
+
+  return TDK_Success;
+}
+
+/// \brief Check whether the deduced argument type for a call to a function
+/// template matches the actual argument type per C++ [temp.deduct.call]p4.
+static bool 
+CheckOriginalCallArgDeduction(Sema &S, Sema::OriginalCallArg OriginalArg, 
+                              QualType DeducedA) {
+  ASTContext &Context = S.Context;
+  
+  QualType A = OriginalArg.OriginalArgType;
+  QualType OriginalParamType = OriginalArg.OriginalParamType;
+  
+  // Check for type equality (top-level cv-qualifiers are ignored).
+  if (Context.hasSameUnqualifiedType(A, DeducedA))
+    return false;
+  
+  // Strip off references on the argument types; they aren't needed for
+  // the following checks.
+  if (const ReferenceType *DeducedARef = DeducedA->getAs<ReferenceType>())
+    DeducedA = DeducedARef->getPointeeType();
+  if (const ReferenceType *ARef = A->getAs<ReferenceType>())
+    A = ARef->getPointeeType();
+  
+  // C++ [temp.deduct.call]p4:
+  //   [...] However, there are three cases that allow a difference:
+  //     - If the original P is a reference type, the deduced A (i.e., the 
+  //       type referred to by the reference) can be more cv-qualified than 
+  //       the transformed A.
+  if (const ReferenceType *OriginalParamRef
+      = OriginalParamType->getAs<ReferenceType>()) {
+    // We don't want to keep the reference around any more.
+    OriginalParamType = OriginalParamRef->getPointeeType();
+    
+    Qualifiers AQuals = A.getQualifiers();
+    Qualifiers DeducedAQuals = DeducedA.getQualifiers();
+    if (AQuals == DeducedAQuals) {
+      // Qualifiers match; there's nothing to do.
+    } else if (!DeducedAQuals.compatiblyIncludes(AQuals)) {
+      return true;
+    } else {        
+      // Qualifiers are compatible, so have the argument type adopt the
+      // deduced argument type's qualifiers as if we had performed the
+      // qualification conversion.
+      A = Context.getQualifiedType(A.getUnqualifiedType(), DeducedAQuals);
+    }
+  }
+  
+  //    - The transformed A can be another pointer or pointer to member 
+  //      type that can be converted to the deduced A via a qualification 
+  //      conversion.
+  //
+  // Also allow conversions which merely strip [[noreturn]] from function types
+  // (recursively) as an extension.
+  // FIXME: Currently, this doesn't place nicely with qualfication conversions.
+  bool ObjCLifetimeConversion = false;
+  QualType ResultTy;
+  if ((A->isAnyPointerType() || A->isMemberPointerType()) &&
+      (S.IsQualificationConversion(A, DeducedA, false,
+                                   ObjCLifetimeConversion) ||
+       S.IsNoReturnConversion(A, DeducedA, ResultTy)))
+    return false;
+  
+  
+  //    - If P is a class and P has the form simple-template-id, then the 
+  //      transformed A can be a derived class of the deduced A. [...]
+  //     [...] Likewise, if P is a pointer to a class of the form 
+  //      simple-template-id, the transformed A can be a pointer to a 
+  //      derived class pointed to by the deduced A.
+  if (const PointerType *OriginalParamPtr
+      = OriginalParamType->getAs<PointerType>()) {
+    if (const PointerType *DeducedAPtr = DeducedA->getAs<PointerType>()) {
+      if (const PointerType *APtr = A->getAs<PointerType>()) {
+        if (A->getPointeeType()->isRecordType()) {
+          OriginalParamType = OriginalParamPtr->getPointeeType();
+          DeducedA = DeducedAPtr->getPointeeType();
+          A = APtr->getPointeeType();
+        }
+      }
+    }
+  }
+  
+  if (Context.hasSameUnqualifiedType(A, DeducedA))
+    return false;
+  
+  if (A->isRecordType() && isSimpleTemplateIdType(OriginalParamType) &&
+      S.IsDerivedFrom(A, DeducedA))
+    return false;
+  
+  return true;
+}
+
+/// \brief Finish template argument deduction for a function template,
+/// checking the deduced template arguments for completeness and forming
+/// the function template specialization.
+///
+/// \param OriginalCallArgs If non-NULL, the original call arguments against
+/// which the deduced argument types should be compared.
+Sema::TemplateDeductionResult
+Sema::FinishTemplateArgumentDeduction(FunctionTemplateDecl *FunctionTemplate,
+                       SmallVectorImpl<DeducedTemplateArgument> &Deduced,
+                                      unsigned NumExplicitlySpecified,
+                                      FunctionDecl *&Specialization,
+                                      TemplateDeductionInfo &Info,
+        SmallVectorImpl<OriginalCallArg> const *OriginalCallArgs) {
+  TemplateParameterList *TemplateParams
+    = FunctionTemplate->getTemplateParameters();
+
+  // Unevaluated SFINAE context.
+  EnterExpressionEvaluationContext Unevaluated(*this, Sema::Unevaluated);
+  SFINAETrap Trap(*this);
+
+  // Enter a new template instantiation context while we instantiate the
+  // actual function declaration.
+  InstantiatingTemplate Inst(*this, FunctionTemplate->getLocation(),
+                             FunctionTemplate, Deduced.data(), Deduced.size(),
+              ActiveTemplateInstantiation::DeducedTemplateArgumentSubstitution,
+                             Info);
+  if (Inst)
+    return TDK_InstantiationDepth;
+
+  ContextRAII SavedContext(*this, FunctionTemplate->getTemplatedDecl());
+
+  // C++ [temp.deduct.type]p2:
+  //   [...] or if any template argument remains neither deduced nor
+  //   explicitly specified, template argument deduction fails.
+  SmallVector<TemplateArgument, 4> Builder;
+  for (unsigned I = 0, N = TemplateParams->size(); I != N; ++I) {
+    NamedDecl *Param = TemplateParams->getParam(I);
+
+    if (!Deduced[I].isNull()) {
+      if (I < NumExplicitlySpecified) {
+        // We have already fully type-checked and converted this
+        // argument, because it was explicitly-specified. Just record the
+        // presence of this argument.
+        Builder.push_back(Deduced[I]);
+        continue;
+      }
+
+      // We have deduced this argument, so it still needs to be
+      // checked and converted.
+
+      // First, for a non-type template parameter type that is
+      // initialized by a declaration, we need the type of the
+      // corresponding non-type template parameter.
+      QualType NTTPType;
+      if (NonTypeTemplateParmDecl *NTTP
+                                = dyn_cast<NonTypeTemplateParmDecl>(Param)) {
+        NTTPType = NTTP->getType();
+        if (NTTPType->isDependentType()) {
+          TemplateArgumentList TemplateArgs(TemplateArgumentList::OnStack,
+                                            Builder.data(), Builder.size());
+          NTTPType = SubstType(NTTPType,
+                               MultiLevelTemplateArgumentList(TemplateArgs),
+                               NTTP->getLocation(),
+                               NTTP->getDeclName());
+          if (NTTPType.isNull()) {
+            Info.Param = makeTemplateParameter(Param);
+            // FIXME: These template arguments are temporary. Free them!
+            Info.reset(TemplateArgumentList::CreateCopy(Context,
+                                                        Builder.data(),
+                                                        Builder.size()));
+            return TDK_SubstitutionFailure;
+          }
+        }
+      }
+
+      if (ConvertDeducedTemplateArgument(*this, Param, Deduced[I],
+                                         FunctionTemplate, NTTPType, 0, Info,
+                                         true, Builder)) {
+        Info.Param = makeTemplateParameter(Param);
+        // FIXME: These template arguments are temporary. Free them!
+        Info.reset(TemplateArgumentList::CreateCopy(Context, Builder.data(),
+                                                    Builder.size()));
+        return TDK_SubstitutionFailure;
+      }
+
+      continue;
+    }
+
+    // C++0x [temp.arg.explicit]p3:
+    //    A trailing template parameter pack (14.5.3) not otherwise deduced will
+    //    be deduced to an empty sequence of template arguments.
+    // FIXME: Where did the word "trailing" come from?
+    if (Param->isTemplateParameterPack()) {
+      // We may have had explicitly-specified template arguments for this
+      // template parameter pack. If so, our empty deduction extends the
+      // explicitly-specified set (C++0x [temp.arg.explicit]p9).
+      const TemplateArgument *ExplicitArgs;
+      unsigned NumExplicitArgs;
+      if (CurrentInstantiationScope->getPartiallySubstitutedPack(&ExplicitArgs,
+                                                             &NumExplicitArgs)
+          == Param)
+        Builder.push_back(TemplateArgument(ExplicitArgs, NumExplicitArgs));
+      else
+        Builder.push_back(TemplateArgument(0, 0));
+
+      continue;
+    }
+
+    // Substitute into the default template argument, if available.
+    TemplateArgumentLoc DefArg
+      = SubstDefaultTemplateArgumentIfAvailable(FunctionTemplate,
+                                              FunctionTemplate->getLocation(),
+                                  FunctionTemplate->getSourceRange().getEnd(),
+                                                Param,
+                                                Builder);
+
+    // If there was no default argument, deduction is incomplete.
+    if (DefArg.getArgument().isNull()) {
+      Info.Param = makeTemplateParameter(
+                         const_cast<NamedDecl *>(TemplateParams->getParam(I)));
+      return TDK_Incomplete;
+    }
+
+    // Check whether we can actually use the default argument.
+    if (CheckTemplateArgument(Param, DefArg,
+                              FunctionTemplate,
+                              FunctionTemplate->getLocation(),
+                              FunctionTemplate->getSourceRange().getEnd(),
+                              0, Builder,
+                              CTAK_Specified)) {
+      Info.Param = makeTemplateParameter(
+                         const_cast<NamedDecl *>(TemplateParams->getParam(I)));
+      // FIXME: These template arguments are temporary. Free them!
+      Info.reset(TemplateArgumentList::CreateCopy(Context, Builder.data(),
+                                                  Builder.size()));
+      return TDK_SubstitutionFailure;
+    }
+
+    // If we get here, we successfully used the default template argument.
+  }
+
+  // Form the template argument list from the deduced template arguments.
+  TemplateArgumentList *DeducedArgumentList
+    = TemplateArgumentList::CreateCopy(Context, Builder.data(), Builder.size());
+  Info.reset(DeducedArgumentList);
+
+  // Substitute the deduced template arguments into the function template
+  // declaration to produce the function template specialization.
+  DeclContext *Owner = FunctionTemplate->getDeclContext();
+  if (FunctionTemplate->getFriendObjectKind())
+    Owner = FunctionTemplate->getLexicalDeclContext();
+  Specialization = cast_or_null<FunctionDecl>(
+                      SubstDecl(FunctionTemplate->getTemplatedDecl(), Owner,
+                         MultiLevelTemplateArgumentList(*DeducedArgumentList)));
+  if (!Specialization || Specialization->isInvalidDecl())
+    return TDK_SubstitutionFailure;
+
+  assert(Specialization->getPrimaryTemplate()->getCanonicalDecl() ==
+         FunctionTemplate->getCanonicalDecl());
+
+  // If the template argument list is owned by the function template
+  // specialization, release it.
+  if (Specialization->getTemplateSpecializationArgs() == DeducedArgumentList &&
+      !Trap.hasErrorOccurred())
+    Info.take();
+
+  // There may have been an error that did not prevent us from constructing a
+  // declaration. Mark the declaration invalid and return with a substitution
+  // failure.
+  if (Trap.hasErrorOccurred()) {
+    Specialization->setInvalidDecl(true);
+    return TDK_SubstitutionFailure;
+  }
+
+  if (OriginalCallArgs) {
+    // C++ [temp.deduct.call]p4:
+    //   In general, the deduction process attempts to find template argument
+    //   values that will make the deduced A identical to A (after the type A 
+    //   is transformed as described above). [...]
+    for (unsigned I = 0, N = OriginalCallArgs->size(); I != N; ++I) {
+      OriginalCallArg OriginalArg = (*OriginalCallArgs)[I];
+      unsigned ParamIdx = OriginalArg.ArgIdx;
+      
+      if (ParamIdx >= Specialization->getNumParams())
+        continue;
+      
+      QualType DeducedA = Specialization->getParamDecl(ParamIdx)->getType();
+      if (CheckOriginalCallArgDeduction(*this, OriginalArg, DeducedA))
+        return Sema::TDK_SubstitutionFailure;
+    }
+  }
+  
+  // If we suppressed any diagnostics while performing template argument
+  // deduction, and if we haven't already instantiated this declaration,
+  // keep track of these diagnostics. They'll be emitted if this specialization
+  // is actually used.
+  if (Info.diag_begin() != Info.diag_end()) {
+    llvm::DenseMap<Decl *, SmallVector<PartialDiagnosticAt, 1> >::iterator
+      Pos = SuppressedDiagnostics.find(Specialization->getCanonicalDecl());
+    if (Pos == SuppressedDiagnostics.end())
+        SuppressedDiagnostics[Specialization->getCanonicalDecl()]
+          .append(Info.diag_begin(), Info.diag_end());
+  }
+
+  return TDK_Success;
+}
+
+/// Gets the type of a function for template-argument-deducton
+/// purposes when it's considered as part of an overload set.
+static QualType GetTypeOfFunction(ASTContext &Context,
+                                  const OverloadExpr::FindResult &R,
+                                  FunctionDecl *Fn) {
+  if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(Fn))
+    if (Method->isInstance()) {
+      // An instance method that's referenced in a form that doesn't
+      // look like a member pointer is just invalid.
+      if (!R.HasFormOfMemberPointer) return QualType();
+
+      return Context.getMemberPointerType(Fn->getType(),
+               Context.getTypeDeclType(Method->getParent()).getTypePtr());
+    }
+
+  if (!R.IsAddressOfOperand) return Fn->getType();
+  return Context.getPointerType(Fn->getType());
+}
+
+/// Apply the deduction rules for overload sets.
+///
+/// \return the null type if this argument should be treated as an
+/// undeduced context
+static QualType
+ResolveOverloadForDeduction(Sema &S, TemplateParameterList *TemplateParams,
+                            Expr *Arg, QualType ParamType,
+                            bool ParamWasReference) {
+
+  OverloadExpr::FindResult R = OverloadExpr::find(Arg);
+
+  OverloadExpr *Ovl = R.Expression;
+
+  // C++0x [temp.deduct.call]p4
+  unsigned TDF = 0;
+  if (ParamWasReference)
+    TDF |= TDF_ParamWithReferenceType;
+  if (R.IsAddressOfOperand)
+    TDF |= TDF_IgnoreQualifiers;
+
+  // C++0x [temp.deduct.call]p6:
+  //   When P is a function type, pointer to function type, or pointer
+  //   to member function type:
+
+  if (!ParamType->isFunctionType() &&
+      !ParamType->isFunctionPointerType() &&
+      !ParamType->isMemberFunctionPointerType()) {
+    if (Ovl->hasExplicitTemplateArgs()) {
+      // But we can still look for an explicit specialization.
+      if (FunctionDecl *ExplicitSpec
+            = S.ResolveSingleFunctionTemplateSpecialization(Ovl))
+        return GetTypeOfFunction(S.Context, R, ExplicitSpec);
+    }
+
+    return QualType();
+  }
+  
+  // Gather the explicit template arguments, if any.
+  TemplateArgumentListInfo ExplicitTemplateArgs;
+  if (Ovl->hasExplicitTemplateArgs())
+    Ovl->getExplicitTemplateArgs().copyInto(ExplicitTemplateArgs);
+  QualType Match;
+  for (UnresolvedSetIterator I = Ovl->decls_begin(),
+         E = Ovl->decls_end(); I != E; ++I) {
+    NamedDecl *D = (*I)->getUnderlyingDecl();
+
+    if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(D)) {
+      //   - If the argument is an overload set containing one or more
+      //     function templates, the parameter is treated as a
+      //     non-deduced context.
+      if (!Ovl->hasExplicitTemplateArgs())
+        return QualType();
+      
+      // Otherwise, see if we can resolve a function type 
+      FunctionDecl *Specialization = 0;
+      TemplateDeductionInfo Info(S.Context, Ovl->getNameLoc());
+      if (S.DeduceTemplateArguments(FunTmpl, &ExplicitTemplateArgs,
+                                    Specialization, Info))
+        continue;
+      
+      D = Specialization;
+    }
+
+    FunctionDecl *Fn = cast<FunctionDecl>(D);
+    QualType ArgType = GetTypeOfFunction(S.Context, R, Fn);
+    if (ArgType.isNull()) continue;
+
+    // Function-to-pointer conversion.
+    if (!ParamWasReference && ParamType->isPointerType() &&
+        ArgType->isFunctionType())
+      ArgType = S.Context.getPointerType(ArgType);
+
+    //   - If the argument is an overload set (not containing function
+    //     templates), trial argument deduction is attempted using each
+    //     of the members of the set. If deduction succeeds for only one
+    //     of the overload set members, that member is used as the
+    //     argument value for the deduction. If deduction succeeds for
+    //     more than one member of the overload set the parameter is
+    //     treated as a non-deduced context.
+
+    // We do all of this in a fresh context per C++0x [temp.deduct.type]p2:
+    //   Type deduction is done independently for each P/A pair, and
+    //   the deduced template argument values are then combined.
+    // So we do not reject deductions which were made elsewhere.
+    SmallVector<DeducedTemplateArgument, 8>
+      Deduced(TemplateParams->size());
+    TemplateDeductionInfo Info(S.Context, Ovl->getNameLoc());
+    Sema::TemplateDeductionResult Result
+      = DeduceTemplateArgumentsByTypeMatch(S, TemplateParams, ParamType,
+                                           ArgType, Info, Deduced, TDF);
+    if (Result) continue;
+    if (!Match.isNull()) return QualType();
+    Match = ArgType;
+  }
+
+  return Match;
+}
+
+/// \brief Perform the adjustments to the parameter and argument types
+/// described in C++ [temp.deduct.call].
+///
+/// \returns true if the caller should not attempt to perform any template
+/// argument deduction based on this P/A pair.
+static bool AdjustFunctionParmAndArgTypesForDeduction(Sema &S,
+                                          TemplateParameterList *TemplateParams,
+                                                      QualType &ParamType,
+                                                      QualType &ArgType,
+                                                      Expr *Arg,
+                                                      unsigned &TDF) {
+  // C++0x [temp.deduct.call]p3:
+  //   If P is a cv-qualified type, the top level cv-qualifiers of P's type
+  //   are ignored for type deduction.
+  if (ParamType.hasQualifiers())
+    ParamType = ParamType.getUnqualifiedType();
+  const ReferenceType *ParamRefType = ParamType->getAs<ReferenceType>();
+  if (ParamRefType) {
+    QualType PointeeType = ParamRefType->getPointeeType();
+
+    // If the argument has incomplete array type, try to complete it's type.
+    if (ArgType->isIncompleteArrayType() &&
+        !S.RequireCompleteExprType(Arg, S.PDiag(), 
+                                   std::make_pair(SourceLocation(), S.PDiag())))
+      ArgType = Arg->getType();
+
+    //   [C++0x] If P is an rvalue reference to a cv-unqualified
+    //   template parameter and the argument is an lvalue, the type
+    //   "lvalue reference to A" is used in place of A for type
+    //   deduction.
+    if (isa<RValueReferenceType>(ParamType)) {
+      if (!PointeeType.getQualifiers() &&
+          isa<TemplateTypeParmType>(PointeeType) &&
+          Arg->Classify(S.Context).isLValue() &&
+          Arg->getType() != S.Context.OverloadTy &&
+          Arg->getType() != S.Context.BoundMemberTy)
+        ArgType = S.Context.getLValueReferenceType(ArgType);
+    }
+
+    //   [...] If P is a reference type, the type referred to by P is used
+    //   for type deduction.
+    ParamType = PointeeType;
+  }
+
+  // Overload sets usually make this parameter an undeduced
+  // context, but there are sometimes special circumstances.
+  if (ArgType == S.Context.OverloadTy) {
+    ArgType = ResolveOverloadForDeduction(S, TemplateParams,
+                                          Arg, ParamType,
+                                          ParamRefType != 0);
+    if (ArgType.isNull())
+      return true;
+  }
+
+  if (ParamRefType) {
+    // C++0x [temp.deduct.call]p3:
+    //   [...] If P is of the form T&&, where T is a template parameter, and
+    //   the argument is an lvalue, the type A& is used in place of A for
+    //   type deduction.
+    if (ParamRefType->isRValueReferenceType() &&
+        ParamRefType->getAs<TemplateTypeParmType>() &&
+        Arg->isLValue())
+      ArgType = S.Context.getLValueReferenceType(ArgType);
+  } else {
+    // C++ [temp.deduct.call]p2:
+    //   If P is not a reference type:
+    //   - If A is an array type, the pointer type produced by the
+    //     array-to-pointer standard conversion (4.2) is used in place of
+    //     A for type deduction; otherwise,
+    if (ArgType->isArrayType())
+      ArgType = S.Context.getArrayDecayedType(ArgType);
+    //   - If A is a function type, the pointer type produced by the
+    //     function-to-pointer standard conversion (4.3) is used in place
+    //     of A for type deduction; otherwise,
+    else if (ArgType->isFunctionType())
+      ArgType = S.Context.getPointerType(ArgType);
+    else {
+      // - If A is a cv-qualified type, the top level cv-qualifiers of A's
+      //   type are ignored for type deduction.
+      ArgType = ArgType.getUnqualifiedType();
+    }
+  }
+
+  // C++0x [temp.deduct.call]p4:
+  //   In general, the deduction process attempts to find template argument
+  //   values that will make the deduced A identical to A (after the type A
+  //   is transformed as described above). [...]
+  TDF = TDF_SkipNonDependent;
+
+  //     - If the original P is a reference type, the deduced A (i.e., the
+  //       type referred to by the reference) can be more cv-qualified than
+  //       the transformed A.
+  if (ParamRefType)
+    TDF |= TDF_ParamWithReferenceType;
+  //     - The transformed A can be another pointer or pointer to member
+  //       type that can be converted to the deduced A via a qualification
+  //       conversion (4.4).
+  if (ArgType->isPointerType() || ArgType->isMemberPointerType() ||
+      ArgType->isObjCObjectPointerType())
+    TDF |= TDF_IgnoreQualifiers;
+  //     - If P is a class and P has the form simple-template-id, then the
+  //       transformed A can be a derived class of the deduced A. Likewise,
+  //       if P is a pointer to a class of the form simple-template-id, the
+  //       transformed A can be a pointer to a derived class pointed to by
+  //       the deduced A.
+  if (isSimpleTemplateIdType(ParamType) ||
+      (isa<PointerType>(ParamType) &&
+       isSimpleTemplateIdType(
+                              ParamType->getAs<PointerType>()->getPointeeType())))
+    TDF |= TDF_DerivedClass;
+
+  return false;
+}
+
+static bool hasDeducibleTemplateParameters(Sema &S,
+                                           FunctionTemplateDecl *FunctionTemplate,
+                                           QualType T);
+
+/// \brief Perform template argument deduction by matching a parameter type
+///        against a single expression, where the expression is an element of
+///        an initializer list that was originally matched against the argument
+///        type.
+static Sema::TemplateDeductionResult
+DeduceTemplateArgumentByListElement(Sema &S,
+                                    TemplateParameterList *TemplateParams,
+                                    QualType ParamType, Expr *Arg,
+                                    TemplateDeductionInfo &Info,
+                              SmallVectorImpl<DeducedTemplateArgument> &Deduced,
+                                    unsigned TDF) {
+  // Handle the case where an init list contains another init list as the
+  // element.
+  if (InitListExpr *ILE = dyn_cast<InitListExpr>(Arg)) {
+    QualType X;
+    if (!S.isStdInitializerList(ParamType.getNonReferenceType(), &X))
+      return Sema::TDK_Success; // Just ignore this expression.
+
+    // Recurse down into the init list.
+    for (unsigned i = 0, e = ILE->getNumInits(); i < e; ++i) {
+      if (Sema::TemplateDeductionResult Result =
+            DeduceTemplateArgumentByListElement(S, TemplateParams, X,
+                                                 ILE->getInit(i),
+                                                 Info, Deduced, TDF))
+        return Result;
+    }
+    return Sema::TDK_Success;
+  }
+
+  // For all other cases, just match by type.
+  QualType ArgType = Arg->getType();
+  if (AdjustFunctionParmAndArgTypesForDeduction(S, TemplateParams, ParamType, 
+                                                ArgType, Arg, TDF))
+    return Sema::TDK_FailedOverloadResolution;
+  return DeduceTemplateArgumentsByTypeMatch(S, TemplateParams, ParamType,
+                                            ArgType, Info, Deduced, TDF);
+}
+
+/// \brief Perform template argument deduction from a function call
+/// (C++ [temp.deduct.call]).
+///
+/// \param FunctionTemplate the function template for which we are performing
+/// template argument deduction.
+///
+/// \param ExplicitTemplateArguments the explicit template arguments provided
+/// for this call.
+///
+/// \param Args the function call arguments
+///
+/// \param NumArgs the number of arguments in Args
+///
+/// \param Name the name of the function being called. This is only significant
+/// when the function template is a conversion function template, in which
+/// case this routine will also perform template argument deduction based on
+/// the function to which
+///
+/// \param Specialization if template argument deduction was successful,
+/// this will be set to the function template specialization produced by
+/// template argument deduction.
+///
+/// \param Info the argument will be updated to provide additional information
+/// about template argument deduction.
+///
+/// \returns the result of template argument deduction.
+Sema::TemplateDeductionResult
+Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
+                              TemplateArgumentListInfo *ExplicitTemplateArgs,
+                              llvm::ArrayRef<Expr *> Args,
+                              FunctionDecl *&Specialization,
+                              TemplateDeductionInfo &Info) {
+  FunctionDecl *Function = FunctionTemplate->getTemplatedDecl();
+
+  // C++ [temp.deduct.call]p1:
+  //   Template argument deduction is done by comparing each function template
+  //   parameter type (call it P) with the type of the corresponding argument
+  //   of the call (call it A) as described below.
+  unsigned CheckArgs = Args.size();
+  if (Args.size() < Function->getMinRequiredArguments())
+    return TDK_TooFewArguments;
+  else if (Args.size() > Function->getNumParams()) {
+    const FunctionProtoType *Proto
+      = Function->getType()->getAs<FunctionProtoType>();
+    if (Proto->isTemplateVariadic())
+      /* Do nothing */;
+    else if (Proto->isVariadic())
+      CheckArgs = Function->getNumParams();
+    else
+      return TDK_TooManyArguments;
+  }
+
+  // The types of the parameters from which we will perform template argument
+  // deduction.
+  LocalInstantiationScope InstScope(*this);
+  TemplateParameterList *TemplateParams
+    = FunctionTemplate->getTemplateParameters();
+  SmallVector<DeducedTemplateArgument, 4> Deduced;
+  SmallVector<QualType, 4> ParamTypes;
+  unsigned NumExplicitlySpecified = 0;
+  if (ExplicitTemplateArgs) {
+    TemplateDeductionResult Result =
+      SubstituteExplicitTemplateArguments(FunctionTemplate,
+                                          *ExplicitTemplateArgs,
+                                          Deduced,
+                                          ParamTypes,
+                                          0,
+                                          Info);
+    if (Result)
+      return Result;
+
+    NumExplicitlySpecified = Deduced.size();
+  } else {
+    // Just fill in the parameter types from the function declaration.
+    for (unsigned I = 0, N = Function->getNumParams(); I != N; ++I)
+      ParamTypes.push_back(Function->getParamDecl(I)->getType());
+  }
+
+  // Deduce template arguments from the function parameters.
+  Deduced.resize(TemplateParams->size());
+  unsigned ArgIdx = 0;
+  SmallVector<OriginalCallArg, 4> OriginalCallArgs;
+  for (unsigned ParamIdx = 0, NumParams = ParamTypes.size();
+       ParamIdx != NumParams; ++ParamIdx) {
+    QualType OrigParamType = ParamTypes[ParamIdx];
+    QualType ParamType = OrigParamType;
+    
+    const PackExpansionType *ParamExpansion
+      = dyn_cast<PackExpansionType>(ParamType);
+    if (!ParamExpansion) {
+      // Simple case: matching a function parameter to a function argument.
+      if (ArgIdx >= CheckArgs)
+        break;
+
+      Expr *Arg = Args[ArgIdx++];
+      QualType ArgType = Arg->getType();
+      
+      unsigned TDF = 0;
+      if (AdjustFunctionParmAndArgTypesForDeduction(*this, TemplateParams,
+                                                    ParamType, ArgType, Arg,
+                                                    TDF))
+        continue;
+
+      // If we have nothing to deduce, we're done.
+      if (!hasDeducibleTemplateParameters(*this, FunctionTemplate, ParamType))
+        continue;
+
+      // If the argument is an initializer list ...
+      if (InitListExpr *ILE = dyn_cast<InitListExpr>(Arg)) {
+        // ... then the parameter is an undeduced context, unless the parameter
+        // type is (reference to cv) std::initializer_list<P'>, in which case
+        // deduction is done for each element of the initializer list, and the
+        // result is the deduced type if it's the same for all elements.
+        QualType X;
+        // Removing references was already done.
+        if (!isStdInitializerList(ParamType, &X))
+          continue;
+
+        for (unsigned i = 0, e = ILE->getNumInits(); i < e; ++i) {
+          if (TemplateDeductionResult Result =
+                DeduceTemplateArgumentByListElement(*this, TemplateParams, X,
+                                                     ILE->getInit(i),
+                                                     Info, Deduced, TDF))
+            return Result;
+        }
+        // Don't track the argument type, since an initializer list has none.
+        continue;
+      }
+
+      // Keep track of the argument type and corresponding parameter index,
+      // so we can check for compatibility between the deduced A and A.
+      OriginalCallArgs.push_back(OriginalCallArg(OrigParamType, ArgIdx-1, 
+                                                 ArgType));
+
+      if (TemplateDeductionResult Result
+            = DeduceTemplateArgumentsByTypeMatch(*this, TemplateParams,
+                                                 ParamType, ArgType,
+                                                 Info, Deduced, TDF))
+        return Result;
+
+      continue;
+    }
+
+    // C++0x [temp.deduct.call]p1:
+    //   For a function parameter pack that occurs at the end of the
+    //   parameter-declaration-list, the type A of each remaining argument of
+    //   the call is compared with the type P of the declarator-id of the
+    //   function parameter pack. Each comparison deduces template arguments
+    //   for subsequent positions in the template parameter packs expanded by
+    //   the function parameter pack. For a function parameter pack that does
+    //   not occur at the end of the parameter-declaration-list, the type of
+    //   the parameter pack is a non-deduced context.
+    if (ParamIdx + 1 < NumParams)
+      break;
+
+    QualType ParamPattern = ParamExpansion->getPattern();
+    SmallVector<unsigned, 2> PackIndices;
+    {
+      llvm::SmallBitVector SawIndices(TemplateParams->size());
+      SmallVector<UnexpandedParameterPack, 2> Unexpanded;
+      collectUnexpandedParameterPacks(ParamPattern, Unexpanded);
+      for (unsigned I = 0, N = Unexpanded.size(); I != N; ++I) {
+        unsigned Depth, Index;
+        llvm::tie(Depth, Index) = getDepthAndIndex(Unexpanded[I]);
+        if (Depth == 0 && !SawIndices[Index]) {
+          SawIndices[Index] = true;
+          PackIndices.push_back(Index);
+        }
+      }
+    }
+    assert(!PackIndices.empty() && "Pack expansion without unexpanded packs?");
+
+    // Keep track of the deduced template arguments for each parameter pack
+    // expanded by this pack expansion (the outer index) and for each
+    // template argument (the inner SmallVectors).
+    SmallVector<SmallVector<DeducedTemplateArgument, 4>, 2>
+      NewlyDeducedPacks(PackIndices.size());
+    SmallVector<DeducedTemplateArgument, 2>
+      SavedPacks(PackIndices.size());
+    PrepareArgumentPackDeduction(*this, Deduced, PackIndices, SavedPacks,
+                                 NewlyDeducedPacks);
+    bool HasAnyArguments = false;
+    for (; ArgIdx < Args.size(); ++ArgIdx) {
+      HasAnyArguments = true;
+
+      QualType OrigParamType = ParamPattern;
+      ParamType = OrigParamType;
+      Expr *Arg = Args[ArgIdx];
+      QualType ArgType = Arg->getType();
+      
+      unsigned TDF = 0;
+      if (AdjustFunctionParmAndArgTypesForDeduction(*this, TemplateParams,
+                                                    ParamType, ArgType, Arg,
+                                                    TDF)) {
+        // We can't actually perform any deduction for this argument, so stop
+        // deduction at this point.
+        ++ArgIdx;
+        break;
+      }
+
+      // As above, initializer lists need special handling.
+      if (InitListExpr *ILE = dyn_cast<InitListExpr>(Arg)) {
+        QualType X;
+        if (!isStdInitializerList(ParamType, &X)) {
+          ++ArgIdx;
+          break;
+        }
+
+        for (unsigned i = 0, e = ILE->getNumInits(); i < e; ++i) {
+          if (TemplateDeductionResult Result =
+                DeduceTemplateArgumentsByTypeMatch(*this, TemplateParams, X,
+                                                   ILE->getInit(i)->getType(),
+                                                   Info, Deduced, TDF))
+            return Result;
+        }
+      } else {
+
+        // Keep track of the argument type and corresponding argument index,
+        // so we can check for compatibility between the deduced A and A.
+        if (hasDeducibleTemplateParameters(*this, FunctionTemplate, ParamType))
+          OriginalCallArgs.push_back(OriginalCallArg(OrigParamType, ArgIdx, 
+                                                     ArgType));
+
+        if (TemplateDeductionResult Result
+            = DeduceTemplateArgumentsByTypeMatch(*this, TemplateParams,
+                                                 ParamType, ArgType, Info,
+                                                 Deduced, TDF))
+          return Result;
+      }
+
+      // Capture the deduced template arguments for each parameter pack expanded
+      // by this pack expansion, add them to the list of arguments we've deduced
+      // for that pack, then clear out the deduced argument.
+      for (unsigned I = 0, N = PackIndices.size(); I != N; ++I) {
+        DeducedTemplateArgument &DeducedArg = Deduced[PackIndices[I]];
+        if (!DeducedArg.isNull()) {
+          NewlyDeducedPacks[I].push_back(DeducedArg);
+          DeducedArg = DeducedTemplateArgument();
+        }
+      }
+    }
+
+    // Build argument packs for each of the parameter packs expanded by this
+    // pack expansion.
+    if (Sema::TemplateDeductionResult Result
+          = FinishArgumentPackDeduction(*this, TemplateParams, HasAnyArguments,
+                                        Deduced, PackIndices, SavedPacks,
+                                        NewlyDeducedPacks, Info))
+      return Result;
+
+    // After we've matching against a parameter pack, we're done.
+    break;
+  }
+
+  return FinishTemplateArgumentDeduction(FunctionTemplate, Deduced,
+                                         NumExplicitlySpecified,
+                                         Specialization, Info, &OriginalCallArgs);
+}
+
+/// \brief Deduce template arguments when taking the address of a function
+/// template (C++ [temp.deduct.funcaddr]) or matching a specialization to
+/// a template.
+///
+/// \param FunctionTemplate the function template for which we are performing
+/// template argument deduction.
+///
+/// \param ExplicitTemplateArguments the explicitly-specified template
+/// arguments.
+///
+/// \param ArgFunctionType the function type that will be used as the
+/// "argument" type (A) when performing template argument deduction from the
+/// function template's function type. This type may be NULL, if there is no
+/// argument type to compare against, in C++0x [temp.arg.explicit]p3.
+///
+/// \param Specialization if template argument deduction was successful,
+/// this will be set to the function template specialization produced by
+/// template argument deduction.
+///
+/// \param Info the argument will be updated to provide additional information
+/// about template argument deduction.
+///
+/// \returns the result of template argument deduction.
+Sema::TemplateDeductionResult
+Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
+                              TemplateArgumentListInfo *ExplicitTemplateArgs,
+                              QualType ArgFunctionType,
+                              FunctionDecl *&Specialization,
+                              TemplateDeductionInfo &Info) {
+  FunctionDecl *Function = FunctionTemplate->getTemplatedDecl();
+  TemplateParameterList *TemplateParams
+    = FunctionTemplate->getTemplateParameters();
+  QualType FunctionType = Function->getType();
+
+  // Substitute any explicit template arguments.
+  LocalInstantiationScope InstScope(*this);
+  SmallVector<DeducedTemplateArgument, 4> Deduced;
+  unsigned NumExplicitlySpecified = 0;
+  SmallVector<QualType, 4> ParamTypes;
+  if (ExplicitTemplateArgs) {
+    if (TemplateDeductionResult Result
+          = SubstituteExplicitTemplateArguments(FunctionTemplate,
+                                                *ExplicitTemplateArgs,
+                                                Deduced, ParamTypes,
+                                                &FunctionType, Info))
+      return Result;
+
+    NumExplicitlySpecified = Deduced.size();
+  }
+
+  // Unevaluated SFINAE context.
+  EnterExpressionEvaluationContext Unevaluated(*this, Sema::Unevaluated);
+  SFINAETrap Trap(*this);
+
+  Deduced.resize(TemplateParams->size());
+
+  if (!ArgFunctionType.isNull()) {
+    // Deduce template arguments from the function type.
+    if (TemplateDeductionResult Result
+          = DeduceTemplateArgumentsByTypeMatch(*this, TemplateParams,
+                                      FunctionType, ArgFunctionType, Info,
+                                      Deduced, TDF_TopLevelParameterTypeList))
+      return Result;
+  }
+
+  if (TemplateDeductionResult Result
+        = FinishTemplateArgumentDeduction(FunctionTemplate, Deduced,
+                                          NumExplicitlySpecified,
+                                          Specialization, Info))
+    return Result;
+
+  // If the requested function type does not match the actual type of the
+  // specialization, template argument deduction fails.
+  if (!ArgFunctionType.isNull() &&
+      !Context.hasSameType(ArgFunctionType, Specialization->getType()))
+    return TDK_NonDeducedMismatch;
+
+  return TDK_Success;
+}
+
+/// \brief Deduce template arguments for a templated conversion
+/// function (C++ [temp.deduct.conv]) and, if successful, produce a
+/// conversion function template specialization.
+Sema::TemplateDeductionResult
+Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
+                              QualType ToType,
+                              CXXConversionDecl *&Specialization,
+                              TemplateDeductionInfo &Info) {
+  CXXConversionDecl *Conv
+    = cast<CXXConversionDecl>(FunctionTemplate->getTemplatedDecl());
+  QualType FromType = Conv->getConversionType();
+
+  // Canonicalize the types for deduction.
+  QualType P = Context.getCanonicalType(FromType);
+  QualType A = Context.getCanonicalType(ToType);
+
+  // C++0x [temp.deduct.conv]p2:
+  //   If P is a reference type, the type referred to by P is used for
+  //   type deduction.
+  if (const ReferenceType *PRef = P->getAs<ReferenceType>())
+    P = PRef->getPointeeType();
+
+  // C++0x [temp.deduct.conv]p4:
+  //   [...] If A is a reference type, the type referred to by A is used
+  //   for type deduction.
+  if (const ReferenceType *ARef = A->getAs<ReferenceType>())
+    A = ARef->getPointeeType().getUnqualifiedType();
+  // C++ [temp.deduct.conv]p3:
+  //
+  //   If A is not a reference type:
+  else {
+    assert(!A->isReferenceType() && "Reference types were handled above");
+
+    //   - If P is an array type, the pointer type produced by the
+    //     array-to-pointer standard conversion (4.2) is used in place
+    //     of P for type deduction; otherwise,
+    if (P->isArrayType())
+      P = Context.getArrayDecayedType(P);
+    //   - If P is a function type, the pointer type produced by the
+    //     function-to-pointer standard conversion (4.3) is used in
+    //     place of P for type deduction; otherwise,
+    else if (P->isFunctionType())
+      P = Context.getPointerType(P);
+    //   - If P is a cv-qualified type, the top level cv-qualifiers of
+    //     P's type are ignored for type deduction.
+    else
+      P = P.getUnqualifiedType();
+
+    // C++0x [temp.deduct.conv]p4:
+    //   If A is a cv-qualified type, the top level cv-qualifiers of A's
+    //   type are ignored for type deduction. If A is a reference type, the type 
+    //   referred to by A is used for type deduction.
+    A = A.getUnqualifiedType();
+  }
+
+  // Unevaluated SFINAE context.
+  EnterExpressionEvaluationContext Unevaluated(*this, Sema::Unevaluated);
+  SFINAETrap Trap(*this);
+
+  // C++ [temp.deduct.conv]p1:
+  //   Template argument deduction is done by comparing the return
+  //   type of the template conversion function (call it P) with the
+  //   type that is required as the result of the conversion (call it
+  //   A) as described in 14.8.2.4.
+  TemplateParameterList *TemplateParams
+    = FunctionTemplate->getTemplateParameters();
+  SmallVector<DeducedTemplateArgument, 4> Deduced;
+  Deduced.resize(TemplateParams->size());
+
+  // C++0x [temp.deduct.conv]p4:
+  //   In general, the deduction process attempts to find template
+  //   argument values that will make the deduced A identical to
+  //   A. However, there are two cases that allow a difference:
+  unsigned TDF = 0;
+  //     - If the original A is a reference type, A can be more
+  //       cv-qualified than the deduced A (i.e., the type referred to
+  //       by the reference)
+  if (ToType->isReferenceType())
+    TDF |= TDF_ParamWithReferenceType;
+  //     - The deduced A can be another pointer or pointer to member
+  //       type that can be converted to A via a qualification
+  //       conversion.
+  //
+  // (C++0x [temp.deduct.conv]p6 clarifies that this only happens when
+  // both P and A are pointers or member pointers. In this case, we
+  // just ignore cv-qualifiers completely).
+  if ((P->isPointerType() && A->isPointerType()) ||
+      (P->isMemberPointerType() && A->isMemberPointerType()))
+    TDF |= TDF_IgnoreQualifiers;
+  if (TemplateDeductionResult Result
+        = DeduceTemplateArgumentsByTypeMatch(*this, TemplateParams,
+                                             P, A, Info, Deduced, TDF))
+    return Result;
+
+  // Finish template argument deduction.
+  LocalInstantiationScope InstScope(*this);
+  FunctionDecl *Spec = 0;
+  TemplateDeductionResult Result
+    = FinishTemplateArgumentDeduction(FunctionTemplate, Deduced, 0, Spec,
+                                      Info);
+  Specialization = cast_or_null<CXXConversionDecl>(Spec);
+  return Result;
+}
+
+/// \brief Deduce template arguments for a function template when there is
+/// nothing to deduce against (C++0x [temp.arg.explicit]p3).
+///
+/// \param FunctionTemplate the function template for which we are performing
+/// template argument deduction.
+///
+/// \param ExplicitTemplateArguments the explicitly-specified template
+/// arguments.
+///
+/// \param Specialization if template argument deduction was successful,
+/// this will be set to the function template specialization produced by
+/// template argument deduction.
+///
+/// \param Info the argument will be updated to provide additional information
+/// about template argument deduction.
+///
+/// \returns the result of template argument deduction.
+Sema::TemplateDeductionResult
+Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
+                              TemplateArgumentListInfo *ExplicitTemplateArgs,
+                              FunctionDecl *&Specialization,
+                              TemplateDeductionInfo &Info) {
+  return DeduceTemplateArguments(FunctionTemplate, ExplicitTemplateArgs,
+                                 QualType(), Specialization, Info);
+}
+
+namespace {
+  /// Substitute the 'auto' type specifier within a type for a given replacement
+  /// type.
+  class SubstituteAutoTransform :
+    public TreeTransform<SubstituteAutoTransform> {
+    QualType Replacement;
+  public:
+    SubstituteAutoTransform(Sema &SemaRef, QualType Replacement) :
+      TreeTransform<SubstituteAutoTransform>(SemaRef), Replacement(Replacement) {
+    }
+    QualType TransformAutoType(TypeLocBuilder &TLB, AutoTypeLoc TL) {
+      // If we're building the type pattern to deduce against, don't wrap the
+      // substituted type in an AutoType. Certain template deduction rules
+      // apply only when a template type parameter appears directly (and not if
+      // the parameter is found through desugaring). For instance:
+      //   auto &&lref = lvalue;
+      // must transform into "rvalue reference to T" not "rvalue reference to
+      // auto type deduced as T" in order for [temp.deduct.call]p3 to apply.
+      if (isa<TemplateTypeParmType>(Replacement)) {
+        QualType Result = Replacement;
+        TemplateTypeParmTypeLoc NewTL = TLB.push<TemplateTypeParmTypeLoc>(Result);
+        NewTL.setNameLoc(TL.getNameLoc());
+        return Result;
+      } else {
+        QualType Result = RebuildAutoType(Replacement);
+        AutoTypeLoc NewTL = TLB.push<AutoTypeLoc>(Result);
+        NewTL.setNameLoc(TL.getNameLoc());
+        return Result;
+      }
+    }
+
+    ExprResult TransformLambdaExpr(LambdaExpr *E) {
+      // Lambdas never need to be transformed.
+      return E;
+    }
+  };
+}
+
+/// \brief Deduce the type for an auto type-specifier (C++0x [dcl.spec.auto]p6)
+///
+/// \param Type the type pattern using the auto type-specifier.
+///
+/// \param Init the initializer for the variable whose type is to be deduced.
+///
+/// \param Result if type deduction was successful, this will be set to the
+/// deduced type. This may still contain undeduced autos if the type is
+/// dependent. This will be set to null if deduction succeeded, but auto
+/// substitution failed; the appropriate diagnostic will already have been
+/// produced in that case.
+Sema::DeduceAutoResult
+Sema::DeduceAutoType(TypeSourceInfo *Type, Expr *&Init,
+                     TypeSourceInfo *&Result) {
+  if (Init->getType()->isNonOverloadPlaceholderType()) {
+    ExprResult result = CheckPlaceholderExpr(Init);
+    if (result.isInvalid()) return DAR_FailedAlreadyDiagnosed;
+    Init = result.take();
+  }
+
+  if (Init->isTypeDependent()) {
+    Result = Type;
+    return DAR_Succeeded;
+  }
+
+  SourceLocation Loc = Init->getExprLoc();
+
+  LocalInstantiationScope InstScope(*this);
+
+  // Build template<class TemplParam> void Func(FuncParam);
+  TemplateTypeParmDecl *TemplParam =
+    TemplateTypeParmDecl::Create(Context, 0, SourceLocation(), Loc, 0, 0, 0,
+                                 false, false);
+  QualType TemplArg = QualType(TemplParam->getTypeForDecl(), 0);
+  NamedDecl *TemplParamPtr = TemplParam;
+  FixedSizeTemplateParameterList<1> TemplateParams(Loc, Loc, &TemplParamPtr,
+                                                   Loc);
+
+  TypeSourceInfo *FuncParamInfo =
+    SubstituteAutoTransform(*this, TemplArg).TransformType(Type);
+  assert(FuncParamInfo && "substituting template parameter for 'auto' failed");
+  QualType FuncParam = FuncParamInfo->getType();
+
+  // Deduce type of TemplParam in Func(Init)
+  SmallVector<DeducedTemplateArgument, 1> Deduced;
+  Deduced.resize(1);
+  QualType InitType = Init->getType();
+  unsigned TDF = 0;
+
+  TemplateDeductionInfo Info(Context, Loc);
+
+  InitListExpr * InitList = dyn_cast<InitListExpr>(Init);
+  if (InitList) {
+    for (unsigned i = 0, e = InitList->getNumInits(); i < e; ++i) {
+      if (DeduceTemplateArgumentByListElement(*this, &TemplateParams, 
+                                              TemplArg,
+                                              InitList->getInit(i),
+                                              Info, Deduced, TDF))
+        return DAR_Failed;
+    }
+  } else {
+    if (AdjustFunctionParmAndArgTypesForDeduction(*this, &TemplateParams,
+                                                  FuncParam, InitType, Init,
+                                                  TDF))
+      return DAR_Failed;
+    
+    if (DeduceTemplateArgumentsByTypeMatch(*this, &TemplateParams, FuncParam,
+                                           InitType, Info, Deduced, TDF))
+      return DAR_Failed;
+  }
+
+  QualType DeducedType = Deduced[0].getAsType();
+  if (DeducedType.isNull())
+    return DAR_Failed;
+
+  if (InitList) {
+    DeducedType = BuildStdInitializerList(DeducedType, Loc);
+    if (DeducedType.isNull())
+      return DAR_FailedAlreadyDiagnosed;
+  }
+
+  Result = SubstituteAutoTransform(*this, DeducedType).TransformType(Type);
+
+  // Check that the deduced argument type is compatible with the original
+  // argument type per C++ [temp.deduct.call]p4.
+  if (!InitList && Result &&
+      CheckOriginalCallArgDeduction(*this, 
+                                    Sema::OriginalCallArg(FuncParam,0,InitType),
+                                    Result->getType())) {
+    Result = 0;
+    return DAR_Failed;
+  }
+
+  return DAR_Succeeded;
+}
+
+void Sema::DiagnoseAutoDeductionFailure(VarDecl *VDecl, Expr *Init) {
+  if (isa<InitListExpr>(Init))
+    Diag(VDecl->getLocation(),
+         diag::err_auto_var_deduction_failure_from_init_list)
+      << VDecl->getDeclName() << VDecl->getType() << Init->getSourceRange();
+  else
+    Diag(VDecl->getLocation(), diag::err_auto_var_deduction_failure)
+      << VDecl->getDeclName() << VDecl->getType() << Init->getType()
+      << Init->getSourceRange();
+}
+
+static void
+MarkUsedTemplateParameters(ASTContext &Ctx, QualType T,
+                           bool OnlyDeduced,
+                           unsigned Level,
+                           llvm::SmallBitVector &Deduced);
+
+/// \brief If this is a non-static member function,
+static void MaybeAddImplicitObjectParameterType(ASTContext &Context,
+                                                CXXMethodDecl *Method,
+                                 SmallVectorImpl<QualType> &ArgTypes) {
+  if (Method->isStatic())
+    return;
+
+  // C++ [over.match.funcs]p4:
+  //
+  //   For non-static member functions, the type of the implicit
+  //   object parameter is
+  //     - "lvalue reference to cv X" for functions declared without a
+  //       ref-qualifier or with the & ref-qualifier
+  //     - "rvalue reference to cv X" for functions declared with the
+  //       && ref-qualifier
+  //
+  // FIXME: We don't have ref-qualifiers yet, so we don't do that part.
+  QualType ArgTy = Context.getTypeDeclType(Method->getParent());
+  ArgTy = Context.getQualifiedType(ArgTy,
+                        Qualifiers::fromCVRMask(Method->getTypeQualifiers()));
+  ArgTy = Context.getLValueReferenceType(ArgTy);
+  ArgTypes.push_back(ArgTy);
+}
+
+/// \brief Determine whether the function template \p FT1 is at least as
+/// specialized as \p FT2.
+static bool isAtLeastAsSpecializedAs(Sema &S,
+                                     SourceLocation Loc,
+                                     FunctionTemplateDecl *FT1,
+                                     FunctionTemplateDecl *FT2,
+                                     TemplatePartialOrderingContext TPOC,
+                                     unsigned NumCallArguments,
+    SmallVectorImpl<RefParamPartialOrderingComparison> *RefParamComparisons) {
+  FunctionDecl *FD1 = FT1->getTemplatedDecl();
+  FunctionDecl *FD2 = FT2->getTemplatedDecl();
+  const FunctionProtoType *Proto1 = FD1->getType()->getAs<FunctionProtoType>();
+  const FunctionProtoType *Proto2 = FD2->getType()->getAs<FunctionProtoType>();
+
+  assert(Proto1 && Proto2 && "Function templates must have prototypes");
+  TemplateParameterList *TemplateParams = FT2->getTemplateParameters();
+  SmallVector<DeducedTemplateArgument, 4> Deduced;
+  Deduced.resize(TemplateParams->size());
+
+  // C++0x [temp.deduct.partial]p3:
+  //   The types used to determine the ordering depend on the context in which
+  //   the partial ordering is done:
+  TemplateDeductionInfo Info(S.Context, Loc);
+  CXXMethodDecl *Method1 = 0;
+  CXXMethodDecl *Method2 = 0;
+  bool IsNonStatic2 = false;
+  bool IsNonStatic1 = false;
+  unsigned Skip2 = 0;
+  switch (TPOC) {
+  case TPOC_Call: {
+    //   - In the context of a function call, the function parameter types are
+    //     used.
+    Method1 = dyn_cast<CXXMethodDecl>(FD1);
+    Method2 = dyn_cast<CXXMethodDecl>(FD2);
+    IsNonStatic1 = Method1 && !Method1->isStatic();
+    IsNonStatic2 = Method2 && !Method2->isStatic();
+
+    // C++0x [temp.func.order]p3:
+    //   [...] If only one of the function templates is a non-static
+    //   member, that function template is considered to have a new
+    //   first parameter inserted in its function parameter list. The
+    //   new parameter is of type "reference to cv A," where cv are
+    //   the cv-qualifiers of the function template (if any) and A is
+    //   the class of which the function template is a member.
+    //
+    // C++98/03 doesn't have this provision, so instead we drop the
+    // first argument of the free function or static member, which
+    // seems to match existing practice.
+    SmallVector<QualType, 4> Args1;
+    unsigned Skip1 = !S.getLangOpts().CPlusPlus0x &&
+      IsNonStatic2 && !IsNonStatic1;
+    if (S.getLangOpts().CPlusPlus0x && IsNonStatic1 && !IsNonStatic2)
+      MaybeAddImplicitObjectParameterType(S.Context, Method1, Args1);
+    Args1.insert(Args1.end(),
+                 Proto1->arg_type_begin() + Skip1, Proto1->arg_type_end());
+
+    SmallVector<QualType, 4> Args2;
+    Skip2 = !S.getLangOpts().CPlusPlus0x &&
+      IsNonStatic1 && !IsNonStatic2;
+    if (S.getLangOpts().CPlusPlus0x && IsNonStatic2 && !IsNonStatic1)
+      MaybeAddImplicitObjectParameterType(S.Context, Method2, Args2);
+    Args2.insert(Args2.end(),
+                 Proto2->arg_type_begin() + Skip2, Proto2->arg_type_end());
+
+    // C++ [temp.func.order]p5:
+    //   The presence of unused ellipsis and default arguments has no effect on
+    //   the partial ordering of function templates.
+    if (Args1.size() > NumCallArguments)
+      Args1.resize(NumCallArguments);
+    if (Args2.size() > NumCallArguments)
+      Args2.resize(NumCallArguments);
+    if (DeduceTemplateArguments(S, TemplateParams, Args2.data(), Args2.size(),
+                                Args1.data(), Args1.size(), Info, Deduced,
+                                TDF_None, /*PartialOrdering=*/true,
+                                RefParamComparisons))
+        return false;
+
+    break;
+  }
+
+  case TPOC_Conversion:
+    //   - In the context of a call to a conversion operator, the return types
+    //     of the conversion function templates are used.
+    if (DeduceTemplateArgumentsByTypeMatch(S, TemplateParams,
+                                           Proto2->getResultType(),
+                                           Proto1->getResultType(),
+                                           Info, Deduced, TDF_None,
+                                           /*PartialOrdering=*/true,
+                                           RefParamComparisons))
+      return false;
+    break;
+
+  case TPOC_Other:
+    //   - In other contexts (14.6.6.2) the function template's function type
+    //     is used.
+    if (DeduceTemplateArgumentsByTypeMatch(S, TemplateParams,
+                                           FD2->getType(), FD1->getType(),
+                                           Info, Deduced, TDF_None,
+                                           /*PartialOrdering=*/true,
+                                           RefParamComparisons))
+      return false;
+    break;
+  }
+
+  // C++0x [temp.deduct.partial]p11:
+  //   In most cases, all template parameters must have values in order for
+  //   deduction to succeed, but for partial ordering purposes a template
+  //   parameter may remain without a value provided it is not used in the
+  //   types being used for partial ordering. [ Note: a template parameter used
+  //   in a non-deduced context is considered used. -end note]
+  unsigned ArgIdx = 0, NumArgs = Deduced.size();
+  for (; ArgIdx != NumArgs; ++ArgIdx)
+    if (Deduced[ArgIdx].isNull())
+      break;
+
+  if (ArgIdx == NumArgs) {
+    // All template arguments were deduced. FT1 is at least as specialized
+    // as FT2.
+    return true;
+  }
+
+  // Figure out which template parameters were used.
+  llvm::SmallBitVector UsedParameters(TemplateParams->size());
+  switch (TPOC) {
+  case TPOC_Call: {
+    unsigned NumParams = std::min(NumCallArguments,
+                                  std::min(Proto1->getNumArgs(),
+                                           Proto2->getNumArgs()));
+    if (S.getLangOpts().CPlusPlus0x && IsNonStatic2 && !IsNonStatic1)
+      ::MarkUsedTemplateParameters(S.Context, Method2->getThisType(S.Context),
+                                   false,
+                                   TemplateParams->getDepth(), UsedParameters);
+    for (unsigned I = Skip2; I < NumParams; ++I)
+      ::MarkUsedTemplateParameters(S.Context, Proto2->getArgType(I), false,
+                                   TemplateParams->getDepth(),
+                                   UsedParameters);
+    break;
+  }
+
+  case TPOC_Conversion:
+    ::MarkUsedTemplateParameters(S.Context, Proto2->getResultType(), false,
+                                 TemplateParams->getDepth(),
+                                 UsedParameters);
+    break;
+
+  case TPOC_Other:
+    ::MarkUsedTemplateParameters(S.Context, FD2->getType(), false,
+                                 TemplateParams->getDepth(),
+                                 UsedParameters);
+    break;
+  }
+
+  for (; ArgIdx != NumArgs; ++ArgIdx)
+    // If this argument had no value deduced but was used in one of the types
+    // used for partial ordering, then deduction fails.
+    if (Deduced[ArgIdx].isNull() && UsedParameters[ArgIdx])
+      return false;
+
+  return true;
+}
+
+/// \brief Determine whether this a function template whose parameter-type-list
+/// ends with a function parameter pack.
+static bool isVariadicFunctionTemplate(FunctionTemplateDecl *FunTmpl) {
+  FunctionDecl *Function = FunTmpl->getTemplatedDecl();
+  unsigned NumParams = Function->getNumParams();
+  if (NumParams == 0)
+    return false;
+
+  ParmVarDecl *Last = Function->getParamDecl(NumParams - 1);
+  if (!Last->isParameterPack())
+    return false;
+
+  // Make sure that no previous parameter is a parameter pack.
+  while (--NumParams > 0) {
+    if (Function->getParamDecl(NumParams - 1)->isParameterPack())
+      return false;
+  }
+
+  return true;
+}
+
+/// \brief Returns the more specialized function template according
+/// to the rules of function template partial ordering (C++ [temp.func.order]).
+///
+/// \param FT1 the first function template
+///
+/// \param FT2 the second function template
+///
+/// \param TPOC the context in which we are performing partial ordering of
+/// function templates.
+///
+/// \param NumCallArguments The number of arguments in a call, used only
+/// when \c TPOC is \c TPOC_Call.
+///
+/// \returns the more specialized function template. If neither
+/// template is more specialized, returns NULL.
+FunctionTemplateDecl *
+Sema::getMoreSpecializedTemplate(FunctionTemplateDecl *FT1,
+                                 FunctionTemplateDecl *FT2,
+                                 SourceLocation Loc,
+                                 TemplatePartialOrderingContext TPOC,
+                                 unsigned NumCallArguments) {
+  SmallVector<RefParamPartialOrderingComparison, 4> RefParamComparisons;
+  bool Better1 = isAtLeastAsSpecializedAs(*this, Loc, FT1, FT2, TPOC,
+                                          NumCallArguments, 0);
+  bool Better2 = isAtLeastAsSpecializedAs(*this, Loc, FT2, FT1, TPOC,
+                                          NumCallArguments,
+                                          &RefParamComparisons);
+
+  if (Better1 != Better2) // We have a clear winner
+    return Better1? FT1 : FT2;
+
+  if (!Better1 && !Better2) // Neither is better than the other
+    return 0;
+
+  // C++0x [temp.deduct.partial]p10:
+  //   If for each type being considered a given template is at least as
+  //   specialized for all types and more specialized for some set of types and
+  //   the other template is not more specialized for any types or is not at
+  //   least as specialized for any types, then the given template is more
+  //   specialized than the other template. Otherwise, neither template is more
+  //   specialized than the other.
+  Better1 = false;
+  Better2 = false;
+  for (unsigned I = 0, N = RefParamComparisons.size(); I != N; ++I) {
+    // C++0x [temp.deduct.partial]p9:
+    //   If, for a given type, deduction succeeds in both directions (i.e., the
+    //   types are identical after the transformations above) and both P and A
+    //   were reference types (before being replaced with the type referred to
+    //   above):
+
+    //     -- if the type from the argument template was an lvalue reference
+    //        and the type from the parameter template was not, the argument
+    //        type is considered to be more specialized than the other;
+    //        otherwise,
+    if (!RefParamComparisons[I].ArgIsRvalueRef &&
+        RefParamComparisons[I].ParamIsRvalueRef) {
+      Better2 = true;
+      if (Better1)
+        return 0;
+      continue;
+    } else if (!RefParamComparisons[I].ParamIsRvalueRef &&
+               RefParamComparisons[I].ArgIsRvalueRef) {
+      Better1 = true;
+      if (Better2)
+        return 0;
+      continue;
+    }
+
+    //     -- if the type from the argument template is more cv-qualified than
+    //        the type from the parameter template (as described above), the
+    //        argument type is considered to be more specialized than the
+    //        other; otherwise,
+    switch (RefParamComparisons[I].Qualifiers) {
+    case NeitherMoreQualified:
+      break;
+
+    case ParamMoreQualified:
+      Better1 = true;
+      if (Better2)
+        return 0;
+      continue;
+
+    case ArgMoreQualified:
+      Better2 = true;
+      if (Better1)
+        return 0;
+      continue;
+    }
+
+    //     -- neither type is more specialized than the other.
+  }
+
+  assert(!(Better1 && Better2) && "Should have broken out in the loop above");
+  if (Better1)
+    return FT1;
+  else if (Better2)
+    return FT2;
+
+  // FIXME: This mimics what GCC implements, but doesn't match up with the
+  // proposed resolution for core issue 692. This area needs to be sorted out,
+  // but for now we attempt to maintain compatibility.
+  bool Variadic1 = isVariadicFunctionTemplate(FT1);
+  bool Variadic2 = isVariadicFunctionTemplate(FT2);
+  if (Variadic1 != Variadic2)
+    return Variadic1? FT2 : FT1;
+
+  return 0;
+}
+
+/// \brief Determine if the two templates are equivalent.
+static bool isSameTemplate(TemplateDecl *T1, TemplateDecl *T2) {
+  if (T1 == T2)
+    return true;
+
+  if (!T1 || !T2)
+    return false;
+
+  return T1->getCanonicalDecl() == T2->getCanonicalDecl();
+}
+
+/// \brief Retrieve the most specialized of the given function template
+/// specializations.
+///
+/// \param SpecBegin the start iterator of the function template
+/// specializations that we will be comparing.
+///
+/// \param SpecEnd the end iterator of the function template
+/// specializations, paired with \p SpecBegin.
+///
+/// \param TPOC the partial ordering context to use to compare the function
+/// template specializations.
+///
+/// \param NumCallArguments The number of arguments in a call, used only
+/// when \c TPOC is \c TPOC_Call.
+///
+/// \param Loc the location where the ambiguity or no-specializations
+/// diagnostic should occur.
+///
+/// \param NoneDiag partial diagnostic used to diagnose cases where there are
+/// no matching candidates.
+///
+/// \param AmbigDiag partial diagnostic used to diagnose an ambiguity, if one
+/// occurs.
+///
+/// \param CandidateDiag partial diagnostic used for each function template
+/// specialization that is a candidate in the ambiguous ordering. One parameter
+/// in this diagnostic should be unbound, which will correspond to the string
+/// describing the template arguments for the function template specialization.
+///
+/// \param Index if non-NULL and the result of this function is non-nULL,
+/// receives the index corresponding to the resulting function template
+/// specialization.
+///
+/// \returns the most specialized function template specialization, if
+/// found. Otherwise, returns SpecEnd.
+///
+/// \todo FIXME: Consider passing in the "also-ran" candidates that failed
+/// template argument deduction.
+UnresolvedSetIterator
+Sema::getMostSpecialized(UnresolvedSetIterator SpecBegin,
+                        UnresolvedSetIterator SpecEnd,
+                         TemplatePartialOrderingContext TPOC,
+                         unsigned NumCallArguments,
+                         SourceLocation Loc,
+                         const PartialDiagnostic &NoneDiag,
+                         const PartialDiagnostic &AmbigDiag,
+                         const PartialDiagnostic &CandidateDiag,
+                         bool Complain,
+                         QualType TargetType) {
+  if (SpecBegin == SpecEnd) {
+    if (Complain)
+      Diag(Loc, NoneDiag);
+    return SpecEnd;
+  }
+
+  if (SpecBegin + 1 == SpecEnd)
+    return SpecBegin;
+
+  // Find the function template that is better than all of the templates it
+  // has been compared to.
+  UnresolvedSetIterator Best = SpecBegin;
+  FunctionTemplateDecl *BestTemplate
+    = cast<FunctionDecl>(*Best)->getPrimaryTemplate();
+  assert(BestTemplate && "Not a function template specialization?");
+  for (UnresolvedSetIterator I = SpecBegin + 1; I != SpecEnd; ++I) {
+    FunctionTemplateDecl *Challenger
+      = cast<FunctionDecl>(*I)->getPrimaryTemplate();
+    assert(Challenger && "Not a function template specialization?");
+    if (isSameTemplate(getMoreSpecializedTemplate(BestTemplate, Challenger,
+                                                  Loc, TPOC, NumCallArguments),
+                       Challenger)) {
+      Best = I;
+      BestTemplate = Challenger;
+    }
+  }
+
+  // Make sure that the "best" function template is more specialized than all
+  // of the others.
+  bool Ambiguous = false;
+  for (UnresolvedSetIterator I = SpecBegin; I != SpecEnd; ++I) {
+    FunctionTemplateDecl *Challenger
+      = cast<FunctionDecl>(*I)->getPrimaryTemplate();
+    if (I != Best &&
+        !isSameTemplate(getMoreSpecializedTemplate(BestTemplate, Challenger,
+                                                   Loc, TPOC, NumCallArguments),
+                        BestTemplate)) {
+      Ambiguous = true;
+      break;
+    }
+  }
+
+  if (!Ambiguous) {
+    // We found an answer. Return it.
+    return Best;
+  }
+
+  // Diagnose the ambiguity.
+  if (Complain)
+    Diag(Loc, AmbigDiag);
+
+  if (Complain)
+  // FIXME: Can we order the candidates in some sane way?
+    for (UnresolvedSetIterator I = SpecBegin; I != SpecEnd; ++I) {
+      PartialDiagnostic PD = CandidateDiag;
+      PD << getTemplateArgumentBindingsText(
+          cast<FunctionDecl>(*I)->getPrimaryTemplate()->getTemplateParameters(),
+                    *cast<FunctionDecl>(*I)->getTemplateSpecializationArgs());
+      if (!TargetType.isNull())
+        HandleFunctionTypeMismatch(PD, cast<FunctionDecl>(*I)->getType(),
+                                   TargetType);
+      Diag((*I)->getLocation(), PD);
+    }
+
+  return SpecEnd;
+}
+
+/// \brief Returns the more specialized class template partial specialization
+/// according to the rules of partial ordering of class template partial
+/// specializations (C++ [temp.class.order]).
+///
+/// \param PS1 the first class template partial specialization
+///
+/// \param PS2 the second class template partial specialization
+///
+/// \returns the more specialized class template partial specialization. If
+/// neither partial specialization is more specialized, returns NULL.
+ClassTemplatePartialSpecializationDecl *
+Sema::getMoreSpecializedPartialSpecialization(
+                                  ClassTemplatePartialSpecializationDecl *PS1,
+                                  ClassTemplatePartialSpecializationDecl *PS2,
+                                              SourceLocation Loc) {
+  // C++ [temp.class.order]p1:
+  //   For two class template partial specializations, the first is at least as
+  //   specialized as the second if, given the following rewrite to two
+  //   function templates, the first function template is at least as
+  //   specialized as the second according to the ordering rules for function
+  //   templates (14.6.6.2):
+  //     - the first function template has the same template parameters as the
+  //       first partial specialization and has a single function parameter
+  //       whose type is a class template specialization with the template
+  //       arguments of the first partial specialization, and
+  //     - the second function template has the same template parameters as the
+  //       second partial specialization and has a single function parameter
+  //       whose type is a class template specialization with the template
+  //       arguments of the second partial specialization.
+  //
+  // Rather than synthesize function templates, we merely perform the
+  // equivalent partial ordering by performing deduction directly on
+  // the template arguments of the class template partial
+  // specializations. This computation is slightly simpler than the
+  // general problem of function template partial ordering, because
+  // class template partial specializations are more constrained. We
+  // know that every template parameter is deducible from the class
+  // template partial specialization's template arguments, for
+  // example.
+  SmallVector<DeducedTemplateArgument, 4> Deduced;
+  TemplateDeductionInfo Info(Context, Loc);
+
+  QualType PT1 = PS1->getInjectedSpecializationType();
+  QualType PT2 = PS2->getInjectedSpecializationType();
+
+  // Determine whether PS1 is at least as specialized as PS2
+  Deduced.resize(PS2->getTemplateParameters()->size());
+  bool Better1 = !DeduceTemplateArgumentsByTypeMatch(*this,
+                                            PS2->getTemplateParameters(),
+                                            PT2, PT1, Info, Deduced, TDF_None,
+                                            /*PartialOrdering=*/true,
+                                            /*RefParamComparisons=*/0);
+  if (Better1) {
+    InstantiatingTemplate Inst(*this, PS2->getLocation(), PS2,
+                               Deduced.data(), Deduced.size(), Info);
+    Better1 = !::FinishTemplateArgumentDeduction(*this, PS2,
+                                                 PS1->getTemplateArgs(),
+                                                 Deduced, Info);
+  }
+
+  // Determine whether PS2 is at least as specialized as PS1
+  Deduced.clear();
+  Deduced.resize(PS1->getTemplateParameters()->size());
+  bool Better2 = !DeduceTemplateArgumentsByTypeMatch(*this,
+                                            PS1->getTemplateParameters(),
+                                            PT1, PT2, Info, Deduced, TDF_None,
+                                            /*PartialOrdering=*/true,
+                                            /*RefParamComparisons=*/0);
+  if (Better2) {
+    InstantiatingTemplate Inst(*this, PS1->getLocation(), PS1,
+                               Deduced.data(), Deduced.size(), Info);
+    Better2 = !::FinishTemplateArgumentDeduction(*this, PS1,
+                                                 PS2->getTemplateArgs(),
+                                                 Deduced, Info);
+  }
+
+  if (Better1 == Better2)
+    return 0;
+
+  return Better1? PS1 : PS2;
+}
+
+static void
+MarkUsedTemplateParameters(ASTContext &Ctx,
+                           const TemplateArgument &TemplateArg,
+                           bool OnlyDeduced,
+                           unsigned Depth,
+                           llvm::SmallBitVector &Used);
+
+/// \brief Mark the template parameters that are used by the given
+/// expression.
+static void
+MarkUsedTemplateParameters(ASTContext &Ctx,
+                           const Expr *E,
+                           bool OnlyDeduced,
+                           unsigned Depth,
+                           llvm::SmallBitVector &Used) {
+  // We can deduce from a pack expansion.
+  if (const PackExpansionExpr *Expansion = dyn_cast<PackExpansionExpr>(E))
+    E = Expansion->getPattern();
+
+  // Skip through any implicit casts we added while type-checking.
+  while (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(E))
+    E = ICE->getSubExpr();
+
+  // FIXME: if !OnlyDeduced, we have to walk the whole subexpression to
+  // find other occurrences of template parameters.
+  const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E);
+  if (!DRE)
+    return;
+
+  const NonTypeTemplateParmDecl *NTTP
+    = dyn_cast<NonTypeTemplateParmDecl>(DRE->getDecl());
+  if (!NTTP)
+    return;
+
+  if (NTTP->getDepth() == Depth)
+    Used[NTTP->getIndex()] = true;
+}
+
+/// \brief Mark the template parameters that are used by the given
+/// nested name specifier.
+static void
+MarkUsedTemplateParameters(ASTContext &Ctx,
+                           NestedNameSpecifier *NNS,
+                           bool OnlyDeduced,
+                           unsigned Depth,
+                           llvm::SmallBitVector &Used) {
+  if (!NNS)
+    return;
+
+  MarkUsedTemplateParameters(Ctx, NNS->getPrefix(), OnlyDeduced, Depth,
+                             Used);
+  MarkUsedTemplateParameters(Ctx, QualType(NNS->getAsType(), 0),
+                             OnlyDeduced, Depth, Used);
+}
+
+/// \brief Mark the template parameters that are used by the given
+/// template name.
+static void
+MarkUsedTemplateParameters(ASTContext &Ctx,
+                           TemplateName Name,
+                           bool OnlyDeduced,
+                           unsigned Depth,
+                           llvm::SmallBitVector &Used) {
+  if (TemplateDecl *Template = Name.getAsTemplateDecl()) {
+    if (TemplateTemplateParmDecl *TTP
+          = dyn_cast<TemplateTemplateParmDecl>(Template)) {
+      if (TTP->getDepth() == Depth)
+        Used[TTP->getIndex()] = true;
+    }
+    return;
+  }
+
+  if (QualifiedTemplateName *QTN = Name.getAsQualifiedTemplateName())
+    MarkUsedTemplateParameters(Ctx, QTN->getQualifier(), OnlyDeduced,
+                               Depth, Used);
+  if (DependentTemplateName *DTN = Name.getAsDependentTemplateName())
+    MarkUsedTemplateParameters(Ctx, DTN->getQualifier(), OnlyDeduced,
+                               Depth, Used);
+}
+
+/// \brief Mark the template parameters that are used by the given
+/// type.
+static void
+MarkUsedTemplateParameters(ASTContext &Ctx, QualType T,
+                           bool OnlyDeduced,
+                           unsigned Depth,
+                           llvm::SmallBitVector &Used) {
+  if (T.isNull())
+    return;
+
+  // Non-dependent types have nothing deducible
+  if (!T->isDependentType())
+    return;
+
+  T = Ctx.getCanonicalType(T);
+  switch (T->getTypeClass()) {
+  case Type::Pointer:
+    MarkUsedTemplateParameters(Ctx,
+                               cast<PointerType>(T)->getPointeeType(),
+                               OnlyDeduced,
+                               Depth,
+                               Used);
+    break;
+
+  case Type::BlockPointer:
+    MarkUsedTemplateParameters(Ctx,
+                               cast<BlockPointerType>(T)->getPointeeType(),
+                               OnlyDeduced,
+                               Depth,
+                               Used);
+    break;
+
+  case Type::LValueReference:
+  case Type::RValueReference:
+    MarkUsedTemplateParameters(Ctx,
+                               cast<ReferenceType>(T)->getPointeeType(),
+                               OnlyDeduced,
+                               Depth,
+                               Used);
+    break;
+
+  case Type::MemberPointer: {
+    const MemberPointerType *MemPtr = cast<MemberPointerType>(T.getTypePtr());
+    MarkUsedTemplateParameters(Ctx, MemPtr->getPointeeType(), OnlyDeduced,
+                               Depth, Used);
+    MarkUsedTemplateParameters(Ctx, QualType(MemPtr->getClass(), 0),
+                               OnlyDeduced, Depth, Used);
+    break;
+  }
+
+  case Type::DependentSizedArray:
+    MarkUsedTemplateParameters(Ctx,
+                               cast<DependentSizedArrayType>(T)->getSizeExpr(),
+                               OnlyDeduced, Depth, Used);
+    // Fall through to check the element type
+
+  case Type::ConstantArray:
+  case Type::IncompleteArray:
+    MarkUsedTemplateParameters(Ctx,
+                               cast<ArrayType>(T)->getElementType(),
+                               OnlyDeduced, Depth, Used);
+    break;
+
+  case Type::Vector:
+  case Type::ExtVector:
+    MarkUsedTemplateParameters(Ctx,
+                               cast<VectorType>(T)->getElementType(),
+                               OnlyDeduced, Depth, Used);
+    break;
+
+  case Type::DependentSizedExtVector: {
+    const DependentSizedExtVectorType *VecType
+      = cast<DependentSizedExtVectorType>(T);
+    MarkUsedTemplateParameters(Ctx, VecType->getElementType(), OnlyDeduced,
+                               Depth, Used);
+    MarkUsedTemplateParameters(Ctx, VecType->getSizeExpr(), OnlyDeduced,
+                               Depth, Used);
+    break;
+  }
+
+  case Type::FunctionProto: {
+    const FunctionProtoType *Proto = cast<FunctionProtoType>(T);
+    MarkUsedTemplateParameters(Ctx, Proto->getResultType(), OnlyDeduced,
+                               Depth, Used);
+    for (unsigned I = 0, N = Proto->getNumArgs(); I != N; ++I)
+      MarkUsedTemplateParameters(Ctx, Proto->getArgType(I), OnlyDeduced,
+                                 Depth, Used);
+    break;
+  }
+
+  case Type::TemplateTypeParm: {
+    const TemplateTypeParmType *TTP = cast<TemplateTypeParmType>(T);
+    if (TTP->getDepth() == Depth)
+      Used[TTP->getIndex()] = true;
+    break;
+  }
+
+  case Type::SubstTemplateTypeParmPack: {
+    const SubstTemplateTypeParmPackType *Subst
+      = cast<SubstTemplateTypeParmPackType>(T);
+    MarkUsedTemplateParameters(Ctx,
+                               QualType(Subst->getReplacedParameter(), 0),
+                               OnlyDeduced, Depth, Used);
+    MarkUsedTemplateParameters(Ctx, Subst->getArgumentPack(),
+                               OnlyDeduced, Depth, Used);
+    break;
+  }
+
+  case Type::InjectedClassName:
+    T = cast<InjectedClassNameType>(T)->getInjectedSpecializationType();
+    // fall through
+
+  case Type::TemplateSpecialization: {
+    const TemplateSpecializationType *Spec
+      = cast<TemplateSpecializationType>(T);
+    MarkUsedTemplateParameters(Ctx, Spec->getTemplateName(), OnlyDeduced,
+                               Depth, Used);
+
+    // C++0x [temp.deduct.type]p9:
+    //   If the template argument list of P contains a pack expansion that is not
+    //   the last template argument, the entire template argument list is a
+    //   non-deduced context.
+    if (OnlyDeduced &&
+        hasPackExpansionBeforeEnd(Spec->getArgs(), Spec->getNumArgs()))
+      break;
+
+    for (unsigned I = 0, N = Spec->getNumArgs(); I != N; ++I)
+      MarkUsedTemplateParameters(Ctx, Spec->getArg(I), OnlyDeduced, Depth,
+                                 Used);
+    break;
+  }
+
+  case Type::Complex:
+    if (!OnlyDeduced)
+      MarkUsedTemplateParameters(Ctx,
+                                 cast<ComplexType>(T)->getElementType(),
+                                 OnlyDeduced, Depth, Used);
+    break;
+
+  case Type::Atomic:
+    if (!OnlyDeduced)
+      MarkUsedTemplateParameters(Ctx,
+                                 cast<AtomicType>(T)->getValueType(),
+                                 OnlyDeduced, Depth, Used);
+    break;
+
+  case Type::DependentName:
+    if (!OnlyDeduced)
+      MarkUsedTemplateParameters(Ctx,
+                                 cast<DependentNameType>(T)->getQualifier(),
+                                 OnlyDeduced, Depth, Used);
+    break;
+
+  case Type::DependentTemplateSpecialization: {
+    const DependentTemplateSpecializationType *Spec
+      = cast<DependentTemplateSpecializationType>(T);
+    if (!OnlyDeduced)
+      MarkUsedTemplateParameters(Ctx, Spec->getQualifier(),
+                                 OnlyDeduced, Depth, Used);
+
+    // C++0x [temp.deduct.type]p9:
+    //   If the template argument list of P contains a pack expansion that is not
+    //   the last template argument, the entire template argument list is a
+    //   non-deduced context.
+    if (OnlyDeduced &&
+        hasPackExpansionBeforeEnd(Spec->getArgs(), Spec->getNumArgs()))
+      break;
+
+    for (unsigned I = 0, N = Spec->getNumArgs(); I != N; ++I)
+      MarkUsedTemplateParameters(Ctx, Spec->getArg(I), OnlyDeduced, Depth,
+                                 Used);
+    break;
+  }
+
+  case Type::TypeOf:
+    if (!OnlyDeduced)
+      MarkUsedTemplateParameters(Ctx,
+                                 cast<TypeOfType>(T)->getUnderlyingType(),
+                                 OnlyDeduced, Depth, Used);
+    break;
+
+  case Type::TypeOfExpr:
+    if (!OnlyDeduced)
+      MarkUsedTemplateParameters(Ctx,
+                                 cast<TypeOfExprType>(T)->getUnderlyingExpr(),
+                                 OnlyDeduced, Depth, Used);
+    break;
+
+  case Type::Decltype:
+    if (!OnlyDeduced)
+      MarkUsedTemplateParameters(Ctx,
+                                 cast<DecltypeType>(T)->getUnderlyingExpr(),
+                                 OnlyDeduced, Depth, Used);
+    break;
+
+  case Type::UnaryTransform:
+    if (!OnlyDeduced)
+      MarkUsedTemplateParameters(Ctx,
+                               cast<UnaryTransformType>(T)->getUnderlyingType(),
+                                 OnlyDeduced, Depth, Used);
+    break;
+
+  case Type::PackExpansion:
+    MarkUsedTemplateParameters(Ctx,
+                               cast<PackExpansionType>(T)->getPattern(),
+                               OnlyDeduced, Depth, Used);
+    break;
+
+  case Type::Auto:
+    MarkUsedTemplateParameters(Ctx,
+                               cast<AutoType>(T)->getDeducedType(),
+                               OnlyDeduced, Depth, Used);
+
+  // None of these types have any template parameters in them.
+  case Type::Builtin:
+  case Type::VariableArray:
+  case Type::FunctionNoProto:
+  case Type::Record:
+  case Type::Enum:
+  case Type::ObjCInterface:
+  case Type::ObjCObject:
+  case Type::ObjCObjectPointer:
+  case Type::UnresolvedUsing:
+#define TYPE(Class, Base)
+#define ABSTRACT_TYPE(Class, Base)
+#define DEPENDENT_TYPE(Class, Base)
+#define NON_CANONICAL_TYPE(Class, Base) case Type::Class:
+#include "clang/AST/TypeNodes.def"
+    break;
+  }
+}
+
+/// \brief Mark the template parameters that are used by this
+/// template argument.
+static void
+MarkUsedTemplateParameters(ASTContext &Ctx,
+                           const TemplateArgument &TemplateArg,
+                           bool OnlyDeduced,
+                           unsigned Depth,
+                           llvm::SmallBitVector &Used) {
+  switch (TemplateArg.getKind()) {
+  case TemplateArgument::Null:
+  case TemplateArgument::Integral:
+  case TemplateArgument::Declaration:
+    break;
+
+  case TemplateArgument::Type:
+    MarkUsedTemplateParameters(Ctx, TemplateArg.getAsType(), OnlyDeduced,
+                               Depth, Used);
+    break;
+
+  case TemplateArgument::Template:
+  case TemplateArgument::TemplateExpansion:
+    MarkUsedTemplateParameters(Ctx,
+                               TemplateArg.getAsTemplateOrTemplatePattern(),
+                               OnlyDeduced, Depth, Used);
+    break;
+
+  case TemplateArgument::Expression:
+    MarkUsedTemplateParameters(Ctx, TemplateArg.getAsExpr(), OnlyDeduced,
+                               Depth, Used);
+    break;
+
+  case TemplateArgument::Pack:
+    for (TemplateArgument::pack_iterator P = TemplateArg.pack_begin(),
+                                      PEnd = TemplateArg.pack_end();
+         P != PEnd; ++P)
+      MarkUsedTemplateParameters(Ctx, *P, OnlyDeduced, Depth, Used);
+    break;
+  }
+}
+
+/// \brief Mark the template parameters can be deduced by the given
+/// template argument list.
+///
+/// \param TemplateArgs the template argument list from which template
+/// parameters will be deduced.
+///
+/// \param Deduced a bit vector whose elements will be set to \c true
+/// to indicate when the corresponding template parameter will be
+/// deduced.
+void
+Sema::MarkUsedTemplateParameters(const TemplateArgumentList &TemplateArgs,
+                                 bool OnlyDeduced, unsigned Depth,
+                                 llvm::SmallBitVector &Used) {
+  // C++0x [temp.deduct.type]p9:
+  //   If the template argument list of P contains a pack expansion that is not
+  //   the last template argument, the entire template argument list is a
+  //   non-deduced context.
+  if (OnlyDeduced &&
+      hasPackExpansionBeforeEnd(TemplateArgs.data(), TemplateArgs.size()))
+    return;
+
+  for (unsigned I = 0, N = TemplateArgs.size(); I != N; ++I)
+    ::MarkUsedTemplateParameters(Context, TemplateArgs[I], OnlyDeduced,
+                                 Depth, Used);
+}
+
+/// \brief Marks all of the template parameters that will be deduced by a
+/// call to the given function template.
+void
+Sema::MarkDeducedTemplateParameters(ASTContext &Ctx,
+                                    FunctionTemplateDecl *FunctionTemplate,
+                                    llvm::SmallBitVector &Deduced) {
+  TemplateParameterList *TemplateParams
+    = FunctionTemplate->getTemplateParameters();
+  Deduced.clear();
+  Deduced.resize(TemplateParams->size());
+
+  FunctionDecl *Function = FunctionTemplate->getTemplatedDecl();
+  for (unsigned I = 0, N = Function->getNumParams(); I != N; ++I)
+    ::MarkUsedTemplateParameters(Ctx, Function->getParamDecl(I)->getType(),
+                                 true, TemplateParams->getDepth(), Deduced);
+}
+
+bool hasDeducibleTemplateParameters(Sema &S,
+                                    FunctionTemplateDecl *FunctionTemplate,
+                                    QualType T) {
+  if (!T->isDependentType())
+    return false;
+
+  TemplateParameterList *TemplateParams
+    = FunctionTemplate->getTemplateParameters();
+  llvm::SmallBitVector Deduced(TemplateParams->size());
+  ::MarkUsedTemplateParameters(S.Context, T, true, TemplateParams->getDepth(), 
+                               Deduced);
+
+  return Deduced.any();
+}
diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp
new file mode 100644
index 0000000..128dc2f
--- /dev/null
+++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp
@@ -0,0 +1,2621 @@
+//===------- SemaTemplateInstantiate.cpp - C++ Template Instantiation ------===/
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//===----------------------------------------------------------------------===/
+//
+//  This file implements C++ template instantiation.
+//
+//===----------------------------------------------------------------------===/
+
+#include "clang/Sema/SemaInternal.h"
+#include "TreeTransform.h"
+#include "clang/Sema/DeclSpec.h"
+#include "clang/Sema/Initialization.h"
+#include "clang/Sema/Lookup.h"
+#include "clang/Sema/Template.h"
+#include "clang/Sema/TemplateDeduction.h"
+#include "clang/AST/ASTConsumer.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/DeclTemplate.h"
+#include "clang/Basic/LangOptions.h"
+
+using namespace clang;
+using namespace sema;
+
+//===----------------------------------------------------------------------===/
+// Template Instantiation Support
+//===----------------------------------------------------------------------===/
+
+/// \brief Retrieve the template argument list(s) that should be used to
+/// instantiate the definition of the given declaration.
+///
+/// \param D the declaration for which we are computing template instantiation
+/// arguments.
+///
+/// \param Innermost if non-NULL, the innermost template argument list.
+///
+/// \param RelativeToPrimary true if we should get the template
+/// arguments relative to the primary template, even when we're
+/// dealing with a specialization. This is only relevant for function
+/// template specializations.
+///
+/// \param Pattern If non-NULL, indicates the pattern from which we will be
+/// instantiating the definition of the given declaration, \p D. This is
+/// used to determine the proper set of template instantiation arguments for
+/// friend function template specializations.
+MultiLevelTemplateArgumentList
+Sema::getTemplateInstantiationArgs(NamedDecl *D, 
+                                   const TemplateArgumentList *Innermost,
+                                   bool RelativeToPrimary,
+                                   const FunctionDecl *Pattern) {
+  // Accumulate the set of template argument lists in this structure.
+  MultiLevelTemplateArgumentList Result;
+
+  if (Innermost)
+    Result.addOuterTemplateArguments(Innermost);
+  
+  DeclContext *Ctx = dyn_cast<DeclContext>(D);
+  if (!Ctx) {
+    Ctx = D->getDeclContext();
+    
+    // If we have a template template parameter with translation unit context,
+    // then we're performing substitution into a default template argument of
+    // this template template parameter before we've constructed the template
+    // that will own this template template parameter. In this case, we
+    // use empty template parameter lists for all of the outer templates
+    // to avoid performing any substitutions.
+    if (Ctx->isTranslationUnit()) {
+      if (TemplateTemplateParmDecl *TTP 
+                                      = dyn_cast<TemplateTemplateParmDecl>(D)) {
+        for (unsigned I = 0, N = TTP->getDepth() + 1; I != N; ++I)
+          Result.addOuterTemplateArguments(0, 0);
+        return Result;
+      }
+    }
+  }
+  
+  while (!Ctx->isFileContext()) {
+    // Add template arguments from a class template instantiation.
+    if (ClassTemplateSpecializationDecl *Spec
+          = dyn_cast<ClassTemplateSpecializationDecl>(Ctx)) {
+      // We're done when we hit an explicit specialization.
+      if (Spec->getSpecializationKind() == TSK_ExplicitSpecialization &&
+          !isa<ClassTemplatePartialSpecializationDecl>(Spec))
+        break;
+
+      Result.addOuterTemplateArguments(&Spec->getTemplateInstantiationArgs());
+      
+      // If this class template specialization was instantiated from a 
+      // specialized member that is a class template, we're done.
+      assert(Spec->getSpecializedTemplate() && "No class template?");
+      if (Spec->getSpecializedTemplate()->isMemberSpecialization())
+        break;
+    }
+    // Add template arguments from a function template specialization.
+    else if (FunctionDecl *Function = dyn_cast<FunctionDecl>(Ctx)) {
+      if (!RelativeToPrimary &&
+          (Function->getTemplateSpecializationKind() == 
+                                                  TSK_ExplicitSpecialization &&
+           !Function->getClassScopeSpecializationPattern()))
+        break;
+          
+      if (const TemplateArgumentList *TemplateArgs
+            = Function->getTemplateSpecializationArgs()) {
+        // Add the template arguments for this specialization.
+        Result.addOuterTemplateArguments(TemplateArgs);
+
+        // If this function was instantiated from a specialized member that is
+        // a function template, we're done.
+        assert(Function->getPrimaryTemplate() && "No function template?");
+        if (Function->getPrimaryTemplate()->isMemberSpecialization())
+          break;
+      } else if (FunctionTemplateDecl *FunTmpl
+                                   = Function->getDescribedFunctionTemplate()) {
+        // Add the "injected" template arguments.
+        std::pair<const TemplateArgument *, unsigned>
+          Injected = FunTmpl->getInjectedTemplateArgs();
+        Result.addOuterTemplateArguments(Injected.first, Injected.second);
+      }
+      
+      // If this is a friend declaration and it declares an entity at
+      // namespace scope, take arguments from its lexical parent
+      // instead of its semantic parent, unless of course the pattern we're
+      // instantiating actually comes from the file's context!
+      if (Function->getFriendObjectKind() &&
+          Function->getDeclContext()->isFileContext() &&
+          (!Pattern || !Pattern->getLexicalDeclContext()->isFileContext())) {
+        Ctx = Function->getLexicalDeclContext();
+        RelativeToPrimary = false;
+        continue;
+      }
+    } else if (CXXRecordDecl *Rec = dyn_cast<CXXRecordDecl>(Ctx)) {
+      if (ClassTemplateDecl *ClassTemplate = Rec->getDescribedClassTemplate()) {
+        QualType T = ClassTemplate->getInjectedClassNameSpecialization();
+        const TemplateSpecializationType *TST
+          = cast<TemplateSpecializationType>(Context.getCanonicalType(T));
+        Result.addOuterTemplateArguments(TST->getArgs(), TST->getNumArgs());
+        if (ClassTemplate->isMemberSpecialization())
+          break;
+      }
+    }
+
+    Ctx = Ctx->getParent();
+    RelativeToPrimary = false;
+  }
+
+  return Result;
+}
+
+bool Sema::ActiveTemplateInstantiation::isInstantiationRecord() const {
+  switch (Kind) {
+  case TemplateInstantiation:
+  case ExceptionSpecInstantiation:
+  case DefaultTemplateArgumentInstantiation:
+  case DefaultFunctionArgumentInstantiation:
+    return true;
+      
+  case ExplicitTemplateArgumentSubstitution:
+  case DeducedTemplateArgumentSubstitution:
+  case PriorTemplateArgumentSubstitution:
+  case DefaultTemplateArgumentChecking:
+    return false;
+  }
+
+  llvm_unreachable("Invalid InstantiationKind!");
+}
+
+Sema::InstantiatingTemplate::
+InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
+                      Decl *Entity,
+                      SourceRange InstantiationRange)
+  : SemaRef(SemaRef),
+    SavedInNonInstantiationSFINAEContext(
+                                        SemaRef.InNonInstantiationSFINAEContext)
+{
+  Invalid = CheckInstantiationDepth(PointOfInstantiation,
+                                    InstantiationRange);
+  if (!Invalid) {
+    ActiveTemplateInstantiation Inst;
+    Inst.Kind = ActiveTemplateInstantiation::TemplateInstantiation;
+    Inst.PointOfInstantiation = PointOfInstantiation;
+    Inst.Entity = reinterpret_cast<uintptr_t>(Entity);
+    Inst.TemplateArgs = 0;
+    Inst.NumTemplateArgs = 0;
+    Inst.InstantiationRange = InstantiationRange;
+    SemaRef.InNonInstantiationSFINAEContext = false;
+    SemaRef.ActiveTemplateInstantiations.push_back(Inst);
+  }
+}
+
+Sema::InstantiatingTemplate::
+InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
+                      FunctionDecl *Entity, ExceptionSpecification,
+                      SourceRange InstantiationRange)
+  : SemaRef(SemaRef),
+    SavedInNonInstantiationSFINAEContext(
+                                        SemaRef.InNonInstantiationSFINAEContext)
+{
+  Invalid = CheckInstantiationDepth(PointOfInstantiation,
+                                    InstantiationRange);
+  if (!Invalid) {
+    ActiveTemplateInstantiation Inst;
+    Inst.Kind = ActiveTemplateInstantiation::ExceptionSpecInstantiation;
+    Inst.PointOfInstantiation = PointOfInstantiation;
+    Inst.Entity = reinterpret_cast<uintptr_t>(Entity);
+    Inst.TemplateArgs = 0;
+    Inst.NumTemplateArgs = 0;
+    Inst.InstantiationRange = InstantiationRange;
+    SemaRef.InNonInstantiationSFINAEContext = false;
+    SemaRef.ActiveTemplateInstantiations.push_back(Inst);
+  }
+}
+
+Sema::InstantiatingTemplate::InstantiatingTemplate(Sema &SemaRef,
+                                         SourceLocation PointOfInstantiation,
+                                         TemplateDecl *Template,
+                                         const TemplateArgument *TemplateArgs,
+                                         unsigned NumTemplateArgs,
+                                         SourceRange InstantiationRange)
+  : SemaRef(SemaRef),
+    SavedInNonInstantiationSFINAEContext(
+                                     SemaRef.InNonInstantiationSFINAEContext)
+{
+  Invalid = CheckInstantiationDepth(PointOfInstantiation,
+                                    InstantiationRange);
+  if (!Invalid) {
+    ActiveTemplateInstantiation Inst;
+    Inst.Kind
+      = ActiveTemplateInstantiation::DefaultTemplateArgumentInstantiation;
+    Inst.PointOfInstantiation = PointOfInstantiation;
+    Inst.Entity = reinterpret_cast<uintptr_t>(Template);
+    Inst.TemplateArgs = TemplateArgs;
+    Inst.NumTemplateArgs = NumTemplateArgs;
+    Inst.InstantiationRange = InstantiationRange;
+    SemaRef.InNonInstantiationSFINAEContext = false;
+    SemaRef.ActiveTemplateInstantiations.push_back(Inst);
+  }
+}
+
+Sema::InstantiatingTemplate::InstantiatingTemplate(Sema &SemaRef,
+                                         SourceLocation PointOfInstantiation,
+                                      FunctionTemplateDecl *FunctionTemplate,
+                                        const TemplateArgument *TemplateArgs,
+                                                   unsigned NumTemplateArgs,
+                         ActiveTemplateInstantiation::InstantiationKind Kind,
+                                   sema::TemplateDeductionInfo &DeductionInfo,
+                                              SourceRange InstantiationRange)
+  : SemaRef(SemaRef),
+    SavedInNonInstantiationSFINAEContext(
+                                     SemaRef.InNonInstantiationSFINAEContext)
+{
+  Invalid = CheckInstantiationDepth(PointOfInstantiation,
+                                    InstantiationRange);
+  if (!Invalid) {
+    ActiveTemplateInstantiation Inst;
+    Inst.Kind = Kind;
+    Inst.PointOfInstantiation = PointOfInstantiation;
+    Inst.Entity = reinterpret_cast<uintptr_t>(FunctionTemplate);
+    Inst.TemplateArgs = TemplateArgs;
+    Inst.NumTemplateArgs = NumTemplateArgs;
+    Inst.DeductionInfo = &DeductionInfo;
+    Inst.InstantiationRange = InstantiationRange;
+    SemaRef.InNonInstantiationSFINAEContext = false;
+    SemaRef.ActiveTemplateInstantiations.push_back(Inst);
+    
+    if (!Inst.isInstantiationRecord())
+      ++SemaRef.NonInstantiationEntries;
+  }
+}
+
+Sema::InstantiatingTemplate::InstantiatingTemplate(Sema &SemaRef,
+                                         SourceLocation PointOfInstantiation,
+                          ClassTemplatePartialSpecializationDecl *PartialSpec,
+                                         const TemplateArgument *TemplateArgs,
+                                         unsigned NumTemplateArgs,
+                                    sema::TemplateDeductionInfo &DeductionInfo,
+                                         SourceRange InstantiationRange)
+  : SemaRef(SemaRef),
+    SavedInNonInstantiationSFINAEContext(
+                                     SemaRef.InNonInstantiationSFINAEContext)
+{
+  Invalid = false;
+    
+  ActiveTemplateInstantiation Inst;
+  Inst.Kind = ActiveTemplateInstantiation::DeducedTemplateArgumentSubstitution;
+  Inst.PointOfInstantiation = PointOfInstantiation;
+  Inst.Entity = reinterpret_cast<uintptr_t>(PartialSpec);
+  Inst.TemplateArgs = TemplateArgs;
+  Inst.NumTemplateArgs = NumTemplateArgs;
+  Inst.DeductionInfo = &DeductionInfo;
+  Inst.InstantiationRange = InstantiationRange;
+  SemaRef.InNonInstantiationSFINAEContext = false;
+  SemaRef.ActiveTemplateInstantiations.push_back(Inst);
+      
+  assert(!Inst.isInstantiationRecord());
+  ++SemaRef.NonInstantiationEntries;
+}
+
+Sema::InstantiatingTemplate::InstantiatingTemplate(Sema &SemaRef,
+                                          SourceLocation PointOfInstantiation,
+                                          ParmVarDecl *Param,
+                                          const TemplateArgument *TemplateArgs,
+                                          unsigned NumTemplateArgs,
+                                          SourceRange InstantiationRange)
+  : SemaRef(SemaRef),
+    SavedInNonInstantiationSFINAEContext(
+                                     SemaRef.InNonInstantiationSFINAEContext)
+{
+  Invalid = CheckInstantiationDepth(PointOfInstantiation, InstantiationRange);
+
+  if (!Invalid) {
+    ActiveTemplateInstantiation Inst;
+    Inst.Kind
+      = ActiveTemplateInstantiation::DefaultFunctionArgumentInstantiation;
+    Inst.PointOfInstantiation = PointOfInstantiation;
+    Inst.Entity = reinterpret_cast<uintptr_t>(Param);
+    Inst.TemplateArgs = TemplateArgs;
+    Inst.NumTemplateArgs = NumTemplateArgs;
+    Inst.InstantiationRange = InstantiationRange;
+    SemaRef.InNonInstantiationSFINAEContext = false;
+    SemaRef.ActiveTemplateInstantiations.push_back(Inst);
+  }
+}
+
+Sema::InstantiatingTemplate::
+InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
+                      NamedDecl *Template,
+                      NonTypeTemplateParmDecl *Param,
+                      const TemplateArgument *TemplateArgs,
+                      unsigned NumTemplateArgs,
+                      SourceRange InstantiationRange) 
+  : SemaRef(SemaRef),
+    SavedInNonInstantiationSFINAEContext(
+                                     SemaRef.InNonInstantiationSFINAEContext)
+{
+  Invalid = false;
+  
+  ActiveTemplateInstantiation Inst;
+  Inst.Kind = ActiveTemplateInstantiation::PriorTemplateArgumentSubstitution;
+  Inst.PointOfInstantiation = PointOfInstantiation;
+  Inst.Template = Template;
+  Inst.Entity = reinterpret_cast<uintptr_t>(Param);
+  Inst.TemplateArgs = TemplateArgs;
+  Inst.NumTemplateArgs = NumTemplateArgs;
+  Inst.InstantiationRange = InstantiationRange;
+  SemaRef.InNonInstantiationSFINAEContext = false;
+  SemaRef.ActiveTemplateInstantiations.push_back(Inst);
+  
+  assert(!Inst.isInstantiationRecord());
+  ++SemaRef.NonInstantiationEntries;
+}
+
+Sema::InstantiatingTemplate::
+InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
+                      NamedDecl *Template,
+                      TemplateTemplateParmDecl *Param,
+                      const TemplateArgument *TemplateArgs,
+                      unsigned NumTemplateArgs,
+                      SourceRange InstantiationRange) 
+  : SemaRef(SemaRef),
+    SavedInNonInstantiationSFINAEContext(
+                                     SemaRef.InNonInstantiationSFINAEContext)
+{
+  Invalid = false;
+  ActiveTemplateInstantiation Inst;
+  Inst.Kind = ActiveTemplateInstantiation::PriorTemplateArgumentSubstitution;
+  Inst.PointOfInstantiation = PointOfInstantiation;
+  Inst.Template = Template;
+  Inst.Entity = reinterpret_cast<uintptr_t>(Param);
+  Inst.TemplateArgs = TemplateArgs;
+  Inst.NumTemplateArgs = NumTemplateArgs;
+  Inst.InstantiationRange = InstantiationRange;
+  SemaRef.InNonInstantiationSFINAEContext = false;
+  SemaRef.ActiveTemplateInstantiations.push_back(Inst);
+  
+  assert(!Inst.isInstantiationRecord());
+  ++SemaRef.NonInstantiationEntries;
+}
+
+Sema::InstantiatingTemplate::
+InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
+                      TemplateDecl *Template,
+                      NamedDecl *Param,
+                      const TemplateArgument *TemplateArgs,
+                      unsigned NumTemplateArgs,
+                      SourceRange InstantiationRange) 
+  : SemaRef(SemaRef),
+    SavedInNonInstantiationSFINAEContext(
+                                     SemaRef.InNonInstantiationSFINAEContext)
+{
+  Invalid = false;
+  
+  ActiveTemplateInstantiation Inst;
+  Inst.Kind = ActiveTemplateInstantiation::DefaultTemplateArgumentChecking;
+  Inst.PointOfInstantiation = PointOfInstantiation;
+  Inst.Template = Template;
+  Inst.Entity = reinterpret_cast<uintptr_t>(Param);
+  Inst.TemplateArgs = TemplateArgs;
+  Inst.NumTemplateArgs = NumTemplateArgs;
+  Inst.InstantiationRange = InstantiationRange;
+  SemaRef.InNonInstantiationSFINAEContext = false;
+  SemaRef.ActiveTemplateInstantiations.push_back(Inst);
+  
+  assert(!Inst.isInstantiationRecord());
+  ++SemaRef.NonInstantiationEntries;
+}
+
+void Sema::InstantiatingTemplate::Clear() {
+  if (!Invalid) {
+    if (!SemaRef.ActiveTemplateInstantiations.back().isInstantiationRecord()) {
+      assert(SemaRef.NonInstantiationEntries > 0);
+      --SemaRef.NonInstantiationEntries;
+    }
+    SemaRef.InNonInstantiationSFINAEContext
+      = SavedInNonInstantiationSFINAEContext;
+    SemaRef.ActiveTemplateInstantiations.pop_back();
+    Invalid = true;
+  }
+}
+
+bool Sema::InstantiatingTemplate::CheckInstantiationDepth(
+                                        SourceLocation PointOfInstantiation,
+                                           SourceRange InstantiationRange) {
+  assert(SemaRef.NonInstantiationEntries <=
+                                   SemaRef.ActiveTemplateInstantiations.size());
+  if ((SemaRef.ActiveTemplateInstantiations.size() - 
+          SemaRef.NonInstantiationEntries)
+        <= SemaRef.getLangOpts().InstantiationDepth)
+    return false;
+
+  SemaRef.Diag(PointOfInstantiation,
+               diag::err_template_recursion_depth_exceeded)
+    << SemaRef.getLangOpts().InstantiationDepth
+    << InstantiationRange;
+  SemaRef.Diag(PointOfInstantiation, diag::note_template_recursion_depth)
+    << SemaRef.getLangOpts().InstantiationDepth;
+  return true;
+}
+
+/// \brief Prints the current instantiation stack through a series of
+/// notes.
+void Sema::PrintInstantiationStack() {
+  // Determine which template instantiations to skip, if any.
+  unsigned SkipStart = ActiveTemplateInstantiations.size(), SkipEnd = SkipStart;
+  unsigned Limit = Diags.getTemplateBacktraceLimit();
+  if (Limit && Limit < ActiveTemplateInstantiations.size()) {
+    SkipStart = Limit / 2 + Limit % 2;
+    SkipEnd = ActiveTemplateInstantiations.size() - Limit / 2;
+  }
+
+  // FIXME: In all of these cases, we need to show the template arguments
+  unsigned InstantiationIdx = 0;
+  for (SmallVector<ActiveTemplateInstantiation, 16>::reverse_iterator
+         Active = ActiveTemplateInstantiations.rbegin(),
+         ActiveEnd = ActiveTemplateInstantiations.rend();
+       Active != ActiveEnd;
+       ++Active, ++InstantiationIdx) {
+    // Skip this instantiation?
+    if (InstantiationIdx >= SkipStart && InstantiationIdx < SkipEnd) {
+      if (InstantiationIdx == SkipStart) {
+        // Note that we're skipping instantiations.
+        Diags.Report(Active->PointOfInstantiation,
+                     diag::note_instantiation_contexts_suppressed)
+          << unsigned(ActiveTemplateInstantiations.size() - Limit);
+      }
+      continue;
+    }
+
+    switch (Active->Kind) {
+    case ActiveTemplateInstantiation::TemplateInstantiation: {
+      Decl *D = reinterpret_cast<Decl *>(Active->Entity);
+      if (CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(D)) {
+        unsigned DiagID = diag::note_template_member_class_here;
+        if (isa<ClassTemplateSpecializationDecl>(Record))
+          DiagID = diag::note_template_class_instantiation_here;
+        Diags.Report(Active->PointOfInstantiation, DiagID)
+          << Context.getTypeDeclType(Record)
+          << Active->InstantiationRange;
+      } else if (FunctionDecl *Function = dyn_cast<FunctionDecl>(D)) {
+        unsigned DiagID;
+        if (Function->getPrimaryTemplate())
+          DiagID = diag::note_function_template_spec_here;
+        else
+          DiagID = diag::note_template_member_function_here;
+        Diags.Report(Active->PointOfInstantiation, DiagID)
+          << Function
+          << Active->InstantiationRange;
+      } else if (VarDecl *VD = dyn_cast<VarDecl>(D)) {
+        Diags.Report(Active->PointOfInstantiation,
+                     diag::note_template_static_data_member_def_here)
+          << VD
+          << Active->InstantiationRange;
+      } else if (EnumDecl *ED = dyn_cast<EnumDecl>(D)) {
+        Diags.Report(Active->PointOfInstantiation,
+                     diag::note_template_enum_def_here)
+          << ED
+          << Active->InstantiationRange;
+      } else {
+        Diags.Report(Active->PointOfInstantiation,
+                     diag::note_template_type_alias_instantiation_here)
+          << cast<TypeAliasTemplateDecl>(D)
+          << Active->InstantiationRange;
+      }
+      break;
+    }
+
+    case ActiveTemplateInstantiation::DefaultTemplateArgumentInstantiation: {
+      TemplateDecl *Template = cast<TemplateDecl>((Decl *)Active->Entity);
+      std::string TemplateArgsStr
+        = TemplateSpecializationType::PrintTemplateArgumentList(
+                                                         Active->TemplateArgs,
+                                                      Active->NumTemplateArgs,
+                                                      getPrintingPolicy());
+      Diags.Report(Active->PointOfInstantiation,
+                   diag::note_default_arg_instantiation_here)
+        << (Template->getNameAsString() + TemplateArgsStr)
+        << Active->InstantiationRange;
+      break;
+    }
+
+    case ActiveTemplateInstantiation::ExplicitTemplateArgumentSubstitution: {
+      FunctionTemplateDecl *FnTmpl
+        = cast<FunctionTemplateDecl>((Decl *)Active->Entity);
+      Diags.Report(Active->PointOfInstantiation,
+                   diag::note_explicit_template_arg_substitution_here)
+        << FnTmpl 
+        << getTemplateArgumentBindingsText(FnTmpl->getTemplateParameters(), 
+                                           Active->TemplateArgs, 
+                                           Active->NumTemplateArgs)
+        << Active->InstantiationRange;
+      break;
+    }
+
+    case ActiveTemplateInstantiation::DeducedTemplateArgumentSubstitution:
+      if (ClassTemplatePartialSpecializationDecl *PartialSpec
+            = dyn_cast<ClassTemplatePartialSpecializationDecl>(
+                                                    (Decl *)Active->Entity)) {
+        Diags.Report(Active->PointOfInstantiation,
+                     diag::note_partial_spec_deduct_instantiation_here)
+          << Context.getTypeDeclType(PartialSpec)
+          << getTemplateArgumentBindingsText(
+                                         PartialSpec->getTemplateParameters(), 
+                                             Active->TemplateArgs, 
+                                             Active->NumTemplateArgs)
+          << Active->InstantiationRange;
+      } else {
+        FunctionTemplateDecl *FnTmpl
+          = cast<FunctionTemplateDecl>((Decl *)Active->Entity);
+        Diags.Report(Active->PointOfInstantiation,
+                     diag::note_function_template_deduction_instantiation_here)
+          << FnTmpl
+          << getTemplateArgumentBindingsText(FnTmpl->getTemplateParameters(), 
+                                             Active->TemplateArgs, 
+                                             Active->NumTemplateArgs)
+          << Active->InstantiationRange;
+      }
+      break;
+
+    case ActiveTemplateInstantiation::DefaultFunctionArgumentInstantiation: {
+      ParmVarDecl *Param = cast<ParmVarDecl>((Decl *)Active->Entity);
+      FunctionDecl *FD = cast<FunctionDecl>(Param->getDeclContext());
+
+      std::string TemplateArgsStr
+        = TemplateSpecializationType::PrintTemplateArgumentList(
+                                                         Active->TemplateArgs,
+                                                      Active->NumTemplateArgs,
+                                                      getPrintingPolicy());
+      Diags.Report(Active->PointOfInstantiation,
+                   diag::note_default_function_arg_instantiation_here)
+        << (FD->getNameAsString() + TemplateArgsStr)
+        << Active->InstantiationRange;
+      break;
+    }
+
+    case ActiveTemplateInstantiation::PriorTemplateArgumentSubstitution: {
+      NamedDecl *Parm = cast<NamedDecl>((Decl *)Active->Entity);
+      std::string Name;
+      if (!Parm->getName().empty())
+        Name = std::string(" '") + Parm->getName().str() + "'";
+                    
+      TemplateParameterList *TemplateParams = 0;
+      if (TemplateDecl *Template = dyn_cast<TemplateDecl>(Active->Template))
+        TemplateParams = Template->getTemplateParameters();
+      else
+        TemplateParams =
+          cast<ClassTemplatePartialSpecializationDecl>(Active->Template)
+                                                      ->getTemplateParameters();
+      Diags.Report(Active->PointOfInstantiation,
+                   diag::note_prior_template_arg_substitution)
+        << isa<TemplateTemplateParmDecl>(Parm)
+        << Name
+        << getTemplateArgumentBindingsText(TemplateParams, 
+                                           Active->TemplateArgs, 
+                                           Active->NumTemplateArgs)
+        << Active->InstantiationRange;
+      break;
+    }
+
+    case ActiveTemplateInstantiation::DefaultTemplateArgumentChecking: {
+      TemplateParameterList *TemplateParams = 0;
+      if (TemplateDecl *Template = dyn_cast<TemplateDecl>(Active->Template))
+        TemplateParams = Template->getTemplateParameters();
+      else
+        TemplateParams =
+          cast<ClassTemplatePartialSpecializationDecl>(Active->Template)
+                                                      ->getTemplateParameters();
+
+      Diags.Report(Active->PointOfInstantiation,
+                   diag::note_template_default_arg_checking)
+        << getTemplateArgumentBindingsText(TemplateParams, 
+                                           Active->TemplateArgs, 
+                                           Active->NumTemplateArgs)
+        << Active->InstantiationRange;
+      break;
+    }
+
+    case ActiveTemplateInstantiation::ExceptionSpecInstantiation:
+      Diags.Report(Active->PointOfInstantiation,
+                   diag::note_template_exception_spec_instantiation_here)
+        << cast<FunctionDecl>((Decl *)Active->Entity)
+        << Active->InstantiationRange;
+      break;
+    }
+  }
+}
+
+llvm::Optional<TemplateDeductionInfo *> Sema::isSFINAEContext() const {
+  if (InNonInstantiationSFINAEContext)
+    return llvm::Optional<TemplateDeductionInfo *>(0);
+
+  for (SmallVector<ActiveTemplateInstantiation, 16>::const_reverse_iterator
+         Active = ActiveTemplateInstantiations.rbegin(),
+         ActiveEnd = ActiveTemplateInstantiations.rend();
+       Active != ActiveEnd;
+       ++Active) 
+  {
+    switch(Active->Kind) {
+    case ActiveTemplateInstantiation::DefaultFunctionArgumentInstantiation:
+    case ActiveTemplateInstantiation::TemplateInstantiation:
+    case ActiveTemplateInstantiation::ExceptionSpecInstantiation:
+      // This is a template instantiation, so there is no SFINAE.
+      return llvm::Optional<TemplateDeductionInfo *>();
+
+    case ActiveTemplateInstantiation::DefaultTemplateArgumentInstantiation:
+    case ActiveTemplateInstantiation::PriorTemplateArgumentSubstitution:
+    case ActiveTemplateInstantiation::DefaultTemplateArgumentChecking:
+      // A default template argument instantiation and substitution into
+      // template parameters with arguments for prior parameters may or may 
+      // not be a SFINAE context; look further up the stack.
+      break;
+
+    case ActiveTemplateInstantiation::ExplicitTemplateArgumentSubstitution:
+    case ActiveTemplateInstantiation::DeducedTemplateArgumentSubstitution:
+      // We're either substitution explicitly-specified template arguments
+      // or deduced template arguments, so SFINAE applies.
+      assert(Active->DeductionInfo && "Missing deduction info pointer");
+      return Active->DeductionInfo;
+    }
+  }
+
+  return llvm::Optional<TemplateDeductionInfo *>();
+}
+
+/// \brief Retrieve the depth and index of a parameter pack.
+static std::pair<unsigned, unsigned> 
+getDepthAndIndex(NamedDecl *ND) {
+  if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(ND))
+    return std::make_pair(TTP->getDepth(), TTP->getIndex());
+  
+  if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(ND))
+    return std::make_pair(NTTP->getDepth(), NTTP->getIndex());
+  
+  TemplateTemplateParmDecl *TTP = cast<TemplateTemplateParmDecl>(ND);
+  return std::make_pair(TTP->getDepth(), TTP->getIndex());
+}
+
+//===----------------------------------------------------------------------===/
+// Template Instantiation for Types
+//===----------------------------------------------------------------------===/
+namespace {
+  class TemplateInstantiator : public TreeTransform<TemplateInstantiator> {
+    const MultiLevelTemplateArgumentList &TemplateArgs;
+    SourceLocation Loc;
+    DeclarationName Entity;
+
+  public:
+    typedef TreeTransform<TemplateInstantiator> inherited;
+
+    TemplateInstantiator(Sema &SemaRef,
+                         const MultiLevelTemplateArgumentList &TemplateArgs,
+                         SourceLocation Loc,
+                         DeclarationName Entity)
+      : inherited(SemaRef), TemplateArgs(TemplateArgs), Loc(Loc),
+        Entity(Entity) { }
+
+    /// \brief Determine whether the given type \p T has already been
+    /// transformed.
+    ///
+    /// For the purposes of template instantiation, a type has already been
+    /// transformed if it is NULL or if it is not dependent.
+    bool AlreadyTransformed(QualType T);
+
+    /// \brief Returns the location of the entity being instantiated, if known.
+    SourceLocation getBaseLocation() { return Loc; }
+
+    /// \brief Returns the name of the entity being instantiated, if any.
+    DeclarationName getBaseEntity() { return Entity; }
+
+    /// \brief Sets the "base" location and entity when that
+    /// information is known based on another transformation.
+    void setBase(SourceLocation Loc, DeclarationName Entity) {
+      this->Loc = Loc;
+      this->Entity = Entity;
+    }
+
+    bool TryExpandParameterPacks(SourceLocation EllipsisLoc,
+                                 SourceRange PatternRange,
+                             llvm::ArrayRef<UnexpandedParameterPack> Unexpanded,
+                                 bool &ShouldExpand,
+                                 bool &RetainExpansion,
+                                 llvm::Optional<unsigned> &NumExpansions) {
+      return getSema().CheckParameterPacksForExpansion(EllipsisLoc, 
+                                                       PatternRange, Unexpanded,
+                                                       TemplateArgs, 
+                                                       ShouldExpand,
+                                                       RetainExpansion,
+                                                       NumExpansions);
+    }
+
+    void ExpandingFunctionParameterPack(ParmVarDecl *Pack) { 
+      SemaRef.CurrentInstantiationScope->MakeInstantiatedLocalArgPack(Pack);
+    }
+    
+    TemplateArgument ForgetPartiallySubstitutedPack() {
+      TemplateArgument Result;
+      if (NamedDecl *PartialPack
+            = SemaRef.CurrentInstantiationScope->getPartiallySubstitutedPack()){
+        MultiLevelTemplateArgumentList &TemplateArgs
+          = const_cast<MultiLevelTemplateArgumentList &>(this->TemplateArgs);
+        unsigned Depth, Index;
+        llvm::tie(Depth, Index) = getDepthAndIndex(PartialPack);
+        if (TemplateArgs.hasTemplateArgument(Depth, Index)) {
+          Result = TemplateArgs(Depth, Index);
+          TemplateArgs.setArgument(Depth, Index, TemplateArgument());
+        }
+      }
+      
+      return Result;
+    }
+    
+    void RememberPartiallySubstitutedPack(TemplateArgument Arg) {
+      if (Arg.isNull())
+        return;
+      
+      if (NamedDecl *PartialPack
+            = SemaRef.CurrentInstantiationScope->getPartiallySubstitutedPack()){
+        MultiLevelTemplateArgumentList &TemplateArgs
+        = const_cast<MultiLevelTemplateArgumentList &>(this->TemplateArgs);
+        unsigned Depth, Index;
+        llvm::tie(Depth, Index) = getDepthAndIndex(PartialPack);
+        TemplateArgs.setArgument(Depth, Index, Arg);
+      }
+    }
+
+    /// \brief Transform the given declaration by instantiating a reference to
+    /// this declaration.
+    Decl *TransformDecl(SourceLocation Loc, Decl *D);
+
+    void transformAttrs(Decl *Old, Decl *New) { 
+      SemaRef.InstantiateAttrs(TemplateArgs, Old, New);
+    }
+
+    void transformedLocalDecl(Decl *Old, Decl *New) {
+      SemaRef.CurrentInstantiationScope->InstantiatedLocal(Old, New);
+    }
+    
+    /// \brief Transform the definition of the given declaration by
+    /// instantiating it.
+    Decl *TransformDefinition(SourceLocation Loc, Decl *D);
+
+    /// \bried Transform the first qualifier within a scope by instantiating the
+    /// declaration.
+    NamedDecl *TransformFirstQualifierInScope(NamedDecl *D, SourceLocation Loc);
+      
+    /// \brief Rebuild the exception declaration and register the declaration
+    /// as an instantiated local.
+    VarDecl *RebuildExceptionDecl(VarDecl *ExceptionDecl, 
+                                  TypeSourceInfo *Declarator,
+                                  SourceLocation StartLoc,
+                                  SourceLocation NameLoc,
+                                  IdentifierInfo *Name);
+
+    /// \brief Rebuild the Objective-C exception declaration and register the 
+    /// declaration as an instantiated local.
+    VarDecl *RebuildObjCExceptionDecl(VarDecl *ExceptionDecl, 
+                                      TypeSourceInfo *TSInfo, QualType T);
+      
+    /// \brief Check for tag mismatches when instantiating an
+    /// elaborated type.
+    QualType RebuildElaboratedType(SourceLocation KeywordLoc,
+                                   ElaboratedTypeKeyword Keyword,
+                                   NestedNameSpecifierLoc QualifierLoc,
+                                   QualType T);
+
+    TemplateName TransformTemplateName(CXXScopeSpec &SS,
+                                       TemplateName Name,
+                                       SourceLocation NameLoc,                                     
+                                       QualType ObjectType = QualType(),
+                                       NamedDecl *FirstQualifierInScope = 0);
+
+    ExprResult TransformPredefinedExpr(PredefinedExpr *E);
+    ExprResult TransformDeclRefExpr(DeclRefExpr *E);
+    ExprResult TransformCXXDefaultArgExpr(CXXDefaultArgExpr *E);
+    ExprResult TransformTemplateParmRefExpr(DeclRefExpr *E,
+                                            NonTypeTemplateParmDecl *D);
+    ExprResult TransformSubstNonTypeTemplateParmPackExpr(
+                                           SubstNonTypeTemplateParmPackExpr *E);
+    
+    QualType TransformFunctionProtoType(TypeLocBuilder &TLB,
+                                        FunctionProtoTypeLoc TL);
+    QualType TransformFunctionProtoType(TypeLocBuilder &TLB,
+                                        FunctionProtoTypeLoc TL,
+                                        CXXRecordDecl *ThisContext,
+                                        unsigned ThisTypeQuals);
+
+    ParmVarDecl *TransformFunctionTypeParam(ParmVarDecl *OldParm,
+                                            int indexAdjustment,
+                                        llvm::Optional<unsigned> NumExpansions,
+                                            bool ExpectParameterPack);
+
+    /// \brief Transforms a template type parameter type by performing
+    /// substitution of the corresponding template type argument.
+    QualType TransformTemplateTypeParmType(TypeLocBuilder &TLB,
+                                           TemplateTypeParmTypeLoc TL);
+
+    /// \brief Transforms an already-substituted template type parameter pack
+    /// into either itself (if we aren't substituting into its pack expansion)
+    /// or the appropriate substituted argument.
+    QualType TransformSubstTemplateTypeParmPackType(TypeLocBuilder &TLB,
+                                           SubstTemplateTypeParmPackTypeLoc TL);
+
+    ExprResult TransformCallExpr(CallExpr *CE) {
+      getSema().CallsUndergoingInstantiation.push_back(CE);
+      ExprResult Result =
+          TreeTransform<TemplateInstantiator>::TransformCallExpr(CE);
+      getSema().CallsUndergoingInstantiation.pop_back();
+      return move(Result);
+    }
+
+  private:
+    ExprResult transformNonTypeTemplateParmRef(NonTypeTemplateParmDecl *parm,
+                                               SourceLocation loc,
+                                               const TemplateArgument &arg);
+  };
+}
+
+bool TemplateInstantiator::AlreadyTransformed(QualType T) {
+  if (T.isNull())
+    return true;
+  
+  if (T->isInstantiationDependentType() || T->isVariablyModifiedType())
+    return false;
+  
+  getSema().MarkDeclarationsReferencedInType(Loc, T);
+  return true;
+}
+
+Decl *TemplateInstantiator::TransformDecl(SourceLocation Loc, Decl *D) {
+  if (!D)
+    return 0;
+
+  if (TemplateTemplateParmDecl *TTP = dyn_cast<TemplateTemplateParmDecl>(D)) {
+    if (TTP->getDepth() < TemplateArgs.getNumLevels()) {
+      // If the corresponding template argument is NULL or non-existent, it's
+      // because we are performing instantiation from explicitly-specified
+      // template arguments in a function template, but there were some
+      // arguments left unspecified.
+      if (!TemplateArgs.hasTemplateArgument(TTP->getDepth(),
+                                            TTP->getPosition()))
+        return D;
+
+      TemplateArgument Arg = TemplateArgs(TTP->getDepth(), TTP->getPosition());
+      
+      if (TTP->isParameterPack()) {
+        assert(Arg.getKind() == TemplateArgument::Pack && 
+               "Missing argument pack");
+        
+        assert(getSema().ArgumentPackSubstitutionIndex >= 0);        
+        assert(getSema().ArgumentPackSubstitutionIndex < (int)Arg.pack_size());
+        Arg = Arg.pack_begin()[getSema().ArgumentPackSubstitutionIndex];
+      }
+
+      TemplateName Template = Arg.getAsTemplate();
+      assert(!Template.isNull() && Template.getAsTemplateDecl() &&
+             "Wrong kind of template template argument");
+      return Template.getAsTemplateDecl();
+    }
+
+    // Fall through to find the instantiated declaration for this template
+    // template parameter.
+  }
+
+  return SemaRef.FindInstantiatedDecl(Loc, cast<NamedDecl>(D), TemplateArgs);
+}
+
+Decl *TemplateInstantiator::TransformDefinition(SourceLocation Loc, Decl *D) {
+  Decl *Inst = getSema().SubstDecl(D, getSema().CurContext, TemplateArgs);
+  if (!Inst)
+    return 0;
+
+  getSema().CurrentInstantiationScope->InstantiatedLocal(D, Inst);
+  return Inst;
+}
+
+NamedDecl *
+TemplateInstantiator::TransformFirstQualifierInScope(NamedDecl *D, 
+                                                     SourceLocation Loc) {
+  // If the first part of the nested-name-specifier was a template type 
+  // parameter, instantiate that type parameter down to a tag type.
+  if (TemplateTypeParmDecl *TTPD = dyn_cast_or_null<TemplateTypeParmDecl>(D)) {
+    const TemplateTypeParmType *TTP 
+      = cast<TemplateTypeParmType>(getSema().Context.getTypeDeclType(TTPD));
+    
+    if (TTP->getDepth() < TemplateArgs.getNumLevels()) {
+      // FIXME: This needs testing w/ member access expressions.
+      TemplateArgument Arg = TemplateArgs(TTP->getDepth(), TTP->getIndex());
+      
+      if (TTP->isParameterPack()) {
+        assert(Arg.getKind() == TemplateArgument::Pack && 
+               "Missing argument pack");
+        
+        if (getSema().ArgumentPackSubstitutionIndex == -1)
+          return 0;
+        
+        assert(getSema().ArgumentPackSubstitutionIndex < (int)Arg.pack_size());
+        Arg = Arg.pack_begin()[getSema().ArgumentPackSubstitutionIndex];
+      }
+
+      QualType T = Arg.getAsType();
+      if (T.isNull())
+        return cast_or_null<NamedDecl>(TransformDecl(Loc, D));
+      
+      if (const TagType *Tag = T->getAs<TagType>())
+        return Tag->getDecl();
+      
+      // The resulting type is not a tag; complain.
+      getSema().Diag(Loc, diag::err_nested_name_spec_non_tag) << T;
+      return 0;
+    }
+  }
+  
+  return cast_or_null<NamedDecl>(TransformDecl(Loc, D));
+}
+
+VarDecl *
+TemplateInstantiator::RebuildExceptionDecl(VarDecl *ExceptionDecl,
+                                           TypeSourceInfo *Declarator,
+                                           SourceLocation StartLoc,
+                                           SourceLocation NameLoc,
+                                           IdentifierInfo *Name) {
+  VarDecl *Var = inherited::RebuildExceptionDecl(ExceptionDecl, Declarator,
+                                                 StartLoc, NameLoc, Name);
+  if (Var)
+    getSema().CurrentInstantiationScope->InstantiatedLocal(ExceptionDecl, Var);
+  return Var;
+}
+
+VarDecl *TemplateInstantiator::RebuildObjCExceptionDecl(VarDecl *ExceptionDecl, 
+                                                        TypeSourceInfo *TSInfo, 
+                                                        QualType T) {
+  VarDecl *Var = inherited::RebuildObjCExceptionDecl(ExceptionDecl, TSInfo, T);
+  if (Var)
+    getSema().CurrentInstantiationScope->InstantiatedLocal(ExceptionDecl, Var);
+  return Var;
+}
+
+QualType
+TemplateInstantiator::RebuildElaboratedType(SourceLocation KeywordLoc,
+                                            ElaboratedTypeKeyword Keyword,
+                                            NestedNameSpecifierLoc QualifierLoc,
+                                            QualType T) {
+  if (const TagType *TT = T->getAs<TagType>()) {
+    TagDecl* TD = TT->getDecl();
+
+    SourceLocation TagLocation = KeywordLoc;
+
+    // FIXME: type might be anonymous.
+    IdentifierInfo *Id = TD->getIdentifier();
+
+    // TODO: should we even warn on struct/class mismatches for this?  Seems
+    // like it's likely to produce a lot of spurious errors.
+    if (Keyword != ETK_None && Keyword != ETK_Typename) {
+      TagTypeKind Kind = TypeWithKeyword::getTagTypeKindForKeyword(Keyword);
+      if (!SemaRef.isAcceptableTagRedeclaration(TD, Kind, /*isDefinition*/false,
+                                                TagLocation, *Id)) {
+        SemaRef.Diag(TagLocation, diag::err_use_with_wrong_tag)
+          << Id
+          << FixItHint::CreateReplacement(SourceRange(TagLocation),
+                                          TD->getKindName());
+        SemaRef.Diag(TD->getLocation(), diag::note_previous_use);
+      }
+    }
+  }
+
+  return TreeTransform<TemplateInstantiator>::RebuildElaboratedType(KeywordLoc,
+                                                                    Keyword,
+                                                                  QualifierLoc,
+                                                                    T);
+}
+
+TemplateName TemplateInstantiator::TransformTemplateName(CXXScopeSpec &SS,
+                                                         TemplateName Name,
+                                                         SourceLocation NameLoc,                                     
+                                                         QualType ObjectType,
+                                             NamedDecl *FirstQualifierInScope) {
+  if (TemplateTemplateParmDecl *TTP
+       = dyn_cast_or_null<TemplateTemplateParmDecl>(Name.getAsTemplateDecl())) {
+    if (TTP->getDepth() < TemplateArgs.getNumLevels()) {
+      // If the corresponding template argument is NULL or non-existent, it's
+      // because we are performing instantiation from explicitly-specified
+      // template arguments in a function template, but there were some
+      // arguments left unspecified.
+      if (!TemplateArgs.hasTemplateArgument(TTP->getDepth(),
+                                            TTP->getPosition()))
+        return Name;
+      
+      TemplateArgument Arg = TemplateArgs(TTP->getDepth(), TTP->getPosition());
+      
+      if (TTP->isParameterPack()) {
+        assert(Arg.getKind() == TemplateArgument::Pack && 
+               "Missing argument pack");
+        
+        if (getSema().ArgumentPackSubstitutionIndex == -1) {
+          // We have the template argument pack to substitute, but we're not
+          // actually expanding the enclosing pack expansion yet. So, just
+          // keep the entire argument pack.
+          return getSema().Context.getSubstTemplateTemplateParmPack(TTP, Arg);
+        }
+        
+        assert(getSema().ArgumentPackSubstitutionIndex < (int)Arg.pack_size());
+        Arg = Arg.pack_begin()[getSema().ArgumentPackSubstitutionIndex];
+      }
+      
+      TemplateName Template = Arg.getAsTemplate();
+      assert(!Template.isNull() && "Null template template argument");
+
+      // We don't ever want to substitute for a qualified template name, since
+      // the qualifier is handled separately. So, look through the qualified
+      // template name to its underlying declaration.
+      if (QualifiedTemplateName *QTN = Template.getAsQualifiedTemplateName())
+        Template = TemplateName(QTN->getTemplateDecl());
+
+      Template = getSema().Context.getSubstTemplateTemplateParm(TTP, Template);
+      return Template;
+    }
+  }
+  
+  if (SubstTemplateTemplateParmPackStorage *SubstPack
+      = Name.getAsSubstTemplateTemplateParmPack()) {
+    if (getSema().ArgumentPackSubstitutionIndex == -1)
+      return Name;
+    
+    const TemplateArgument &ArgPack = SubstPack->getArgumentPack();
+    assert(getSema().ArgumentPackSubstitutionIndex < (int)ArgPack.pack_size() &&
+           "Pack substitution index out-of-range");
+    return ArgPack.pack_begin()[getSema().ArgumentPackSubstitutionIndex]
+    .getAsTemplate();
+  }
+  
+  return inherited::TransformTemplateName(SS, Name, NameLoc, ObjectType, 
+                                          FirstQualifierInScope);  
+}
+
+ExprResult 
+TemplateInstantiator::TransformPredefinedExpr(PredefinedExpr *E) {
+  if (!E->isTypeDependent())
+    return SemaRef.Owned(E);
+
+  FunctionDecl *currentDecl = getSema().getCurFunctionDecl();
+  assert(currentDecl && "Must have current function declaration when "
+                        "instantiating.");
+
+  PredefinedExpr::IdentType IT = E->getIdentType();
+
+  unsigned Length = PredefinedExpr::ComputeName(IT, currentDecl).length();
+
+  llvm::APInt LengthI(32, Length + 1);
+  QualType ResTy = getSema().Context.CharTy.withConst();
+  ResTy = getSema().Context.getConstantArrayType(ResTy, LengthI, 
+                                                 ArrayType::Normal, 0);
+  PredefinedExpr *PE =
+    new (getSema().Context) PredefinedExpr(E->getLocation(), ResTy, IT);
+  return getSema().Owned(PE);
+}
+
+ExprResult
+TemplateInstantiator::TransformTemplateParmRefExpr(DeclRefExpr *E,
+                                               NonTypeTemplateParmDecl *NTTP) {
+  // If the corresponding template argument is NULL or non-existent, it's
+  // because we are performing instantiation from explicitly-specified
+  // template arguments in a function template, but there were some
+  // arguments left unspecified.
+  if (!TemplateArgs.hasTemplateArgument(NTTP->getDepth(),
+                                        NTTP->getPosition()))
+    return SemaRef.Owned(E);
+
+  TemplateArgument Arg = TemplateArgs(NTTP->getDepth(), NTTP->getPosition());
+  if (NTTP->isParameterPack()) {
+    assert(Arg.getKind() == TemplateArgument::Pack && 
+           "Missing argument pack");
+    
+    if (getSema().ArgumentPackSubstitutionIndex == -1) {
+      // We have an argument pack, but we can't select a particular argument
+      // out of it yet. Therefore, we'll build an expression to hold on to that
+      // argument pack.
+      QualType TargetType = SemaRef.SubstType(NTTP->getType(), TemplateArgs,
+                                              E->getLocation(), 
+                                              NTTP->getDeclName());
+      if (TargetType.isNull())
+        return ExprError();
+      
+      return new (SemaRef.Context) SubstNonTypeTemplateParmPackExpr(TargetType,
+                                                                    NTTP, 
+                                                              E->getLocation(),
+                                                                    Arg);
+    }
+    
+    assert(getSema().ArgumentPackSubstitutionIndex < (int)Arg.pack_size());
+    Arg = Arg.pack_begin()[getSema().ArgumentPackSubstitutionIndex];
+  }
+
+  return transformNonTypeTemplateParmRef(NTTP, E->getLocation(), Arg);
+}
+
+ExprResult TemplateInstantiator::transformNonTypeTemplateParmRef(
+                                                 NonTypeTemplateParmDecl *parm,
+                                                 SourceLocation loc,
+                                                 const TemplateArgument &arg) {
+  ExprResult result;
+  QualType type;
+
+  // The template argument itself might be an expression, in which
+  // case we just return that expression.
+  if (arg.getKind() == TemplateArgument::Expression) {
+    Expr *argExpr = arg.getAsExpr();
+    result = SemaRef.Owned(argExpr);
+    type = argExpr->getType();
+
+  } else if (arg.getKind() == TemplateArgument::Declaration) {
+    ValueDecl *VD;
+    if (Decl *D = arg.getAsDecl()) {
+      VD = cast<ValueDecl>(D);
+
+      // Find the instantiation of the template argument.  This is
+      // required for nested templates.
+      VD = cast_or_null<ValueDecl>(
+             getSema().FindInstantiatedDecl(loc, VD, TemplateArgs));
+      if (!VD)
+        return ExprError();
+    } else {
+      // Propagate NULL template argument.
+      VD = 0;
+    }
+    
+    // Derive the type we want the substituted decl to have.  This had
+    // better be non-dependent, or these checks will have serious problems.
+    if (parm->isExpandedParameterPack()) {
+      type = parm->getExpansionType(SemaRef.ArgumentPackSubstitutionIndex);
+    } else if (parm->isParameterPack() && 
+               isa<PackExpansionType>(parm->getType())) {
+      type = SemaRef.SubstType(
+                        cast<PackExpansionType>(parm->getType())->getPattern(),
+                                     TemplateArgs, loc, parm->getDeclName());
+    } else {
+      type = SemaRef.SubstType(parm->getType(), TemplateArgs, 
+                               loc, parm->getDeclName());
+    }
+    assert(!type.isNull() && "type substitution failed for param type");
+    assert(!type->isDependentType() && "param type still dependent");
+    result = SemaRef.BuildExpressionFromDeclTemplateArgument(arg, type, loc);
+
+    if (!result.isInvalid()) type = result.get()->getType();
+  } else {
+    result = SemaRef.BuildExpressionFromIntegralTemplateArgument(arg, loc);
+
+    // Note that this type can be different from the type of 'result',
+    // e.g. if it's an enum type.
+    type = arg.getIntegralType();
+  }
+  if (result.isInvalid()) return ExprError();
+
+  Expr *resultExpr = result.take();
+  return SemaRef.Owned(new (SemaRef.Context)
+                SubstNonTypeTemplateParmExpr(type,
+                                             resultExpr->getValueKind(),
+                                             loc, parm, resultExpr));
+}
+                                                   
+ExprResult 
+TemplateInstantiator::TransformSubstNonTypeTemplateParmPackExpr(
+                                          SubstNonTypeTemplateParmPackExpr *E) {
+  if (getSema().ArgumentPackSubstitutionIndex == -1) {
+    // We aren't expanding the parameter pack, so just return ourselves.
+    return getSema().Owned(E);
+  }
+  
+  const TemplateArgument &ArgPack = E->getArgumentPack();
+  unsigned Index = (unsigned)getSema().ArgumentPackSubstitutionIndex;
+  assert(Index < ArgPack.pack_size() && "Substitution index out-of-range");
+  
+  const TemplateArgument &Arg = ArgPack.pack_begin()[Index];
+  return transformNonTypeTemplateParmRef(E->getParameterPack(),
+                                         E->getParameterPackLocation(),
+                                         Arg);
+}
+
+ExprResult
+TemplateInstantiator::TransformDeclRefExpr(DeclRefExpr *E) {
+  NamedDecl *D = E->getDecl();
+  if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(D)) {
+    if (NTTP->getDepth() < TemplateArgs.getNumLevels())
+      return TransformTemplateParmRefExpr(E, NTTP);
+    
+    // We have a non-type template parameter that isn't fully substituted;
+    // FindInstantiatedDecl will find it in the local instantiation scope.
+  }
+
+  return TreeTransform<TemplateInstantiator>::TransformDeclRefExpr(E);
+}
+
+ExprResult TemplateInstantiator::TransformCXXDefaultArgExpr(
+    CXXDefaultArgExpr *E) {
+  assert(!cast<FunctionDecl>(E->getParam()->getDeclContext())->
+             getDescribedFunctionTemplate() &&
+         "Default arg expressions are never formed in dependent cases.");
+  return SemaRef.BuildCXXDefaultArgExpr(E->getUsedLocation(),
+                           cast<FunctionDecl>(E->getParam()->getDeclContext()), 
+                                        E->getParam());
+}
+
+QualType TemplateInstantiator::TransformFunctionProtoType(TypeLocBuilder &TLB,
+                                                      FunctionProtoTypeLoc TL) {
+  // We need a local instantiation scope for this function prototype.
+  LocalInstantiationScope Scope(SemaRef, /*CombineWithOuterScope=*/true);
+  return inherited::TransformFunctionProtoType(TLB, TL);
+}
+
+QualType TemplateInstantiator::TransformFunctionProtoType(TypeLocBuilder &TLB,
+                                 FunctionProtoTypeLoc TL,
+                                 CXXRecordDecl *ThisContext,
+                                 unsigned ThisTypeQuals) {
+  // We need a local instantiation scope for this function prototype.
+  LocalInstantiationScope Scope(SemaRef, /*CombineWithOuterScope=*/true);
+  return inherited::TransformFunctionProtoType(TLB, TL, ThisContext, 
+                                               ThisTypeQuals);  
+}
+
+ParmVarDecl *
+TemplateInstantiator::TransformFunctionTypeParam(ParmVarDecl *OldParm,
+                                                 int indexAdjustment,
+                                       llvm::Optional<unsigned> NumExpansions,
+                                                 bool ExpectParameterPack) {
+  return SemaRef.SubstParmVarDecl(OldParm, TemplateArgs, indexAdjustment,
+                                  NumExpansions, ExpectParameterPack);
+}
+
+QualType
+TemplateInstantiator::TransformTemplateTypeParmType(TypeLocBuilder &TLB,
+                                                TemplateTypeParmTypeLoc TL) {
+  const TemplateTypeParmType *T = TL.getTypePtr();
+  if (T->getDepth() < TemplateArgs.getNumLevels()) {
+    // Replace the template type parameter with its corresponding
+    // template argument.
+
+    // If the corresponding template argument is NULL or doesn't exist, it's
+    // because we are performing instantiation from explicitly-specified
+    // template arguments in a function template class, but there were some
+    // arguments left unspecified.
+    if (!TemplateArgs.hasTemplateArgument(T->getDepth(), T->getIndex())) {
+      TemplateTypeParmTypeLoc NewTL
+        = TLB.push<TemplateTypeParmTypeLoc>(TL.getType());
+      NewTL.setNameLoc(TL.getNameLoc());
+      return TL.getType();
+    }
+
+    TemplateArgument Arg = TemplateArgs(T->getDepth(), T->getIndex());
+    
+    if (T->isParameterPack()) {
+      assert(Arg.getKind() == TemplateArgument::Pack && 
+             "Missing argument pack");
+      
+      if (getSema().ArgumentPackSubstitutionIndex == -1) {
+        // We have the template argument pack, but we're not expanding the
+        // enclosing pack expansion yet. Just save the template argument
+        // pack for later substitution.
+        QualType Result
+          = getSema().Context.getSubstTemplateTypeParmPackType(T, Arg);
+        SubstTemplateTypeParmPackTypeLoc NewTL
+          = TLB.push<SubstTemplateTypeParmPackTypeLoc>(Result);
+        NewTL.setNameLoc(TL.getNameLoc());
+        return Result;
+      }
+      
+      assert(getSema().ArgumentPackSubstitutionIndex < (int)Arg.pack_size());
+      Arg = Arg.pack_begin()[getSema().ArgumentPackSubstitutionIndex];
+    }
+    
+    assert(Arg.getKind() == TemplateArgument::Type &&
+           "Template argument kind mismatch");
+
+    QualType Replacement = Arg.getAsType();
+
+    // TODO: only do this uniquing once, at the start of instantiation.
+    QualType Result
+      = getSema().Context.getSubstTemplateTypeParmType(T, Replacement);
+    SubstTemplateTypeParmTypeLoc NewTL
+      = TLB.push<SubstTemplateTypeParmTypeLoc>(Result);
+    NewTL.setNameLoc(TL.getNameLoc());
+    return Result;
+  }
+
+  // The template type parameter comes from an inner template (e.g.,
+  // the template parameter list of a member template inside the
+  // template we are instantiating). Create a new template type
+  // parameter with the template "level" reduced by one.
+  TemplateTypeParmDecl *NewTTPDecl = 0;
+  if (TemplateTypeParmDecl *OldTTPDecl = T->getDecl())
+    NewTTPDecl = cast_or_null<TemplateTypeParmDecl>(
+                                  TransformDecl(TL.getNameLoc(), OldTTPDecl));
+
+  QualType Result
+    = getSema().Context.getTemplateTypeParmType(T->getDepth()
+                                                 - TemplateArgs.getNumLevels(),
+                                                T->getIndex(),
+                                                T->isParameterPack(),
+                                                NewTTPDecl);
+  TemplateTypeParmTypeLoc NewTL = TLB.push<TemplateTypeParmTypeLoc>(Result);
+  NewTL.setNameLoc(TL.getNameLoc());
+  return Result;
+}
+
+QualType 
+TemplateInstantiator::TransformSubstTemplateTypeParmPackType(
+                                                            TypeLocBuilder &TLB,
+                                         SubstTemplateTypeParmPackTypeLoc TL) {
+  if (getSema().ArgumentPackSubstitutionIndex == -1) {
+    // We aren't expanding the parameter pack, so just return ourselves.
+    SubstTemplateTypeParmPackTypeLoc NewTL
+      = TLB.push<SubstTemplateTypeParmPackTypeLoc>(TL.getType());
+    NewTL.setNameLoc(TL.getNameLoc());
+    return TL.getType();
+  }
+  
+  const TemplateArgument &ArgPack = TL.getTypePtr()->getArgumentPack();
+  unsigned Index = (unsigned)getSema().ArgumentPackSubstitutionIndex;
+  assert(Index < ArgPack.pack_size() && "Substitution index out-of-range");
+  
+  QualType Result = ArgPack.pack_begin()[Index].getAsType();
+  Result = getSema().Context.getSubstTemplateTypeParmType(
+                                      TL.getTypePtr()->getReplacedParameter(),
+                                                          Result);
+  SubstTemplateTypeParmTypeLoc NewTL
+    = TLB.push<SubstTemplateTypeParmTypeLoc>(Result);
+  NewTL.setNameLoc(TL.getNameLoc());
+  return Result;
+}
+
+/// \brief Perform substitution on the type T with a given set of template
+/// arguments.
+///
+/// This routine substitutes the given template arguments into the
+/// type T and produces the instantiated type.
+///
+/// \param T the type into which the template arguments will be
+/// substituted. If this type is not dependent, it will be returned
+/// immediately.
+///
+/// \param TemplateArgs the template arguments that will be
+/// substituted for the top-level template parameters within T.
+///
+/// \param Loc the location in the source code where this substitution
+/// is being performed. It will typically be the location of the
+/// declarator (if we're instantiating the type of some declaration)
+/// or the location of the type in the source code (if, e.g., we're
+/// instantiating the type of a cast expression).
+///
+/// \param Entity the name of the entity associated with a declaration
+/// being instantiated (if any). May be empty to indicate that there
+/// is no such entity (if, e.g., this is a type that occurs as part of
+/// a cast expression) or that the entity has no name (e.g., an
+/// unnamed function parameter).
+///
+/// \returns If the instantiation succeeds, the instantiated
+/// type. Otherwise, produces diagnostics and returns a NULL type.
+TypeSourceInfo *Sema::SubstType(TypeSourceInfo *T,
+                                const MultiLevelTemplateArgumentList &Args,
+                                SourceLocation Loc,
+                                DeclarationName Entity) {
+  assert(!ActiveTemplateInstantiations.empty() &&
+         "Cannot perform an instantiation without some context on the "
+         "instantiation stack");
+  
+  if (!T->getType()->isInstantiationDependentType() && 
+      !T->getType()->isVariablyModifiedType())
+    return T;
+
+  TemplateInstantiator Instantiator(*this, Args, Loc, Entity);
+  return Instantiator.TransformType(T);
+}
+
+TypeSourceInfo *Sema::SubstType(TypeLoc TL,
+                                const MultiLevelTemplateArgumentList &Args,
+                                SourceLocation Loc,
+                                DeclarationName Entity) {
+  assert(!ActiveTemplateInstantiations.empty() &&
+         "Cannot perform an instantiation without some context on the "
+         "instantiation stack");
+  
+  if (TL.getType().isNull())
+    return 0;
+
+  if (!TL.getType()->isInstantiationDependentType() && 
+      !TL.getType()->isVariablyModifiedType()) {
+    // FIXME: Make a copy of the TypeLoc data here, so that we can
+    // return a new TypeSourceInfo. Inefficient!
+    TypeLocBuilder TLB;
+    TLB.pushFullCopy(TL);
+    return TLB.getTypeSourceInfo(Context, TL.getType());
+  }
+
+  TemplateInstantiator Instantiator(*this, Args, Loc, Entity);
+  TypeLocBuilder TLB;
+  TLB.reserve(TL.getFullDataSize());
+  QualType Result = Instantiator.TransformType(TLB, TL);
+  if (Result.isNull())
+    return 0;
+
+  return TLB.getTypeSourceInfo(Context, Result);
+}
+
+/// Deprecated form of the above.
+QualType Sema::SubstType(QualType T,
+                         const MultiLevelTemplateArgumentList &TemplateArgs,
+                         SourceLocation Loc, DeclarationName Entity) {
+  assert(!ActiveTemplateInstantiations.empty() &&
+         "Cannot perform an instantiation without some context on the "
+         "instantiation stack");
+
+  // If T is not a dependent type or a variably-modified type, there
+  // is nothing to do.
+  if (!T->isInstantiationDependentType() && !T->isVariablyModifiedType())
+    return T;
+
+  TemplateInstantiator Instantiator(*this, TemplateArgs, Loc, Entity);
+  return Instantiator.TransformType(T);
+}
+
+static bool NeedsInstantiationAsFunctionType(TypeSourceInfo *T) {
+  if (T->getType()->isInstantiationDependentType() || 
+      T->getType()->isVariablyModifiedType())
+    return true;
+
+  TypeLoc TL = T->getTypeLoc().IgnoreParens();
+  if (!isa<FunctionProtoTypeLoc>(TL))
+    return false;
+
+  FunctionProtoTypeLoc FP = cast<FunctionProtoTypeLoc>(TL);
+  for (unsigned I = 0, E = FP.getNumArgs(); I != E; ++I) {
+    ParmVarDecl *P = FP.getArg(I);
+
+    // The parameter's type as written might be dependent even if the
+    // decayed type was not dependent.
+    if (TypeSourceInfo *TSInfo = P->getTypeSourceInfo())
+      if (TSInfo->getType()->isInstantiationDependentType())
+        return true;
+
+    // TODO: currently we always rebuild expressions.  When we
+    // properly get lazier about this, we should use the same
+    // logic to avoid rebuilding prototypes here.
+    if (P->hasDefaultArg())
+      return true;
+  }
+
+  return false;
+}
+
+/// A form of SubstType intended specifically for instantiating the
+/// type of a FunctionDecl.  Its purpose is solely to force the
+/// instantiation of default-argument expressions.
+TypeSourceInfo *Sema::SubstFunctionDeclType(TypeSourceInfo *T,
+                                const MultiLevelTemplateArgumentList &Args,
+                                SourceLocation Loc,
+                                DeclarationName Entity,
+                                CXXRecordDecl *ThisContext,
+                                unsigned ThisTypeQuals) {
+  assert(!ActiveTemplateInstantiations.empty() &&
+         "Cannot perform an instantiation without some context on the "
+         "instantiation stack");
+  
+  if (!NeedsInstantiationAsFunctionType(T))
+    return T;
+
+  TemplateInstantiator Instantiator(*this, Args, Loc, Entity);
+
+  TypeLocBuilder TLB;
+
+  TypeLoc TL = T->getTypeLoc();
+  TLB.reserve(TL.getFullDataSize());
+
+  QualType Result;
+  
+  if (FunctionProtoTypeLoc *Proto = dyn_cast<FunctionProtoTypeLoc>(&TL)) {
+    Result = Instantiator.TransformFunctionProtoType(TLB, *Proto, ThisContext,
+                                                     ThisTypeQuals);
+  } else {
+    Result = Instantiator.TransformType(TLB, TL);
+  }
+  if (Result.isNull())
+    return 0;
+
+  return TLB.getTypeSourceInfo(Context, Result);
+}
+
+ParmVarDecl *Sema::SubstParmVarDecl(ParmVarDecl *OldParm, 
+                            const MultiLevelTemplateArgumentList &TemplateArgs,
+                                    int indexAdjustment,
+                                    llvm::Optional<unsigned> NumExpansions,
+                                    bool ExpectParameterPack) {
+  TypeSourceInfo *OldDI = OldParm->getTypeSourceInfo();
+  TypeSourceInfo *NewDI = 0;
+  
+  TypeLoc OldTL = OldDI->getTypeLoc();
+  if (isa<PackExpansionTypeLoc>(OldTL)) {    
+    PackExpansionTypeLoc ExpansionTL = cast<PackExpansionTypeLoc>(OldTL);
+    
+    // We have a function parameter pack. Substitute into the pattern of the 
+    // expansion.
+    NewDI = SubstType(ExpansionTL.getPatternLoc(), TemplateArgs, 
+                      OldParm->getLocation(), OldParm->getDeclName());
+    if (!NewDI)
+      return 0;
+        
+    if (NewDI->getType()->containsUnexpandedParameterPack()) {
+      // We still have unexpanded parameter packs, which means that
+      // our function parameter is still a function parameter pack.
+      // Therefore, make its type a pack expansion type.
+      NewDI = CheckPackExpansion(NewDI, ExpansionTL.getEllipsisLoc(),
+                                 NumExpansions);
+    } else if (ExpectParameterPack) {
+      // We expected to get a parameter pack but didn't (because the type
+      // itself is not a pack expansion type), so complain. This can occur when
+      // the substitution goes through an alias template that "loses" the
+      // pack expansion.
+      Diag(OldParm->getLocation(), 
+           diag::err_function_parameter_pack_without_parameter_packs)
+        << NewDI->getType();
+      return 0;
+    } 
+  } else {
+    NewDI = SubstType(OldDI, TemplateArgs, OldParm->getLocation(), 
+                      OldParm->getDeclName());
+  }
+  
+  if (!NewDI)
+    return 0;
+
+  if (NewDI->getType()->isVoidType()) {
+    Diag(OldParm->getLocation(), diag::err_param_with_void_type);
+    return 0;
+  }
+
+  ParmVarDecl *NewParm = CheckParameter(Context.getTranslationUnitDecl(),
+                                        OldParm->getInnerLocStart(),
+                                        OldParm->getLocation(),
+                                        OldParm->getIdentifier(),
+                                        NewDI->getType(), NewDI,
+                                        OldParm->getStorageClass(),
+                                        OldParm->getStorageClassAsWritten());
+  if (!NewParm)
+    return 0;
+                                                
+  // Mark the (new) default argument as uninstantiated (if any).
+  if (OldParm->hasUninstantiatedDefaultArg()) {
+    Expr *Arg = OldParm->getUninstantiatedDefaultArg();
+    NewParm->setUninstantiatedDefaultArg(Arg);
+  } else if (OldParm->hasUnparsedDefaultArg()) {
+    NewParm->setUnparsedDefaultArg();
+    UnparsedDefaultArgInstantiations[OldParm].push_back(NewParm);
+  } else if (Expr *Arg = OldParm->getDefaultArg())
+    NewParm->setUninstantiatedDefaultArg(Arg);
+
+  NewParm->setHasInheritedDefaultArg(OldParm->hasInheritedDefaultArg());
+  
+  if (OldParm->isParameterPack() && !NewParm->isParameterPack()) {
+    // Add the new parameter to the instantiated parameter pack.
+    CurrentInstantiationScope->InstantiatedLocalPackArg(OldParm, NewParm);
+  } else {
+    // Introduce an Old -> New mapping
+    CurrentInstantiationScope->InstantiatedLocal(OldParm, NewParm);  
+  }
+  
+  // FIXME: OldParm may come from a FunctionProtoType, in which case CurContext
+  // can be anything, is this right ?
+  NewParm->setDeclContext(CurContext);
+
+  NewParm->setScopeInfo(OldParm->getFunctionScopeDepth(),
+                        OldParm->getFunctionScopeIndex() + indexAdjustment);
+  
+  return NewParm;  
+}
+
+/// \brief Substitute the given template arguments into the given set of
+/// parameters, producing the set of parameter types that would be generated
+/// from such a substitution.
+bool Sema::SubstParmTypes(SourceLocation Loc, 
+                          ParmVarDecl **Params, unsigned NumParams,
+                          const MultiLevelTemplateArgumentList &TemplateArgs,
+                          SmallVectorImpl<QualType> &ParamTypes,
+                          SmallVectorImpl<ParmVarDecl *> *OutParams) {
+  assert(!ActiveTemplateInstantiations.empty() &&
+         "Cannot perform an instantiation without some context on the "
+         "instantiation stack");
+  
+  TemplateInstantiator Instantiator(*this, TemplateArgs, Loc, 
+                                    DeclarationName());
+  return Instantiator.TransformFunctionTypeParams(Loc, Params, NumParams, 0,
+                                                  ParamTypes, OutParams);
+}
+
+/// \brief Perform substitution on the base class specifiers of the
+/// given class template specialization.
+///
+/// Produces a diagnostic and returns true on error, returns false and
+/// attaches the instantiated base classes to the class template
+/// specialization if successful.
+bool
+Sema::SubstBaseSpecifiers(CXXRecordDecl *Instantiation,
+                          CXXRecordDecl *Pattern,
+                          const MultiLevelTemplateArgumentList &TemplateArgs) {
+  bool Invalid = false;
+  SmallVector<CXXBaseSpecifier*, 4> InstantiatedBases;
+  for (ClassTemplateSpecializationDecl::base_class_iterator
+         Base = Pattern->bases_begin(), BaseEnd = Pattern->bases_end();
+       Base != BaseEnd; ++Base) {
+    if (!Base->getType()->isDependentType()) {
+      InstantiatedBases.push_back(new (Context) CXXBaseSpecifier(*Base));
+      continue;
+    }
+
+    SourceLocation EllipsisLoc;
+    TypeSourceInfo *BaseTypeLoc;
+    if (Base->isPackExpansion()) {
+      // This is a pack expansion. See whether we should expand it now, or
+      // wait until later.
+      SmallVector<UnexpandedParameterPack, 2> Unexpanded;
+      collectUnexpandedParameterPacks(Base->getTypeSourceInfo()->getTypeLoc(),
+                                      Unexpanded);
+      bool ShouldExpand = false;
+      bool RetainExpansion = false;
+      llvm::Optional<unsigned> NumExpansions;
+      if (CheckParameterPacksForExpansion(Base->getEllipsisLoc(), 
+                                          Base->getSourceRange(),
+                                          Unexpanded,
+                                          TemplateArgs, ShouldExpand, 
+                                          RetainExpansion,
+                                          NumExpansions)) {
+        Invalid = true;
+        continue;
+      }
+      
+      // If we should expand this pack expansion now, do so.
+      if (ShouldExpand) {
+        for (unsigned I = 0; I != *NumExpansions; ++I) {
+            Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(*this, I);
+          
+          TypeSourceInfo *BaseTypeLoc = SubstType(Base->getTypeSourceInfo(),
+                                                  TemplateArgs,
+                                              Base->getSourceRange().getBegin(),
+                                                  DeclarationName());
+          if (!BaseTypeLoc) {
+            Invalid = true;
+            continue;
+          }
+          
+          if (CXXBaseSpecifier *InstantiatedBase
+                = CheckBaseSpecifier(Instantiation,
+                                     Base->getSourceRange(),
+                                     Base->isVirtual(),
+                                     Base->getAccessSpecifierAsWritten(),
+                                     BaseTypeLoc,
+                                     SourceLocation()))
+            InstantiatedBases.push_back(InstantiatedBase);
+          else
+            Invalid = true;
+        }
+      
+        continue;
+      }
+      
+      // The resulting base specifier will (still) be a pack expansion.
+      EllipsisLoc = Base->getEllipsisLoc();
+      Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(*this, -1);
+      BaseTypeLoc = SubstType(Base->getTypeSourceInfo(),
+                              TemplateArgs,
+                              Base->getSourceRange().getBegin(),
+                              DeclarationName());
+    } else {
+      BaseTypeLoc = SubstType(Base->getTypeSourceInfo(),
+                              TemplateArgs,
+                              Base->getSourceRange().getBegin(),
+                              DeclarationName());
+    }
+    
+    if (!BaseTypeLoc) {
+      Invalid = true;
+      continue;
+    }
+
+    if (CXXBaseSpecifier *InstantiatedBase
+          = CheckBaseSpecifier(Instantiation,
+                               Base->getSourceRange(),
+                               Base->isVirtual(),
+                               Base->getAccessSpecifierAsWritten(),
+                               BaseTypeLoc,
+                               EllipsisLoc))
+      InstantiatedBases.push_back(InstantiatedBase);
+    else
+      Invalid = true;
+  }
+
+  if (!Invalid &&
+      AttachBaseSpecifiers(Instantiation, InstantiatedBases.data(),
+                           InstantiatedBases.size()))
+    Invalid = true;
+
+  return Invalid;
+}
+
+// Defined via #include from SemaTemplateInstantiateDecl.cpp
+namespace clang {
+  namespace sema {
+    Attr *instantiateTemplateAttribute(const Attr *At, ASTContext &C, Sema &S,
+                            const MultiLevelTemplateArgumentList &TemplateArgs);
+  }
+}
+
+/// Determine whether we would be unable to instantiate this template (because
+/// it either has no definition, or is in the process of being instantiated).
+static bool DiagnoseUninstantiableTemplate(Sema &S,
+                                           SourceLocation PointOfInstantiation,
+                                           TagDecl *Instantiation,
+                                           bool InstantiatedFromMember,
+                                           TagDecl *Pattern,
+                                           TagDecl *PatternDef,
+                                           TemplateSpecializationKind TSK,
+                                           bool Complain = true) {
+  if (PatternDef && !PatternDef->isBeingDefined())
+    return false;
+
+  if (!Complain || (PatternDef && PatternDef->isInvalidDecl())) {
+    // Say nothing
+  } else if (PatternDef) {
+    assert(PatternDef->isBeingDefined());
+    S.Diag(PointOfInstantiation,
+           diag::err_template_instantiate_within_definition)
+      << (TSK != TSK_ImplicitInstantiation)
+      << S.Context.getTypeDeclType(Instantiation);
+    // Not much point in noting the template declaration here, since
+    // we're lexically inside it.
+    Instantiation->setInvalidDecl();
+  } else if (InstantiatedFromMember) {
+    S.Diag(PointOfInstantiation,
+           diag::err_implicit_instantiate_member_undefined)
+      << S.Context.getTypeDeclType(Instantiation);
+    S.Diag(Pattern->getLocation(), diag::note_member_of_template_here);
+  } else {
+    S.Diag(PointOfInstantiation, diag::err_template_instantiate_undefined)
+      << (TSK != TSK_ImplicitInstantiation)
+      << S.Context.getTypeDeclType(Instantiation);
+    S.Diag(Pattern->getLocation(), diag::note_template_decl_here);
+  }
+
+  // In general, Instantiation isn't marked invalid to get more than one
+  // error for multiple undefined instantiations. But the code that does
+  // explicit declaration -> explicit definition conversion can't handle
+  // invalid declarations, so mark as invalid in that case.
+  if (TSK == TSK_ExplicitInstantiationDeclaration)
+    Instantiation->setInvalidDecl();
+  return true;
+}
+
+/// \brief Instantiate the definition of a class from a given pattern.
+///
+/// \param PointOfInstantiation The point of instantiation within the
+/// source code.
+///
+/// \param Instantiation is the declaration whose definition is being
+/// instantiated. This will be either a class template specialization
+/// or a member class of a class template specialization.
+///
+/// \param Pattern is the pattern from which the instantiation
+/// occurs. This will be either the declaration of a class template or
+/// the declaration of a member class of a class template.
+///
+/// \param TemplateArgs The template arguments to be substituted into
+/// the pattern.
+///
+/// \param TSK the kind of implicit or explicit instantiation to perform.
+///
+/// \param Complain whether to complain if the class cannot be instantiated due
+/// to the lack of a definition.
+///
+/// \returns true if an error occurred, false otherwise.
+bool
+Sema::InstantiateClass(SourceLocation PointOfInstantiation,
+                       CXXRecordDecl *Instantiation, CXXRecordDecl *Pattern,
+                       const MultiLevelTemplateArgumentList &TemplateArgs,
+                       TemplateSpecializationKind TSK,
+                       bool Complain) {
+  bool Invalid = false;
+
+  CXXRecordDecl *PatternDef
+    = cast_or_null<CXXRecordDecl>(Pattern->getDefinition());
+  if (DiagnoseUninstantiableTemplate(*this, PointOfInstantiation, Instantiation,
+                                Instantiation->getInstantiatedFromMemberClass(),
+                                     Pattern, PatternDef, TSK, Complain))
+    return true;
+  Pattern = PatternDef;
+
+  // \brief Record the point of instantiation.
+  if (MemberSpecializationInfo *MSInfo 
+        = Instantiation->getMemberSpecializationInfo()) {
+    MSInfo->setTemplateSpecializationKind(TSK);
+    MSInfo->setPointOfInstantiation(PointOfInstantiation);
+  } else if (ClassTemplateSpecializationDecl *Spec 
+        = dyn_cast<ClassTemplateSpecializationDecl>(Instantiation)) {
+    Spec->setTemplateSpecializationKind(TSK);
+    Spec->setPointOfInstantiation(PointOfInstantiation);
+  }
+  
+  InstantiatingTemplate Inst(*this, PointOfInstantiation, Instantiation);
+  if (Inst)
+    return true;
+
+  // Enter the scope of this instantiation. We don't use
+  // PushDeclContext because we don't have a scope.
+  ContextRAII SavedContext(*this, Instantiation);
+  EnterExpressionEvaluationContext EvalContext(*this, 
+                                               Sema::PotentiallyEvaluated);
+
+  // If this is an instantiation of a local class, merge this local
+  // instantiation scope with the enclosing scope. Otherwise, every
+  // instantiation of a class has its own local instantiation scope.
+  bool MergeWithParentScope = !Instantiation->isDefinedOutsideFunctionOrMethod();
+  LocalInstantiationScope Scope(*this, MergeWithParentScope);
+
+  // Pull attributes from the pattern onto the instantiation.
+  InstantiateAttrs(TemplateArgs, Pattern, Instantiation);
+
+  // Start the definition of this instantiation.
+  Instantiation->startDefinition();
+  
+  Instantiation->setTagKind(Pattern->getTagKind());
+
+  // Do substitution on the base class specifiers.
+  if (SubstBaseSpecifiers(Instantiation, Pattern, TemplateArgs))
+    Invalid = true;
+
+  TemplateDeclInstantiator Instantiator(*this, Instantiation, TemplateArgs);
+  SmallVector<Decl*, 4> Fields;
+  SmallVector<std::pair<FieldDecl*, FieldDecl*>, 4>
+    FieldsWithMemberInitializers;
+  // Delay instantiation of late parsed attributes.
+  LateInstantiatedAttrVec LateAttrs;
+  Instantiator.enableLateAttributeInstantiation(&LateAttrs);
+
+  for (RecordDecl::decl_iterator Member = Pattern->decls_begin(),
+         MemberEnd = Pattern->decls_end();
+       Member != MemberEnd; ++Member) {
+    // Don't instantiate members not belonging in this semantic context.
+    // e.g. for:
+    // @code
+    //    template <int i> class A {
+    //      class B *g;
+    //    };
+    // @endcode
+    // 'class B' has the template as lexical context but semantically it is
+    // introduced in namespace scope.
+    if ((*Member)->getDeclContext() != Pattern)
+      continue;
+
+    if ((*Member)->isInvalidDecl()) {
+      Invalid = true; 
+      continue;
+    }
+
+    Decl *NewMember = Instantiator.Visit(*Member);
+    if (NewMember) {
+      if (FieldDecl *Field = dyn_cast<FieldDecl>(NewMember)) {
+        Fields.push_back(Field);
+        FieldDecl *OldField = cast<FieldDecl>(*Member);
+        if (OldField->getInClassInitializer())
+          FieldsWithMemberInitializers.push_back(std::make_pair(OldField,
+                                                                Field));
+      } else if (EnumDecl *Enum = dyn_cast<EnumDecl>(NewMember)) {
+        // C++11 [temp.inst]p1: The implicit instantiation of a class template
+        // specialization causes the implicit instantiation of the definitions
+        // of unscoped member enumerations.
+        // Record a point of instantiation for this implicit instantiation.
+        if (TSK == TSK_ImplicitInstantiation && !Enum->isScoped() &&
+            Enum->isCompleteDefinition()) {
+          MemberSpecializationInfo *MSInfo =Enum->getMemberSpecializationInfo();
+          assert(MSInfo && "no spec info for member enum specialization");
+          MSInfo->setTemplateSpecializationKind(TSK_ImplicitInstantiation);
+          MSInfo->setPointOfInstantiation(PointOfInstantiation);
+        }
+      }
+
+      if (NewMember->isInvalidDecl())
+        Invalid = true;
+    } else {
+      // FIXME: Eventually, a NULL return will mean that one of the
+      // instantiations was a semantic disaster, and we'll want to set Invalid =
+      // true. For now, we expect to skip some members that we can't yet handle.
+    }
+  }
+
+  // Finish checking fields.
+  ActOnFields(0, Instantiation->getLocation(), Instantiation, Fields, 
+              SourceLocation(), SourceLocation(), 0);
+  CheckCompletedCXXClass(Instantiation);
+
+  // Attach any in-class member initializers now the class is complete.
+  {
+    // C++11 [expr.prim.general]p4:
+    //   Otherwise, if a member-declarator declares a non-static data member 
+    //  (9.2) of a class X, the expression this is a prvalue of type "pointer
+    //  to X" within the optional brace-or-equal-initializer. It shall not 
+    //  appear elsewhere in the member-declarator.
+    CXXThisScopeRAII ThisScope(*this, Instantiation, (unsigned)0);
+    
+    for (unsigned I = 0, N = FieldsWithMemberInitializers.size(); I != N; ++I) {
+      FieldDecl *OldField = FieldsWithMemberInitializers[I].first;
+      FieldDecl *NewField = FieldsWithMemberInitializers[I].second;
+      Expr *OldInit = OldField->getInClassInitializer();
+
+      ExprResult NewInit = SubstInitializer(OldInit, TemplateArgs,
+                                            /*CXXDirectInit=*/false);
+      if (NewInit.isInvalid())
+        NewField->setInvalidDecl();
+      else {
+        Expr *Init = NewInit.take();
+        assert(Init && "no-argument initializer in class");
+        assert(!isa<ParenListExpr>(Init) && "call-style init in class");
+        ActOnCXXInClassMemberInitializer(NewField, 
+                                         Init->getSourceRange().getBegin(), 
+                                         Init);
+      }
+    }
+  }
+  // Instantiate late parsed attributes, and attach them to their decls.
+  // See Sema::InstantiateAttrs
+  for (LateInstantiatedAttrVec::iterator I = LateAttrs.begin(),
+       E = LateAttrs.end(); I != E; ++I) {
+    assert(CurrentInstantiationScope == Instantiator.getStartingScope());
+    CurrentInstantiationScope = I->Scope;
+    Attr *NewAttr =
+      instantiateTemplateAttribute(I->TmplAttr, Context, *this, TemplateArgs);
+    I->NewDecl->addAttr(NewAttr);
+    LocalInstantiationScope::deleteScopes(I->Scope,
+                                          Instantiator.getStartingScope());
+  }
+  Instantiator.disableLateAttributeInstantiation();
+  LateAttrs.clear();
+
+  if (!FieldsWithMemberInitializers.empty())
+    ActOnFinishDelayedMemberInitializers(Instantiation);
+
+  if (TSK == TSK_ImplicitInstantiation) {
+    Instantiation->setLocation(Pattern->getLocation());
+    Instantiation->setLocStart(Pattern->getInnerLocStart());
+    Instantiation->setRBraceLoc(Pattern->getRBraceLoc());
+  }
+
+  if (Instantiation->isInvalidDecl())
+    Invalid = true;
+  else {
+    // Instantiate any out-of-line class template partial
+    // specializations now.
+    for (TemplateDeclInstantiator::delayed_partial_spec_iterator 
+              P = Instantiator.delayed_partial_spec_begin(),
+           PEnd = Instantiator.delayed_partial_spec_end();
+         P != PEnd; ++P) {
+      if (!Instantiator.InstantiateClassTemplatePartialSpecialization(
+                                                                P->first,
+                                                                P->second)) {
+        Invalid = true;
+        break;
+      }
+    }
+  }
+
+  // Exit the scope of this instantiation.
+  SavedContext.pop();
+
+  if (!Invalid) {
+    Consumer.HandleTagDeclDefinition(Instantiation);
+
+    // Always emit the vtable for an explicit instantiation definition
+    // of a polymorphic class template specialization.
+    if (TSK == TSK_ExplicitInstantiationDefinition)
+      MarkVTableUsed(PointOfInstantiation, Instantiation, true);
+  }
+
+  return Invalid;
+}
+
+/// \brief Instantiate the definition of an enum from a given pattern.
+///
+/// \param PointOfInstantiation The point of instantiation within the
+///        source code.
+/// \param Instantiation is the declaration whose definition is being
+///        instantiated. This will be a member enumeration of a class
+///        temploid specialization, or a local enumeration within a
+///        function temploid specialization.
+/// \param Pattern The templated declaration from which the instantiation
+///        occurs.
+/// \param TemplateArgs The template arguments to be substituted into
+///        the pattern.
+/// \param TSK The kind of implicit or explicit instantiation to perform.
+///
+/// \return \c true if an error occurred, \c false otherwise.
+bool Sema::InstantiateEnum(SourceLocation PointOfInstantiation,
+                           EnumDecl *Instantiation, EnumDecl *Pattern,
+                           const MultiLevelTemplateArgumentList &TemplateArgs,
+                           TemplateSpecializationKind TSK) {
+  EnumDecl *PatternDef = Pattern->getDefinition();
+  if (DiagnoseUninstantiableTemplate(*this, PointOfInstantiation, Instantiation,
+                                 Instantiation->getInstantiatedFromMemberEnum(),
+                                     Pattern, PatternDef, TSK,/*Complain*/true))
+    return true;
+  Pattern = PatternDef;
+
+  // Record the point of instantiation.
+  if (MemberSpecializationInfo *MSInfo
+        = Instantiation->getMemberSpecializationInfo()) {
+    MSInfo->setTemplateSpecializationKind(TSK);
+    MSInfo->setPointOfInstantiation(PointOfInstantiation);
+  }
+
+  InstantiatingTemplate Inst(*this, PointOfInstantiation, Instantiation);
+  if (Inst)
+    return true;
+
+  // Enter the scope of this instantiation. We don't use
+  // PushDeclContext because we don't have a scope.
+  ContextRAII SavedContext(*this, Instantiation);
+  EnterExpressionEvaluationContext EvalContext(*this,
+                                               Sema::PotentiallyEvaluated);
+
+  LocalInstantiationScope Scope(*this, /*MergeWithParentScope*/true);
+
+  // Pull attributes from the pattern onto the instantiation.
+  InstantiateAttrs(TemplateArgs, Pattern, Instantiation);
+
+  TemplateDeclInstantiator Instantiator(*this, Instantiation, TemplateArgs);
+  Instantiator.InstantiateEnumDefinition(Instantiation, Pattern);
+
+  // Exit the scope of this instantiation.
+  SavedContext.pop();
+
+  return Instantiation->isInvalidDecl();
+}
+
+namespace {
+  /// \brief A partial specialization whose template arguments have matched
+  /// a given template-id.
+  struct PartialSpecMatchResult {
+    ClassTemplatePartialSpecializationDecl *Partial;
+    TemplateArgumentList *Args;
+  };
+}
+
+bool
+Sema::InstantiateClassTemplateSpecialization(
+                           SourceLocation PointOfInstantiation,
+                           ClassTemplateSpecializationDecl *ClassTemplateSpec,
+                           TemplateSpecializationKind TSK,
+                           bool Complain) {
+  // Perform the actual instantiation on the canonical declaration.
+  ClassTemplateSpec = cast<ClassTemplateSpecializationDecl>(
+                                         ClassTemplateSpec->getCanonicalDecl());
+
+  // Check whether we have already instantiated or specialized this class
+  // template specialization.
+  if (ClassTemplateSpec->getSpecializationKind() != TSK_Undeclared) {
+    if (ClassTemplateSpec->getSpecializationKind() == 
+          TSK_ExplicitInstantiationDeclaration &&
+        TSK == TSK_ExplicitInstantiationDefinition) {
+      // An explicit instantiation definition follows an explicit instantiation
+      // declaration (C++0x [temp.explicit]p10); go ahead and perform the
+      // explicit instantiation.
+      ClassTemplateSpec->setSpecializationKind(TSK);
+      
+      // If this is an explicit instantiation definition, mark the
+      // vtable as used.
+      if (TSK == TSK_ExplicitInstantiationDefinition &&
+          !ClassTemplateSpec->isInvalidDecl())
+        MarkVTableUsed(PointOfInstantiation, ClassTemplateSpec, true);
+
+      return false;
+    }
+    
+    // We can only instantiate something that hasn't already been
+    // instantiated or specialized. Fail without any diagnostics: our
+    // caller will provide an error message.    
+    return true;
+  }
+
+  if (ClassTemplateSpec->isInvalidDecl())
+    return true;
+  
+  ClassTemplateDecl *Template = ClassTemplateSpec->getSpecializedTemplate();
+  CXXRecordDecl *Pattern = 0;
+
+  // C++ [temp.class.spec.match]p1:
+  //   When a class template is used in a context that requires an
+  //   instantiation of the class, it is necessary to determine
+  //   whether the instantiation is to be generated using the primary
+  //   template or one of the partial specializations. This is done by
+  //   matching the template arguments of the class template
+  //   specialization with the template argument lists of the partial
+  //   specializations.
+  typedef PartialSpecMatchResult MatchResult;
+  SmallVector<MatchResult, 4> Matched;
+  SmallVector<ClassTemplatePartialSpecializationDecl *, 4> PartialSpecs;
+  Template->getPartialSpecializations(PartialSpecs);
+  for (unsigned I = 0, N = PartialSpecs.size(); I != N; ++I) {
+    ClassTemplatePartialSpecializationDecl *Partial = PartialSpecs[I];
+    TemplateDeductionInfo Info(Context, PointOfInstantiation);
+    if (TemplateDeductionResult Result
+          = DeduceTemplateArguments(Partial,
+                                    ClassTemplateSpec->getTemplateArgs(),
+                                    Info)) {
+      // FIXME: Store the failed-deduction information for use in
+      // diagnostics, later.
+      (void)Result;
+    } else {
+      Matched.push_back(PartialSpecMatchResult());
+      Matched.back().Partial = Partial;
+      Matched.back().Args = Info.take();
+    }
+  }
+
+  // If we're dealing with a member template where the template parameters
+  // have been instantiated, this provides the original template parameters
+  // from which the member template's parameters were instantiated.
+  SmallVector<const NamedDecl *, 4> InstantiatedTemplateParameters;
+  
+  if (Matched.size() >= 1) {
+    SmallVector<MatchResult, 4>::iterator Best = Matched.begin();
+    if (Matched.size() == 1) {
+      //   -- If exactly one matching specialization is found, the
+      //      instantiation is generated from that specialization.
+      // We don't need to do anything for this.
+    } else {
+      //   -- If more than one matching specialization is found, the
+      //      partial order rules (14.5.4.2) are used to determine
+      //      whether one of the specializations is more specialized
+      //      than the others. If none of the specializations is more
+      //      specialized than all of the other matching
+      //      specializations, then the use of the class template is
+      //      ambiguous and the program is ill-formed.
+      for (SmallVector<MatchResult, 4>::iterator P = Best + 1,
+                                                    PEnd = Matched.end();
+           P != PEnd; ++P) {
+        if (getMoreSpecializedPartialSpecialization(P->Partial, Best->Partial,
+                                                    PointOfInstantiation) 
+              == P->Partial)
+          Best = P;
+      }
+      
+      // Determine if the best partial specialization is more specialized than
+      // the others.
+      bool Ambiguous = false;
+      for (SmallVector<MatchResult, 4>::iterator P = Matched.begin(),
+                                                    PEnd = Matched.end();
+           P != PEnd; ++P) {
+        if (P != Best &&
+            getMoreSpecializedPartialSpecialization(P->Partial, Best->Partial,
+                                                    PointOfInstantiation)
+              != Best->Partial) {
+          Ambiguous = true;
+          break;
+        }
+      }
+       
+      if (Ambiguous) {
+        // Partial ordering did not produce a clear winner. Complain.
+        ClassTemplateSpec->setInvalidDecl();
+        Diag(PointOfInstantiation, diag::err_partial_spec_ordering_ambiguous)
+          << ClassTemplateSpec;
+        
+        // Print the matching partial specializations.
+        for (SmallVector<MatchResult, 4>::iterator P = Matched.begin(),
+                                                      PEnd = Matched.end();
+             P != PEnd; ++P)
+          Diag(P->Partial->getLocation(), diag::note_partial_spec_match)
+            << getTemplateArgumentBindingsText(
+                                            P->Partial->getTemplateParameters(),
+                                               *P->Args);
+
+        return true;
+      }
+    }
+    
+    // Instantiate using the best class template partial specialization.
+    ClassTemplatePartialSpecializationDecl *OrigPartialSpec = Best->Partial;
+    while (OrigPartialSpec->getInstantiatedFromMember()) {
+      // If we've found an explicit specialization of this class template,
+      // stop here and use that as the pattern.
+      if (OrigPartialSpec->isMemberSpecialization())
+        break;
+      
+      OrigPartialSpec = OrigPartialSpec->getInstantiatedFromMember();
+    }
+    
+    Pattern = OrigPartialSpec;
+    ClassTemplateSpec->setInstantiationOf(Best->Partial, Best->Args);
+  } else {
+    //   -- If no matches are found, the instantiation is generated
+    //      from the primary template.
+    ClassTemplateDecl *OrigTemplate = Template;
+    while (OrigTemplate->getInstantiatedFromMemberTemplate()) {
+      // If we've found an explicit specialization of this class template,
+      // stop here and use that as the pattern.
+      if (OrigTemplate->isMemberSpecialization())
+        break;
+      
+      OrigTemplate = OrigTemplate->getInstantiatedFromMemberTemplate();
+    }
+    
+    Pattern = OrigTemplate->getTemplatedDecl();
+  }
+
+  bool Result = InstantiateClass(PointOfInstantiation, ClassTemplateSpec, 
+                                 Pattern,
+                                getTemplateInstantiationArgs(ClassTemplateSpec),
+                                 TSK,
+                                 Complain);
+
+  return Result;
+}
+
+/// \brief Instantiates the definitions of all of the member
+/// of the given class, which is an instantiation of a class template
+/// or a member class of a template.
+void
+Sema::InstantiateClassMembers(SourceLocation PointOfInstantiation,
+                              CXXRecordDecl *Instantiation,
+                        const MultiLevelTemplateArgumentList &TemplateArgs,
+                              TemplateSpecializationKind TSK) {
+  for (DeclContext::decl_iterator D = Instantiation->decls_begin(),
+                               DEnd = Instantiation->decls_end();
+       D != DEnd; ++D) {
+    bool SuppressNew = false;
+    if (FunctionDecl *Function = dyn_cast<FunctionDecl>(*D)) {
+      if (FunctionDecl *Pattern
+            = Function->getInstantiatedFromMemberFunction()) {
+        MemberSpecializationInfo *MSInfo 
+          = Function->getMemberSpecializationInfo();
+        assert(MSInfo && "No member specialization information?");
+        if (MSInfo->getTemplateSpecializationKind()
+                                                 == TSK_ExplicitSpecialization)
+          continue;
+        
+        if (CheckSpecializationInstantiationRedecl(PointOfInstantiation, TSK, 
+                                                   Function, 
+                                        MSInfo->getTemplateSpecializationKind(),
+                                              MSInfo->getPointOfInstantiation(),
+                                                   SuppressNew) ||
+            SuppressNew)
+          continue;
+        
+        if (Function->isDefined())
+          continue;
+
+        if (TSK == TSK_ExplicitInstantiationDefinition) {
+          // C++0x [temp.explicit]p8:
+          //   An explicit instantiation definition that names a class template
+          //   specialization explicitly instantiates the class template 
+          //   specialization and is only an explicit instantiation definition 
+          //   of members whose definition is visible at the point of 
+          //   instantiation.
+          if (!Pattern->isDefined())
+            continue;
+        
+          Function->setTemplateSpecializationKind(TSK, PointOfInstantiation);
+                      
+          InstantiateFunctionDefinition(PointOfInstantiation, Function);
+        } else {
+          Function->setTemplateSpecializationKind(TSK, PointOfInstantiation);
+        }
+      }
+    } else if (VarDecl *Var = dyn_cast<VarDecl>(*D)) {
+      if (Var->isStaticDataMember()) {
+        MemberSpecializationInfo *MSInfo = Var->getMemberSpecializationInfo();
+        assert(MSInfo && "No member specialization information?");
+        if (MSInfo->getTemplateSpecializationKind()
+                                                 == TSK_ExplicitSpecialization)
+          continue;
+        
+        if (CheckSpecializationInstantiationRedecl(PointOfInstantiation, TSK, 
+                                                   Var, 
+                                        MSInfo->getTemplateSpecializationKind(),
+                                              MSInfo->getPointOfInstantiation(),
+                                                   SuppressNew) ||
+            SuppressNew)
+          continue;
+        
+        if (TSK == TSK_ExplicitInstantiationDefinition) {
+          // C++0x [temp.explicit]p8:
+          //   An explicit instantiation definition that names a class template
+          //   specialization explicitly instantiates the class template 
+          //   specialization and is only an explicit instantiation definition 
+          //   of members whose definition is visible at the point of 
+          //   instantiation.
+          if (!Var->getInstantiatedFromStaticDataMember()
+                                                     ->getOutOfLineDefinition())
+            continue;
+          
+          Var->setTemplateSpecializationKind(TSK, PointOfInstantiation);
+          InstantiateStaticDataMemberDefinition(PointOfInstantiation, Var);
+        } else {
+          Var->setTemplateSpecializationKind(TSK, PointOfInstantiation);
+        }
+      }      
+    } else if (CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(*D)) {
+      // Always skip the injected-class-name, along with any
+      // redeclarations of nested classes, since both would cause us
+      // to try to instantiate the members of a class twice.
+      if (Record->isInjectedClassName() || Record->getPreviousDecl())
+        continue;
+      
+      MemberSpecializationInfo *MSInfo = Record->getMemberSpecializationInfo();
+      assert(MSInfo && "No member specialization information?");
+      
+      if (MSInfo->getTemplateSpecializationKind()
+                                                == TSK_ExplicitSpecialization)
+        continue;
+
+      if (CheckSpecializationInstantiationRedecl(PointOfInstantiation, TSK, 
+                                                 Record, 
+                                        MSInfo->getTemplateSpecializationKind(),
+                                              MSInfo->getPointOfInstantiation(),
+                                                 SuppressNew) ||
+          SuppressNew)
+        continue;
+      
+      CXXRecordDecl *Pattern = Record->getInstantiatedFromMemberClass();
+      assert(Pattern && "Missing instantiated-from-template information");
+      
+      if (!Record->getDefinition()) {
+        if (!Pattern->getDefinition()) {
+          // C++0x [temp.explicit]p8:
+          //   An explicit instantiation definition that names a class template
+          //   specialization explicitly instantiates the class template 
+          //   specialization and is only an explicit instantiation definition 
+          //   of members whose definition is visible at the point of 
+          //   instantiation.
+          if (TSK == TSK_ExplicitInstantiationDeclaration) {
+            MSInfo->setTemplateSpecializationKind(TSK);
+            MSInfo->setPointOfInstantiation(PointOfInstantiation);
+          }
+          
+          continue;
+        }
+        
+        InstantiateClass(PointOfInstantiation, Record, Pattern,
+                         TemplateArgs,
+                         TSK);
+      } else {
+        if (TSK == TSK_ExplicitInstantiationDefinition &&
+            Record->getTemplateSpecializationKind() ==
+                TSK_ExplicitInstantiationDeclaration) {
+          Record->setTemplateSpecializationKind(TSK);
+          MarkVTableUsed(PointOfInstantiation, Record, true);
+        }
+      }
+      
+      Pattern = cast_or_null<CXXRecordDecl>(Record->getDefinition());
+      if (Pattern)
+        InstantiateClassMembers(PointOfInstantiation, Pattern, TemplateArgs, 
+                                TSK);
+    } else if (EnumDecl *Enum = dyn_cast<EnumDecl>(*D)) {
+      MemberSpecializationInfo *MSInfo = Enum->getMemberSpecializationInfo();
+      assert(MSInfo && "No member specialization information?");
+
+      if (MSInfo->getTemplateSpecializationKind()
+            == TSK_ExplicitSpecialization)
+        continue;
+
+      if (CheckSpecializationInstantiationRedecl(
+            PointOfInstantiation, TSK, Enum,
+            MSInfo->getTemplateSpecializationKind(),
+            MSInfo->getPointOfInstantiation(), SuppressNew) ||
+          SuppressNew)
+        continue;
+
+      if (Enum->getDefinition())
+        continue;
+
+      EnumDecl *Pattern = Enum->getInstantiatedFromMemberEnum();
+      assert(Pattern && "Missing instantiated-from-template information");
+
+      if (TSK == TSK_ExplicitInstantiationDefinition) {
+        if (!Pattern->getDefinition())
+          continue;
+
+        InstantiateEnum(PointOfInstantiation, Enum, Pattern, TemplateArgs, TSK);
+      } else {
+        MSInfo->setTemplateSpecializationKind(TSK);
+        MSInfo->setPointOfInstantiation(PointOfInstantiation);
+      }
+    }
+  }
+}
+
+/// \brief Instantiate the definitions of all of the members of the
+/// given class template specialization, which was named as part of an
+/// explicit instantiation.
+void
+Sema::InstantiateClassTemplateSpecializationMembers(
+                                           SourceLocation PointOfInstantiation,
+                            ClassTemplateSpecializationDecl *ClassTemplateSpec,
+                                               TemplateSpecializationKind TSK) {
+  // C++0x [temp.explicit]p7:
+  //   An explicit instantiation that names a class template
+  //   specialization is an explicit instantion of the same kind
+  //   (declaration or definition) of each of its members (not
+  //   including members inherited from base classes) that has not
+  //   been previously explicitly specialized in the translation unit
+  //   containing the explicit instantiation, except as described
+  //   below.
+  InstantiateClassMembers(PointOfInstantiation, ClassTemplateSpec,
+                          getTemplateInstantiationArgs(ClassTemplateSpec),
+                          TSK);
+}
+
+StmtResult
+Sema::SubstStmt(Stmt *S, const MultiLevelTemplateArgumentList &TemplateArgs) {
+  if (!S)
+    return Owned(S);
+
+  TemplateInstantiator Instantiator(*this, TemplateArgs,
+                                    SourceLocation(),
+                                    DeclarationName());
+  return Instantiator.TransformStmt(S);
+}
+
+ExprResult
+Sema::SubstExpr(Expr *E, const MultiLevelTemplateArgumentList &TemplateArgs) {
+  if (!E)
+    return Owned(E);
+
+  TemplateInstantiator Instantiator(*this, TemplateArgs,
+                                    SourceLocation(),
+                                    DeclarationName());
+  return Instantiator.TransformExpr(E);
+}
+
+bool Sema::SubstExprs(Expr **Exprs, unsigned NumExprs, bool IsCall,
+                      const MultiLevelTemplateArgumentList &TemplateArgs,
+                      SmallVectorImpl<Expr *> &Outputs) {
+  if (NumExprs == 0)
+    return false;
+  
+  TemplateInstantiator Instantiator(*this, TemplateArgs,
+                                    SourceLocation(),
+                                    DeclarationName());
+  return Instantiator.TransformExprs(Exprs, NumExprs, IsCall, Outputs);
+}
+
+NestedNameSpecifierLoc
+Sema::SubstNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS,
+                        const MultiLevelTemplateArgumentList &TemplateArgs) {  
+  if (!NNS)
+    return NestedNameSpecifierLoc();
+  
+  TemplateInstantiator Instantiator(*this, TemplateArgs, NNS.getBeginLoc(),
+                                    DeclarationName());
+  return Instantiator.TransformNestedNameSpecifierLoc(NNS);
+}
+
+/// \brief Do template substitution on declaration name info.
+DeclarationNameInfo
+Sema::SubstDeclarationNameInfo(const DeclarationNameInfo &NameInfo,
+                         const MultiLevelTemplateArgumentList &TemplateArgs) {
+  TemplateInstantiator Instantiator(*this, TemplateArgs, NameInfo.getLoc(),
+                                    NameInfo.getName());
+  return Instantiator.TransformDeclarationNameInfo(NameInfo);
+}
+
+TemplateName
+Sema::SubstTemplateName(NestedNameSpecifierLoc QualifierLoc,
+                        TemplateName Name, SourceLocation Loc,
+                        const MultiLevelTemplateArgumentList &TemplateArgs) {
+  TemplateInstantiator Instantiator(*this, TemplateArgs, Loc,
+                                    DeclarationName());
+  CXXScopeSpec SS;
+  SS.Adopt(QualifierLoc);
+  return Instantiator.TransformTemplateName(SS, Name, Loc);
+}
+
+bool Sema::Subst(const TemplateArgumentLoc *Args, unsigned NumArgs,
+                 TemplateArgumentListInfo &Result,
+                 const MultiLevelTemplateArgumentList &TemplateArgs) {
+  TemplateInstantiator Instantiator(*this, TemplateArgs, SourceLocation(),
+                                    DeclarationName());
+  
+  return Instantiator.TransformTemplateArguments(Args, NumArgs, Result);
+}
+
+llvm::PointerUnion<Decl *, LocalInstantiationScope::DeclArgumentPack *> *
+LocalInstantiationScope::findInstantiationOf(const Decl *D) {
+  for (LocalInstantiationScope *Current = this; Current;
+       Current = Current->Outer) {
+
+    // Check if we found something within this scope.
+    const Decl *CheckD = D;
+    do {
+      LocalDeclsMap::iterator Found = Current->LocalDecls.find(CheckD);
+      if (Found != Current->LocalDecls.end())
+        return &Found->second;
+      
+      // If this is a tag declaration, it's possible that we need to look for
+      // a previous declaration.
+      if (const TagDecl *Tag = dyn_cast<TagDecl>(CheckD))
+        CheckD = Tag->getPreviousDecl();
+      else
+        CheckD = 0;
+    } while (CheckD);
+    
+    // If we aren't combined with our outer scope, we're done. 
+    if (!Current->CombineWithOuterScope)
+      break;
+  }
+
+  // If we didn't find the decl, then we either have a sema bug, or we have a
+  // forward reference to a label declaration.  Return null to indicate that
+  // we have an uninstantiated label.
+  assert(isa<LabelDecl>(D) && "declaration not instantiated in this scope");
+  return 0;
+}
+
+void LocalInstantiationScope::InstantiatedLocal(const Decl *D, Decl *Inst) {
+  llvm::PointerUnion<Decl *, DeclArgumentPack *> &Stored = LocalDecls[D];
+  if (Stored.isNull())
+    Stored = Inst;
+  else if (Stored.is<Decl *>()) {
+    assert(Stored.get<Decl *>() == Inst && "Already instantiated this local");
+    Stored = Inst;
+  } else
+    LocalDecls[D].get<DeclArgumentPack *>()->push_back(Inst);
+}
+
+void LocalInstantiationScope::InstantiatedLocalPackArg(const Decl *D, 
+                                                       Decl *Inst) {
+  DeclArgumentPack *Pack = LocalDecls[D].get<DeclArgumentPack *>();
+  Pack->push_back(Inst);
+}
+
+void LocalInstantiationScope::MakeInstantiatedLocalArgPack(const Decl *D) {
+  llvm::PointerUnion<Decl *, DeclArgumentPack *> &Stored = LocalDecls[D];
+  assert(Stored.isNull() && "Already instantiated this local");
+  DeclArgumentPack *Pack = new DeclArgumentPack;
+  Stored = Pack;
+  ArgumentPacks.push_back(Pack);
+}
+
+void LocalInstantiationScope::SetPartiallySubstitutedPack(NamedDecl *Pack, 
+                                          const TemplateArgument *ExplicitArgs,
+                                                    unsigned NumExplicitArgs) {
+  assert((!PartiallySubstitutedPack || PartiallySubstitutedPack == Pack) &&
+         "Already have a partially-substituted pack");
+  assert((!PartiallySubstitutedPack 
+          || NumArgsInPartiallySubstitutedPack == NumExplicitArgs) &&
+         "Wrong number of arguments in partially-substituted pack");
+  PartiallySubstitutedPack = Pack;
+  ArgsInPartiallySubstitutedPack = ExplicitArgs;
+  NumArgsInPartiallySubstitutedPack = NumExplicitArgs;
+}
+
+NamedDecl *LocalInstantiationScope::getPartiallySubstitutedPack(
+                                         const TemplateArgument **ExplicitArgs,
+                                              unsigned *NumExplicitArgs) const {
+  if (ExplicitArgs)
+    *ExplicitArgs = 0;
+  if (NumExplicitArgs)
+    *NumExplicitArgs = 0;
+  
+  for (const LocalInstantiationScope *Current = this; Current; 
+       Current = Current->Outer) {
+    if (Current->PartiallySubstitutedPack) {
+      if (ExplicitArgs)
+        *ExplicitArgs = Current->ArgsInPartiallySubstitutedPack;
+      if (NumExplicitArgs)
+        *NumExplicitArgs = Current->NumArgsInPartiallySubstitutedPack;
+      
+      return Current->PartiallySubstitutedPack;
+    }
+
+    if (!Current->CombineWithOuterScope)
+      break;
+  }
+  
+  return 0;
+}
diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
new file mode 100644
index 0000000..c7bd99c
--- /dev/null
+++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -0,0 +1,3502 @@
+//===--- SemaTemplateInstantiateDecl.cpp - C++ Template Decl Instantiation ===/
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//===----------------------------------------------------------------------===/
+//
+//  This file implements C++ template instantiation for declarations.
+//
+//===----------------------------------------------------------------------===/
+#include "clang/Sema/SemaInternal.h"
+#include "clang/Sema/Lookup.h"
+#include "clang/Sema/PrettyDeclStackTrace.h"
+#include "clang/Sema/Template.h"
+#include "clang/AST/ASTConsumer.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/DeclTemplate.h"
+#include "clang/AST/DeclVisitor.h"
+#include "clang/AST/DependentDiagnostic.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/ExprCXX.h"
+#include "clang/AST/TypeLoc.h"
+#include "clang/Lex/Preprocessor.h"
+
+using namespace clang;
+
+bool TemplateDeclInstantiator::SubstQualifier(const DeclaratorDecl *OldDecl,
+                                              DeclaratorDecl *NewDecl) {
+  if (!OldDecl->getQualifierLoc())
+    return false;
+
+  NestedNameSpecifierLoc NewQualifierLoc
+    = SemaRef.SubstNestedNameSpecifierLoc(OldDecl->getQualifierLoc(),
+                                          TemplateArgs);
+
+  if (!NewQualifierLoc)
+    return true;
+
+  NewDecl->setQualifierInfo(NewQualifierLoc);
+  return false;
+}
+
+bool TemplateDeclInstantiator::SubstQualifier(const TagDecl *OldDecl,
+                                              TagDecl *NewDecl) {
+  if (!OldDecl->getQualifierLoc())
+    return false;
+
+  NestedNameSpecifierLoc NewQualifierLoc
+  = SemaRef.SubstNestedNameSpecifierLoc(OldDecl->getQualifierLoc(),
+                                        TemplateArgs);
+
+  if (!NewQualifierLoc)
+    return true;
+
+  NewDecl->setQualifierInfo(NewQualifierLoc);
+  return false;
+}
+
+// Include attribute instantiation code.
+#include "clang/Sema/AttrTemplateInstantiate.inc"
+
+void Sema::InstantiateAttrs(const MultiLevelTemplateArgumentList &TemplateArgs,
+                            const Decl *Tmpl, Decl *New,
+                            LateInstantiatedAttrVec *LateAttrs,
+                            LocalInstantiationScope *OuterMostScope) {
+  for (AttrVec::const_iterator i = Tmpl->attr_begin(), e = Tmpl->attr_end();
+       i != e; ++i) {
+    const Attr *TmplAttr = *i;
+
+    // FIXME: This should be generalized to more than just the AlignedAttr.
+    if (const AlignedAttr *Aligned = dyn_cast<AlignedAttr>(TmplAttr)) {
+      if (Aligned->isAlignmentDependent()) {
+        if (Aligned->isAlignmentExpr()) {
+          // The alignment expression is a constant expression.
+          EnterExpressionEvaluationContext Unevaluated(*this,
+                                                       Sema::ConstantEvaluated);
+
+          ExprResult Result = SubstExpr(Aligned->getAlignmentExpr(),
+                                        TemplateArgs);
+          if (!Result.isInvalid())
+            AddAlignedAttr(Aligned->getLocation(), New, Result.takeAs<Expr>());
+        } else {
+          TypeSourceInfo *Result = SubstType(Aligned->getAlignmentType(),
+                                             TemplateArgs,
+                                             Aligned->getLocation(),
+                                             DeclarationName());
+          if (Result)
+            AddAlignedAttr(Aligned->getLocation(), New, Result);
+        }
+        continue;
+      }
+    }
+
+    if (TmplAttr->isLateParsed() && LateAttrs) {
+      // Late parsed attributes must be instantiated and attached after the
+      // enclosing class has been instantiated.  See Sema::InstantiateClass.
+      LocalInstantiationScope *Saved = 0;
+      if (CurrentInstantiationScope)
+        Saved = CurrentInstantiationScope->cloneScopes(OuterMostScope);
+      LateAttrs->push_back(LateInstantiatedAttribute(TmplAttr, Saved, New));
+    } else {
+      Attr *NewAttr = sema::instantiateTemplateAttribute(TmplAttr, Context,
+                                                         *this, TemplateArgs);
+      New->addAttr(NewAttr);
+    }
+  }
+}
+
+Decl *
+TemplateDeclInstantiator::VisitTranslationUnitDecl(TranslationUnitDecl *D) {
+  llvm_unreachable("Translation units cannot be instantiated");
+}
+
+Decl *
+TemplateDeclInstantiator::VisitLabelDecl(LabelDecl *D) {
+  LabelDecl *Inst = LabelDecl::Create(SemaRef.Context, Owner, D->getLocation(),
+                                      D->getIdentifier());
+  Owner->addDecl(Inst);
+  return Inst;
+}
+
+Decl *
+TemplateDeclInstantiator::VisitNamespaceDecl(NamespaceDecl *D) {
+  llvm_unreachable("Namespaces cannot be instantiated");
+}
+
+Decl *
+TemplateDeclInstantiator::VisitNamespaceAliasDecl(NamespaceAliasDecl *D) {
+  NamespaceAliasDecl *Inst
+    = NamespaceAliasDecl::Create(SemaRef.Context, Owner,
+                                 D->getNamespaceLoc(),
+                                 D->getAliasLoc(),
+                                 D->getIdentifier(),
+                                 D->getQualifierLoc(),
+                                 D->getTargetNameLoc(),
+                                 D->getNamespace());
+  Owner->addDecl(Inst);
+  return Inst;
+}
+
+Decl *TemplateDeclInstantiator::InstantiateTypedefNameDecl(TypedefNameDecl *D,
+                                                           bool IsTypeAlias) {
+  bool Invalid = false;
+  TypeSourceInfo *DI = D->getTypeSourceInfo();
+  if (DI->getType()->isInstantiationDependentType() ||
+      DI->getType()->isVariablyModifiedType()) {
+    DI = SemaRef.SubstType(DI, TemplateArgs,
+                           D->getLocation(), D->getDeclName());
+    if (!DI) {
+      Invalid = true;
+      DI = SemaRef.Context.getTrivialTypeSourceInfo(SemaRef.Context.IntTy);
+    }
+  } else {
+    SemaRef.MarkDeclarationsReferencedInType(D->getLocation(), DI->getType());
+  }
+
+  // Create the new typedef
+  TypedefNameDecl *Typedef;
+  if (IsTypeAlias)
+    Typedef = TypeAliasDecl::Create(SemaRef.Context, Owner, D->getLocStart(),
+                                    D->getLocation(), D->getIdentifier(), DI);
+  else
+    Typedef = TypedefDecl::Create(SemaRef.Context, Owner, D->getLocStart(),
+                                  D->getLocation(), D->getIdentifier(), DI);
+  if (Invalid)
+    Typedef->setInvalidDecl();
+
+  // If the old typedef was the name for linkage purposes of an anonymous
+  // tag decl, re-establish that relationship for the new typedef.
+  if (const TagType *oldTagType = D->getUnderlyingType()->getAs<TagType>()) {
+    TagDecl *oldTag = oldTagType->getDecl();
+    if (oldTag->getTypedefNameForAnonDecl() == D) {
+      TagDecl *newTag = DI->getType()->castAs<TagType>()->getDecl();
+      assert(!newTag->getIdentifier() && !newTag->getTypedefNameForAnonDecl());
+      newTag->setTypedefNameForAnonDecl(Typedef);
+    }
+  }
+
+  if (TypedefNameDecl *Prev = D->getPreviousDecl()) {
+    NamedDecl *InstPrev = SemaRef.FindInstantiatedDecl(D->getLocation(), Prev,
+                                                       TemplateArgs);
+    if (!InstPrev)
+      return 0;
+
+    TypedefNameDecl *InstPrevTypedef = cast<TypedefNameDecl>(InstPrev);
+
+    // If the typedef types are not identical, reject them.
+    SemaRef.isIncompatibleTypedef(InstPrevTypedef, Typedef);
+
+    Typedef->setPreviousDeclaration(InstPrevTypedef);
+  }
+
+  SemaRef.InstantiateAttrs(TemplateArgs, D, Typedef);
+
+  Typedef->setAccess(D->getAccess());
+
+  return Typedef;
+}
+
+Decl *TemplateDeclInstantiator::VisitTypedefDecl(TypedefDecl *D) {
+  Decl *Typedef = InstantiateTypedefNameDecl(D, /*IsTypeAlias=*/false);
+  Owner->addDecl(Typedef);
+  return Typedef;
+}
+
+Decl *TemplateDeclInstantiator::VisitTypeAliasDecl(TypeAliasDecl *D) {
+  Decl *Typedef = InstantiateTypedefNameDecl(D, /*IsTypeAlias=*/true);
+  Owner->addDecl(Typedef);
+  return Typedef;
+}
+
+Decl *
+TemplateDeclInstantiator::VisitTypeAliasTemplateDecl(TypeAliasTemplateDecl *D) {
+  // Create a local instantiation scope for this type alias template, which
+  // will contain the instantiations of the template parameters.
+  LocalInstantiationScope Scope(SemaRef);
+
+  TemplateParameterList *TempParams = D->getTemplateParameters();
+  TemplateParameterList *InstParams = SubstTemplateParams(TempParams);
+  if (!InstParams)
+    return 0;
+
+  TypeAliasDecl *Pattern = D->getTemplatedDecl();
+
+  TypeAliasTemplateDecl *PrevAliasTemplate = 0;
+  if (Pattern->getPreviousDecl()) {
+    DeclContext::lookup_result Found = Owner->lookup(Pattern->getDeclName());
+    if (Found.first != Found.second) {
+      PrevAliasTemplate = dyn_cast<TypeAliasTemplateDecl>(*Found.first);
+    }
+  }
+
+  TypeAliasDecl *AliasInst = cast_or_null<TypeAliasDecl>(
+    InstantiateTypedefNameDecl(Pattern, /*IsTypeAlias=*/true));
+  if (!AliasInst)
+    return 0;
+
+  TypeAliasTemplateDecl *Inst
+    = TypeAliasTemplateDecl::Create(SemaRef.Context, Owner, D->getLocation(),
+                                    D->getDeclName(), InstParams, AliasInst);
+  if (PrevAliasTemplate)
+    Inst->setPreviousDeclaration(PrevAliasTemplate);
+
+  Inst->setAccess(D->getAccess());
+
+  if (!PrevAliasTemplate)
+    Inst->setInstantiatedFromMemberTemplate(D);
+
+  Owner->addDecl(Inst);
+
+  return Inst;
+}
+
+Decl *TemplateDeclInstantiator::VisitVarDecl(VarDecl *D) {
+  // If this is the variable for an anonymous struct or union,
+  // instantiate the anonymous struct/union type first.
+  if (const RecordType *RecordTy = D->getType()->getAs<RecordType>())
+    if (RecordTy->getDecl()->isAnonymousStructOrUnion())
+      if (!VisitCXXRecordDecl(cast<CXXRecordDecl>(RecordTy->getDecl())))
+        return 0;
+
+  // Do substitution on the type of the declaration
+  TypeSourceInfo *DI = SemaRef.SubstType(D->getTypeSourceInfo(),
+                                         TemplateArgs,
+                                         D->getTypeSpecStartLoc(),
+                                         D->getDeclName());
+  if (!DI)
+    return 0;
+
+  if (DI->getType()->isFunctionType()) {
+    SemaRef.Diag(D->getLocation(), diag::err_variable_instantiates_to_function)
+      << D->isStaticDataMember() << DI->getType();
+    return 0;
+  }
+
+  // Build the instantiated declaration
+  VarDecl *Var = VarDecl::Create(SemaRef.Context, Owner,
+                                 D->getInnerLocStart(),
+                                 D->getLocation(), D->getIdentifier(),
+                                 DI->getType(), DI,
+                                 D->getStorageClass(),
+                                 D->getStorageClassAsWritten());
+  Var->setThreadSpecified(D->isThreadSpecified());
+  Var->setInitStyle(D->getInitStyle());
+  Var->setCXXForRangeDecl(D->isCXXForRangeDecl());
+  Var->setConstexpr(D->isConstexpr());
+
+  // Substitute the nested name specifier, if any.
+  if (SubstQualifier(D, Var))
+    return 0;
+
+  // If we are instantiating a static data member defined
+  // out-of-line, the instantiation will have the same lexical
+  // context (which will be a namespace scope) as the template.
+  if (D->isOutOfLine())
+    Var->setLexicalDeclContext(D->getLexicalDeclContext());
+
+  Var->setAccess(D->getAccess());
+
+  if (!D->isStaticDataMember()) {
+    Var->setUsed(D->isUsed(false));
+    Var->setReferenced(D->isReferenced());
+  }
+
+  // FIXME: In theory, we could have a previous declaration for variables that
+  // are not static data members.
+  // FIXME: having to fake up a LookupResult is dumb.
+  LookupResult Previous(SemaRef, Var->getDeclName(), Var->getLocation(),
+                        Sema::LookupOrdinaryName, Sema::ForRedeclaration);
+  if (D->isStaticDataMember())
+    SemaRef.LookupQualifiedName(Previous, Owner, false);
+  
+  // In ARC, infer 'retaining' for variables of retainable type.
+  if (SemaRef.getLangOpts().ObjCAutoRefCount && 
+      SemaRef.inferObjCARCLifetime(Var))
+    Var->setInvalidDecl();
+
+  SemaRef.CheckVariableDeclaration(Var, Previous);
+
+  if (D->isOutOfLine()) {
+    D->getLexicalDeclContext()->addDecl(Var);
+    Owner->makeDeclVisibleInContext(Var);
+  } else {
+    Owner->addDecl(Var);
+    if (Owner->isFunctionOrMethod())
+      SemaRef.CurrentInstantiationScope->InstantiatedLocal(D, Var);
+  }
+  SemaRef.InstantiateAttrs(TemplateArgs, D, Var, LateAttrs, StartingScope);
+
+  // Link instantiations of static data members back to the template from
+  // which they were instantiated.
+  if (Var->isStaticDataMember())
+    SemaRef.Context.setInstantiatedFromStaticDataMember(Var, D,
+                                                     TSK_ImplicitInstantiation);
+
+  if (Var->getAnyInitializer()) {
+    // We already have an initializer in the class.
+  } else if (D->getInit()) {
+    if (Var->isStaticDataMember() && !D->isOutOfLine())
+      SemaRef.PushExpressionEvaluationContext(Sema::ConstantEvaluated);
+    else
+      SemaRef.PushExpressionEvaluationContext(Sema::PotentiallyEvaluated);
+
+    // Instantiate the initializer.
+    ExprResult Init = SemaRef.SubstInitializer(D->getInit(), TemplateArgs,
+                                        D->getInitStyle() == VarDecl::CallInit);
+    if (!Init.isInvalid()) {
+      bool TypeMayContainAuto = true;
+      if (Init.get()) {
+        bool DirectInit = D->isDirectInit();
+        SemaRef.AddInitializerToDecl(Var, Init.take(), DirectInit,
+                                     TypeMayContainAuto);
+      } else
+        SemaRef.ActOnUninitializedDecl(Var, TypeMayContainAuto);
+    } else {
+      // FIXME: Not too happy about invalidating the declaration
+      // because of a bogus initializer.
+      Var->setInvalidDecl();
+    }
+
+    SemaRef.PopExpressionEvaluationContext();
+  } else if ((!Var->isStaticDataMember() || Var->isOutOfLine()) &&
+             !Var->isCXXForRangeDecl())
+    SemaRef.ActOnUninitializedDecl(Var, false);
+
+  // Diagnose unused local variables with dependent types, where the diagnostic
+  // will have been deferred.
+  if (!Var->isInvalidDecl() && Owner->isFunctionOrMethod() && !Var->isUsed() &&
+      D->getType()->isDependentType())
+    SemaRef.DiagnoseUnusedDecl(Var);
+
+  return Var;
+}
+
+Decl *TemplateDeclInstantiator::VisitAccessSpecDecl(AccessSpecDecl *D) {
+  AccessSpecDecl* AD
+    = AccessSpecDecl::Create(SemaRef.Context, D->getAccess(), Owner,
+                             D->getAccessSpecifierLoc(), D->getColonLoc());
+  Owner->addHiddenDecl(AD);
+  return AD;
+}
+
+Decl *TemplateDeclInstantiator::VisitFieldDecl(FieldDecl *D) {
+  bool Invalid = false;
+  TypeSourceInfo *DI = D->getTypeSourceInfo();
+  if (DI->getType()->isInstantiationDependentType() ||
+      DI->getType()->isVariablyModifiedType())  {
+    DI = SemaRef.SubstType(DI, TemplateArgs,
+                           D->getLocation(), D->getDeclName());
+    if (!DI) {
+      DI = D->getTypeSourceInfo();
+      Invalid = true;
+    } else if (DI->getType()->isFunctionType()) {
+      // C++ [temp.arg.type]p3:
+      //   If a declaration acquires a function type through a type
+      //   dependent on a template-parameter and this causes a
+      //   declaration that does not use the syntactic form of a
+      //   function declarator to have function type, the program is
+      //   ill-formed.
+      SemaRef.Diag(D->getLocation(), diag::err_field_instantiates_to_function)
+        << DI->getType();
+      Invalid = true;
+    }
+  } else {
+    SemaRef.MarkDeclarationsReferencedInType(D->getLocation(), DI->getType());
+  }
+
+  Expr *BitWidth = D->getBitWidth();
+  if (Invalid)
+    BitWidth = 0;
+  else if (BitWidth) {
+    // The bit-width expression is a constant expression.
+    EnterExpressionEvaluationContext Unevaluated(SemaRef,
+                                                 Sema::ConstantEvaluated);
+
+    ExprResult InstantiatedBitWidth
+      = SemaRef.SubstExpr(BitWidth, TemplateArgs);
+    if (InstantiatedBitWidth.isInvalid()) {
+      Invalid = true;
+      BitWidth = 0;
+    } else
+      BitWidth = InstantiatedBitWidth.takeAs<Expr>();
+  }
+
+  FieldDecl *Field = SemaRef.CheckFieldDecl(D->getDeclName(),
+                                            DI->getType(), DI,
+                                            cast<RecordDecl>(Owner),
+                                            D->getLocation(),
+                                            D->isMutable(),
+                                            BitWidth,
+                                            D->hasInClassInitializer(),
+                                            D->getTypeSpecStartLoc(),
+                                            D->getAccess(),
+                                            0);
+  if (!Field) {
+    cast<Decl>(Owner)->setInvalidDecl();
+    return 0;
+  }
+
+  SemaRef.InstantiateAttrs(TemplateArgs, D, Field, LateAttrs, StartingScope);
+
+  if (Invalid)
+    Field->setInvalidDecl();
+
+  if (!Field->getDeclName()) {
+    // Keep track of where this decl came from.
+    SemaRef.Context.setInstantiatedFromUnnamedFieldDecl(Field, D);
+  }
+  if (CXXRecordDecl *Parent= dyn_cast<CXXRecordDecl>(Field->getDeclContext())) {
+    if (Parent->isAnonymousStructOrUnion() &&
+        Parent->getRedeclContext()->isFunctionOrMethod())
+      SemaRef.CurrentInstantiationScope->InstantiatedLocal(D, Field);
+  }
+
+  Field->setImplicit(D->isImplicit());
+  Field->setAccess(D->getAccess());
+  Owner->addDecl(Field);
+
+  return Field;
+}
+
+Decl *TemplateDeclInstantiator::VisitIndirectFieldDecl(IndirectFieldDecl *D) {
+  NamedDecl **NamedChain =
+    new (SemaRef.Context)NamedDecl*[D->getChainingSize()];
+
+  int i = 0;
+  for (IndirectFieldDecl::chain_iterator PI =
+       D->chain_begin(), PE = D->chain_end();
+       PI != PE; ++PI) {
+    NamedDecl *Next = SemaRef.FindInstantiatedDecl(D->getLocation(), *PI,
+                                              TemplateArgs);
+    if (!Next)
+      return 0;
+
+    NamedChain[i++] = Next;
+  }
+
+  QualType T = cast<FieldDecl>(NamedChain[i-1])->getType();
+  IndirectFieldDecl* IndirectField
+    = IndirectFieldDecl::Create(SemaRef.Context, Owner, D->getLocation(),
+                                D->getIdentifier(), T,
+                                NamedChain, D->getChainingSize());
+
+
+  IndirectField->setImplicit(D->isImplicit());
+  IndirectField->setAccess(D->getAccess());
+  Owner->addDecl(IndirectField);
+  return IndirectField;
+}
+
+Decl *TemplateDeclInstantiator::VisitFriendDecl(FriendDecl *D) {
+  // Handle friend type expressions by simply substituting template
+  // parameters into the pattern type and checking the result.
+  if (TypeSourceInfo *Ty = D->getFriendType()) {
+    TypeSourceInfo *InstTy;
+    // If this is an unsupported friend, don't bother substituting template
+    // arguments into it. The actual type referred to won't be used by any
+    // parts of Clang, and may not be valid for instantiating. Just use the
+    // same info for the instantiated friend.
+    if (D->isUnsupportedFriend()) {
+      InstTy = Ty;
+    } else {
+      InstTy = SemaRef.SubstType(Ty, TemplateArgs,
+                                 D->getLocation(), DeclarationName());
+    }
+    if (!InstTy)
+      return 0;
+
+    FriendDecl *FD = SemaRef.CheckFriendTypeDecl(D->getLocation(),
+                                                 D->getFriendLoc(), InstTy);
+    if (!FD)
+      return 0;
+
+    FD->setAccess(AS_public);
+    FD->setUnsupportedFriend(D->isUnsupportedFriend());
+    Owner->addDecl(FD);
+    return FD;
+  }
+
+  NamedDecl *ND = D->getFriendDecl();
+  assert(ND && "friend decl must be a decl or a type!");
+
+  // All of the Visit implementations for the various potential friend
+  // declarations have to be carefully written to work for friend
+  // objects, with the most important detail being that the target
+  // decl should almost certainly not be placed in Owner.
+  Decl *NewND = Visit(ND);
+  if (!NewND) return 0;
+
+  FriendDecl *FD =
+    FriendDecl::Create(SemaRef.Context, Owner, D->getLocation(),
+                       cast<NamedDecl>(NewND), D->getFriendLoc());
+  FD->setAccess(AS_public);
+  FD->setUnsupportedFriend(D->isUnsupportedFriend());
+  Owner->addDecl(FD);
+  return FD;
+}
+
+Decl *TemplateDeclInstantiator::VisitStaticAssertDecl(StaticAssertDecl *D) {
+  Expr *AssertExpr = D->getAssertExpr();
+
+  // The expression in a static assertion is a constant expression.
+  EnterExpressionEvaluationContext Unevaluated(SemaRef,
+                                               Sema::ConstantEvaluated);
+
+  ExprResult InstantiatedAssertExpr
+    = SemaRef.SubstExpr(AssertExpr, TemplateArgs);
+  if (InstantiatedAssertExpr.isInvalid())
+    return 0;
+
+  ExprResult Message(D->getMessage());
+  D->getMessage();
+  return SemaRef.ActOnStaticAssertDeclaration(D->getLocation(),
+                                              InstantiatedAssertExpr.get(),
+                                              Message.get(),
+                                              D->getRParenLoc());
+}
+
+Decl *TemplateDeclInstantiator::VisitEnumDecl(EnumDecl *D) {
+  EnumDecl *PrevDecl = 0;
+  if (D->getPreviousDecl()) {
+    NamedDecl *Prev = SemaRef.FindInstantiatedDecl(D->getLocation(),
+                                                   D->getPreviousDecl(),
+                                                   TemplateArgs);
+    if (!Prev) return 0;
+    PrevDecl = cast<EnumDecl>(Prev);
+  }
+
+  EnumDecl *Enum = EnumDecl::Create(SemaRef.Context, Owner, D->getLocStart(),
+                                    D->getLocation(), D->getIdentifier(),
+                                    PrevDecl, D->isScoped(),
+                                    D->isScopedUsingClassTag(), D->isFixed());
+  if (D->isFixed()) {
+    if (TypeSourceInfo *TI = D->getIntegerTypeSourceInfo()) {
+      // If we have type source information for the underlying type, it means it
+      // has been explicitly set by the user. Perform substitution on it before
+      // moving on.
+      SourceLocation UnderlyingLoc = TI->getTypeLoc().getBeginLoc();
+      TypeSourceInfo *NewTI = SemaRef.SubstType(TI, TemplateArgs, UnderlyingLoc,
+                                                DeclarationName());
+      if (!NewTI || SemaRef.CheckEnumUnderlyingType(NewTI))
+        Enum->setIntegerType(SemaRef.Context.IntTy);
+      else
+        Enum->setIntegerTypeSourceInfo(NewTI);
+    } else {
+      assert(!D->getIntegerType()->isDependentType()
+             && "Dependent type without type source info");
+      Enum->setIntegerType(D->getIntegerType());
+    }
+  }
+
+  SemaRef.InstantiateAttrs(TemplateArgs, D, Enum);
+
+  Enum->setInstantiationOfMemberEnum(D, TSK_ImplicitInstantiation);
+  Enum->setAccess(D->getAccess());
+  if (SubstQualifier(D, Enum)) return 0;
+  Owner->addDecl(Enum);
+
+  EnumDecl *Def = D->getDefinition();
+  if (Def && Def != D) {
+    // If this is an out-of-line definition of an enum member template, check
+    // that the underlying types match in the instantiation of both
+    // declarations.
+    if (TypeSourceInfo *TI = Def->getIntegerTypeSourceInfo()) {
+      SourceLocation UnderlyingLoc = TI->getTypeLoc().getBeginLoc();
+      QualType DefnUnderlying =
+        SemaRef.SubstType(TI->getType(), TemplateArgs,
+                          UnderlyingLoc, DeclarationName());
+      SemaRef.CheckEnumRedeclaration(Def->getLocation(), Def->isScoped(),
+                                     DefnUnderlying, Enum);
+    }
+  }
+
+  if (D->getDeclContext()->isFunctionOrMethod())
+    SemaRef.CurrentInstantiationScope->InstantiatedLocal(D, Enum);
+
+  // C++11 [temp.inst]p1: The implicit instantiation of a class template
+  // specialization causes the implicit instantiation of the declarations, but
+  // not the definitions of scoped member enumerations.
+  // FIXME: There appears to be no wording for what happens for an enum defined
+  // within a block scope, but we treat that much like a member template. Only
+  // instantiate the definition when visiting the definition in that case, since
+  // we will visit all redeclarations.
+  if (!Enum->isScoped() && Def &&
+      (!D->getDeclContext()->isFunctionOrMethod() || D->isCompleteDefinition()))
+    InstantiateEnumDefinition(Enum, Def);
+
+  return Enum;
+}
+
+void TemplateDeclInstantiator::InstantiateEnumDefinition(
+    EnumDecl *Enum, EnumDecl *Pattern) {
+  Enum->startDefinition();
+
+  // Update the location to refer to the definition.
+  Enum->setLocation(Pattern->getLocation());
+
+  SmallVector<Decl*, 4> Enumerators;
+
+  EnumConstantDecl *LastEnumConst = 0;
+  for (EnumDecl::enumerator_iterator EC = Pattern->enumerator_begin(),
+         ECEnd = Pattern->enumerator_end();
+       EC != ECEnd; ++EC) {
+    // The specified value for the enumerator.
+    ExprResult Value = SemaRef.Owned((Expr *)0);
+    if (Expr *UninstValue = EC->getInitExpr()) {
+      // The enumerator's value expression is a constant expression.
+      EnterExpressionEvaluationContext Unevaluated(SemaRef,
+                                                   Sema::ConstantEvaluated);
+
+      Value = SemaRef.SubstExpr(UninstValue, TemplateArgs);
+    }
+
+    // Drop the initial value and continue.
+    bool isInvalid = false;
+    if (Value.isInvalid()) {
+      Value = SemaRef.Owned((Expr *)0);
+      isInvalid = true;
+    }
+
+    EnumConstantDecl *EnumConst
+      = SemaRef.CheckEnumConstant(Enum, LastEnumConst,
+                                  EC->getLocation(), EC->getIdentifier(),
+                                  Value.get());
+
+    if (isInvalid) {
+      if (EnumConst)
+        EnumConst->setInvalidDecl();
+      Enum->setInvalidDecl();
+    }
+
+    if (EnumConst) {
+      SemaRef.InstantiateAttrs(TemplateArgs, *EC, EnumConst);
+
+      EnumConst->setAccess(Enum->getAccess());
+      Enum->addDecl(EnumConst);
+      Enumerators.push_back(EnumConst);
+      LastEnumConst = EnumConst;
+
+      if (Pattern->getDeclContext()->isFunctionOrMethod() &&
+          !Enum->isScoped()) {
+        // If the enumeration is within a function or method, record the enum
+        // constant as a local.
+        SemaRef.CurrentInstantiationScope->InstantiatedLocal(*EC, EnumConst);
+      }
+    }
+  }
+
+  // FIXME: Fixup LBraceLoc
+  SemaRef.ActOnEnumBody(Enum->getLocation(), SourceLocation(),
+                        Enum->getRBraceLoc(), Enum,
+                        Enumerators.data(), Enumerators.size(),
+                        0, 0);
+}
+
+Decl *TemplateDeclInstantiator::VisitEnumConstantDecl(EnumConstantDecl *D) {
+  llvm_unreachable("EnumConstantDecls can only occur within EnumDecls.");
+}
+
+Decl *TemplateDeclInstantiator::VisitClassTemplateDecl(ClassTemplateDecl *D) {
+  bool isFriend = (D->getFriendObjectKind() != Decl::FOK_None);
+
+  // Create a local instantiation scope for this class template, which
+  // will contain the instantiations of the template parameters.
+  LocalInstantiationScope Scope(SemaRef);
+  TemplateParameterList *TempParams = D->getTemplateParameters();
+  TemplateParameterList *InstParams = SubstTemplateParams(TempParams);
+  if (!InstParams)
+    return NULL;
+
+  CXXRecordDecl *Pattern = D->getTemplatedDecl();
+
+  // Instantiate the qualifier.  We have to do this first in case
+  // we're a friend declaration, because if we are then we need to put
+  // the new declaration in the appropriate context.
+  NestedNameSpecifierLoc QualifierLoc = Pattern->getQualifierLoc();
+  if (QualifierLoc) {
+    QualifierLoc = SemaRef.SubstNestedNameSpecifierLoc(QualifierLoc,
+                                                       TemplateArgs);
+    if (!QualifierLoc)
+      return 0;
+  }
+
+  CXXRecordDecl *PrevDecl = 0;
+  ClassTemplateDecl *PrevClassTemplate = 0;
+
+  if (!isFriend && Pattern->getPreviousDecl()) {
+    DeclContext::lookup_result Found = Owner->lookup(Pattern->getDeclName());
+    if (Found.first != Found.second) {
+      PrevClassTemplate = dyn_cast<ClassTemplateDecl>(*Found.first);
+      if (PrevClassTemplate)
+        PrevDecl = PrevClassTemplate->getTemplatedDecl();
+    }
+  }
+
+  // If this isn't a friend, then it's a member template, in which
+  // case we just want to build the instantiation in the
+  // specialization.  If it is a friend, we want to build it in
+  // the appropriate context.
+  DeclContext *DC = Owner;
+  if (isFriend) {
+    if (QualifierLoc) {
+      CXXScopeSpec SS;
+      SS.Adopt(QualifierLoc);
+      DC = SemaRef.computeDeclContext(SS);
+      if (!DC) return 0;
+    } else {
+      DC = SemaRef.FindInstantiatedContext(Pattern->getLocation(),
+                                           Pattern->getDeclContext(),
+                                           TemplateArgs);
+    }
+
+    // Look for a previous declaration of the template in the owning
+    // context.
+    LookupResult R(SemaRef, Pattern->getDeclName(), Pattern->getLocation(),
+                   Sema::LookupOrdinaryName, Sema::ForRedeclaration);
+    SemaRef.LookupQualifiedName(R, DC);
+
+    if (R.isSingleResult()) {
+      PrevClassTemplate = R.getAsSingle<ClassTemplateDecl>();
+      if (PrevClassTemplate)
+        PrevDecl = PrevClassTemplate->getTemplatedDecl();
+    }
+
+    if (!PrevClassTemplate && QualifierLoc) {
+      SemaRef.Diag(Pattern->getLocation(), diag::err_not_tag_in_scope)
+        << D->getTemplatedDecl()->getTagKind() << Pattern->getDeclName() << DC
+        << QualifierLoc.getSourceRange();
+      return 0;
+    }
+
+    bool AdoptedPreviousTemplateParams = false;
+    if (PrevClassTemplate) {
+      bool Complain = true;
+
+      // HACK: libstdc++ 4.2.1 contains an ill-formed friend class
+      // template for struct std::tr1::__detail::_Map_base, where the
+      // template parameters of the friend declaration don't match the
+      // template parameters of the original declaration. In this one
+      // case, we don't complain about the ill-formed friend
+      // declaration.
+      if (isFriend && Pattern->getIdentifier() &&
+          Pattern->getIdentifier()->isStr("_Map_base") &&
+          DC->isNamespace() &&
+          cast<NamespaceDecl>(DC)->getIdentifier() &&
+          cast<NamespaceDecl>(DC)->getIdentifier()->isStr("__detail")) {
+        DeclContext *DCParent = DC->getParent();
+        if (DCParent->isNamespace() &&
+            cast<NamespaceDecl>(DCParent)->getIdentifier() &&
+            cast<NamespaceDecl>(DCParent)->getIdentifier()->isStr("tr1")) {
+          DeclContext *DCParent2 = DCParent->getParent();
+          if (DCParent2->isNamespace() &&
+              cast<NamespaceDecl>(DCParent2)->getIdentifier() &&
+              cast<NamespaceDecl>(DCParent2)->getIdentifier()->isStr("std") &&
+              DCParent2->getParent()->isTranslationUnit())
+            Complain = false;
+        }
+      }
+
+      TemplateParameterList *PrevParams
+        = PrevClassTemplate->getTemplateParameters();
+
+      // Make sure the parameter lists match.
+      if (!SemaRef.TemplateParameterListsAreEqual(InstParams, PrevParams,
+                                                  Complain,
+                                                  Sema::TPL_TemplateMatch)) {
+        if (Complain)
+          return 0;
+
+        AdoptedPreviousTemplateParams = true;
+        InstParams = PrevParams;
+      }
+
+      // Do some additional validation, then merge default arguments
+      // from the existing declarations.
+      if (!AdoptedPreviousTemplateParams &&
+          SemaRef.CheckTemplateParameterList(InstParams, PrevParams,
+                                             Sema::TPC_ClassTemplate))
+        return 0;
+    }
+  }
+
+  CXXRecordDecl *RecordInst
+    = CXXRecordDecl::Create(SemaRef.Context, Pattern->getTagKind(), DC,
+                            Pattern->getLocStart(), Pattern->getLocation(),
+                            Pattern->getIdentifier(), PrevDecl,
+                            /*DelayTypeCreation=*/true);
+
+  if (QualifierLoc)
+    RecordInst->setQualifierInfo(QualifierLoc);
+
+  ClassTemplateDecl *Inst
+    = ClassTemplateDecl::Create(SemaRef.Context, DC, D->getLocation(),
+                                D->getIdentifier(), InstParams, RecordInst,
+                                PrevClassTemplate);
+  RecordInst->setDescribedClassTemplate(Inst);
+
+  if (isFriend) {
+    if (PrevClassTemplate)
+      Inst->setAccess(PrevClassTemplate->getAccess());
+    else
+      Inst->setAccess(D->getAccess());
+
+    Inst->setObjectOfFriendDecl(PrevClassTemplate != 0);
+    // TODO: do we want to track the instantiation progeny of this
+    // friend target decl?
+  } else {
+    Inst->setAccess(D->getAccess());
+    if (!PrevClassTemplate)
+      Inst->setInstantiatedFromMemberTemplate(D);
+  }
+
+  // Trigger creation of the type for the instantiation.
+  SemaRef.Context.getInjectedClassNameType(RecordInst,
+                                    Inst->getInjectedClassNameSpecialization());
+
+  // Finish handling of friends.
+  if (isFriend) {
+    DC->makeDeclVisibleInContext(Inst);
+    Inst->setLexicalDeclContext(Owner);
+    RecordInst->setLexicalDeclContext(Owner);
+    return Inst;
+  }
+
+  if (D->isOutOfLine()) {
+    Inst->setLexicalDeclContext(D->getLexicalDeclContext());
+    RecordInst->setLexicalDeclContext(D->getLexicalDeclContext());
+  }
+
+  Owner->addDecl(Inst);
+
+  if (!PrevClassTemplate) {
+    // Queue up any out-of-line partial specializations of this member
+    // class template; the client will force their instantiation once
+    // the enclosing class has been instantiated.
+    SmallVector<ClassTemplatePartialSpecializationDecl *, 4> PartialSpecs;
+    D->getPartialSpecializations(PartialSpecs);
+    for (unsigned I = 0, N = PartialSpecs.size(); I != N; ++I)
+      if (PartialSpecs[I]->isOutOfLine())
+        OutOfLinePartialSpecs.push_back(std::make_pair(Inst, PartialSpecs[I]));
+  }
+
+  return Inst;
+}
+
+Decl *
+TemplateDeclInstantiator::VisitClassTemplatePartialSpecializationDecl(
+                                   ClassTemplatePartialSpecializationDecl *D) {
+  ClassTemplateDecl *ClassTemplate = D->getSpecializedTemplate();
+
+  // Lookup the already-instantiated declaration in the instantiation
+  // of the class template and return that.
+  DeclContext::lookup_result Found
+    = Owner->lookup(ClassTemplate->getDeclName());
+  if (Found.first == Found.second)
+    return 0;
+
+  ClassTemplateDecl *InstClassTemplate
+    = dyn_cast<ClassTemplateDecl>(*Found.first);
+  if (!InstClassTemplate)
+    return 0;
+
+  if (ClassTemplatePartialSpecializationDecl *Result
+        = InstClassTemplate->findPartialSpecInstantiatedFromMember(D))
+    return Result;
+
+  return InstantiateClassTemplatePartialSpecialization(InstClassTemplate, D);
+}
+
+Decl *
+TemplateDeclInstantiator::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) {
+  // Create a local instantiation scope for this function template, which
+  // will contain the instantiations of the template parameters and then get
+  // merged with the local instantiation scope for the function template
+  // itself.
+  LocalInstantiationScope Scope(SemaRef);
+
+  TemplateParameterList *TempParams = D->getTemplateParameters();
+  TemplateParameterList *InstParams = SubstTemplateParams(TempParams);
+  if (!InstParams)
+    return NULL;
+
+  FunctionDecl *Instantiated = 0;
+  if (CXXMethodDecl *DMethod = dyn_cast<CXXMethodDecl>(D->getTemplatedDecl()))
+    Instantiated = cast_or_null<FunctionDecl>(VisitCXXMethodDecl(DMethod,
+                                                                 InstParams));
+  else
+    Instantiated = cast_or_null<FunctionDecl>(VisitFunctionDecl(
+                                                          D->getTemplatedDecl(),
+                                                                InstParams));
+
+  if (!Instantiated)
+    return 0;
+
+  Instantiated->setAccess(D->getAccess());
+
+  // Link the instantiated function template declaration to the function
+  // template from which it was instantiated.
+  FunctionTemplateDecl *InstTemplate
+    = Instantiated->getDescribedFunctionTemplate();
+  InstTemplate->setAccess(D->getAccess());
+  assert(InstTemplate &&
+         "VisitFunctionDecl/CXXMethodDecl didn't create a template!");
+
+  bool isFriend = (InstTemplate->getFriendObjectKind() != Decl::FOK_None);
+
+  // Link the instantiation back to the pattern *unless* this is a
+  // non-definition friend declaration.
+  if (!InstTemplate->getInstantiatedFromMemberTemplate() &&
+      !(isFriend && !D->getTemplatedDecl()->isThisDeclarationADefinition()))
+    InstTemplate->setInstantiatedFromMemberTemplate(D);
+
+  // Make declarations visible in the appropriate context.
+  if (!isFriend)
+    Owner->addDecl(InstTemplate);
+
+  return InstTemplate;
+}
+
+Decl *TemplateDeclInstantiator::VisitCXXRecordDecl(CXXRecordDecl *D) {
+  CXXRecordDecl *PrevDecl = 0;
+  if (D->isInjectedClassName())
+    PrevDecl = cast<CXXRecordDecl>(Owner);
+  else if (D->getPreviousDecl()) {
+    NamedDecl *Prev = SemaRef.FindInstantiatedDecl(D->getLocation(),
+                                                   D->getPreviousDecl(),
+                                                   TemplateArgs);
+    if (!Prev) return 0;
+    PrevDecl = cast<CXXRecordDecl>(Prev);
+  }
+
+  CXXRecordDecl *Record
+    = CXXRecordDecl::Create(SemaRef.Context, D->getTagKind(), Owner,
+                            D->getLocStart(), D->getLocation(),
+                            D->getIdentifier(), PrevDecl);
+
+  // Substitute the nested name specifier, if any.
+  if (SubstQualifier(D, Record))
+    return 0;
+
+  Record->setImplicit(D->isImplicit());
+  // FIXME: Check against AS_none is an ugly hack to work around the issue that
+  // the tag decls introduced by friend class declarations don't have an access
+  // specifier. Remove once this area of the code gets sorted out.
+  if (D->getAccess() != AS_none)
+    Record->setAccess(D->getAccess());
+  if (!D->isInjectedClassName())
+    Record->setInstantiationOfMemberClass(D, TSK_ImplicitInstantiation);
+
+  // If the original function was part of a friend declaration,
+  // inherit its namespace state.
+  if (Decl::FriendObjectKind FOK = D->getFriendObjectKind())
+    Record->setObjectOfFriendDecl(FOK == Decl::FOK_Declared);
+
+  // Make sure that anonymous structs and unions are recorded.
+  if (D->isAnonymousStructOrUnion()) {
+    Record->setAnonymousStructOrUnion(true);
+    if (Record->getDeclContext()->getRedeclContext()->isFunctionOrMethod())
+      SemaRef.CurrentInstantiationScope->InstantiatedLocal(D, Record);
+  }
+
+  Owner->addDecl(Record);
+  return Record;
+}
+
+/// Normal class members are of more specific types and therefore
+/// don't make it here.  This function serves two purposes:
+///   1) instantiating function templates
+///   2) substituting friend declarations
+/// FIXME: preserve function definitions in case #2
+Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D,
+                                       TemplateParameterList *TemplateParams) {
+  // Check whether there is already a function template specialization for
+  // this declaration.
+  FunctionTemplateDecl *FunctionTemplate = D->getDescribedFunctionTemplate();
+  if (FunctionTemplate && !TemplateParams) {
+    std::pair<const TemplateArgument *, unsigned> Innermost
+      = TemplateArgs.getInnermost();
+
+    void *InsertPos = 0;
+    FunctionDecl *SpecFunc
+      = FunctionTemplate->findSpecialization(Innermost.first, Innermost.second,
+                                             InsertPos);
+
+    // If we already have a function template specialization, return it.
+    if (SpecFunc)
+      return SpecFunc;
+  }
+
+  bool isFriend;
+  if (FunctionTemplate)
+    isFriend = (FunctionTemplate->getFriendObjectKind() != Decl::FOK_None);
+  else
+    isFriend = (D->getFriendObjectKind() != Decl::FOK_None);
+
+  bool MergeWithParentScope = (TemplateParams != 0) ||
+    Owner->isFunctionOrMethod() ||
+    !(isa<Decl>(Owner) &&
+      cast<Decl>(Owner)->isDefinedOutsideFunctionOrMethod());
+  LocalInstantiationScope Scope(SemaRef, MergeWithParentScope);
+
+  SmallVector<ParmVarDecl *, 4> Params;
+  TypeSourceInfo *TInfo = SubstFunctionType(D, Params);
+  if (!TInfo)
+    return 0;
+  QualType T = TInfo->getType();
+
+  NestedNameSpecifierLoc QualifierLoc = D->getQualifierLoc();
+  if (QualifierLoc) {
+    QualifierLoc = SemaRef.SubstNestedNameSpecifierLoc(QualifierLoc,
+                                                       TemplateArgs);
+    if (!QualifierLoc)
+      return 0;
+  }
+
+  // If we're instantiating a local function declaration, put the result
+  // in the owner;  otherwise we need to find the instantiated context.
+  DeclContext *DC;
+  if (D->getDeclContext()->isFunctionOrMethod())
+    DC = Owner;
+  else if (isFriend && QualifierLoc) {
+    CXXScopeSpec SS;
+    SS.Adopt(QualifierLoc);
+    DC = SemaRef.computeDeclContext(SS);
+    if (!DC) return 0;
+  } else {
+    DC = SemaRef.FindInstantiatedContext(D->getLocation(), D->getDeclContext(),
+                                         TemplateArgs);
+  }
+
+  FunctionDecl *Function =
+      FunctionDecl::Create(SemaRef.Context, DC, D->getInnerLocStart(),
+                           D->getLocation(), D->getDeclName(), T, TInfo,
+                           D->getStorageClass(), D->getStorageClassAsWritten(),
+                           D->isInlineSpecified(), D->hasWrittenPrototype(),
+                           D->isConstexpr());
+
+  if (QualifierLoc)
+    Function->setQualifierInfo(QualifierLoc);
+
+  DeclContext *LexicalDC = Owner;
+  if (!isFriend && D->isOutOfLine()) {
+    assert(D->getDeclContext()->isFileContext());
+    LexicalDC = D->getDeclContext();
+  }
+
+  Function->setLexicalDeclContext(LexicalDC);
+
+  // Attach the parameters
+  if (isa<FunctionProtoType>(Function->getType().IgnoreParens())) {
+    // Adopt the already-instantiated parameters into our own context.
+    for (unsigned P = 0; P < Params.size(); ++P)
+      if (Params[P])
+        Params[P]->setOwningFunction(Function);
+  } else {
+    // Since we were instantiated via a typedef of a function type, create
+    // new parameters.
+    const FunctionProtoType *Proto
+      = Function->getType()->getAs<FunctionProtoType>();
+    assert(Proto && "No function prototype in template instantiation?");
+    for (FunctionProtoType::arg_type_iterator AI = Proto->arg_type_begin(),
+         AE = Proto->arg_type_end(); AI != AE; ++AI) {
+      ParmVarDecl *Param
+        = SemaRef.BuildParmVarDeclForTypedef(Function, Function->getLocation(),
+                                             *AI);
+      Param->setScopeInfo(0, Params.size());
+      Params.push_back(Param);
+    }
+  }
+  Function->setParams(Params);
+
+  SourceLocation InstantiateAtPOI;
+  if (TemplateParams) {
+    // Our resulting instantiation is actually a function template, since we
+    // are substituting only the outer template parameters. For example, given
+    //
+    //   template<typename T>
+    //   struct X {
+    //     template<typename U> friend void f(T, U);
+    //   };
+    //
+    //   X<int> x;
+    //
+    // We are instantiating the friend function template "f" within X<int>,
+    // which means substituting int for T, but leaving "f" as a friend function
+    // template.
+    // Build the function template itself.
+    FunctionTemplate = FunctionTemplateDecl::Create(SemaRef.Context, DC,
+                                                    Function->getLocation(),
+                                                    Function->getDeclName(),
+                                                    TemplateParams, Function);
+    Function->setDescribedFunctionTemplate(FunctionTemplate);
+
+    FunctionTemplate->setLexicalDeclContext(LexicalDC);
+
+    if (isFriend && D->isThisDeclarationADefinition()) {
+      // TODO: should we remember this connection regardless of whether
+      // the friend declaration provided a body?
+      FunctionTemplate->setInstantiatedFromMemberTemplate(
+                                           D->getDescribedFunctionTemplate());
+    }
+  } else if (FunctionTemplate) {
+    // Record this function template specialization.
+    std::pair<const TemplateArgument *, unsigned> Innermost
+      = TemplateArgs.getInnermost();
+    Function->setFunctionTemplateSpecialization(FunctionTemplate,
+                            TemplateArgumentList::CreateCopy(SemaRef.Context,
+                                                             Innermost.first,
+                                                             Innermost.second),
+                                                /*InsertPos=*/0);
+  } else if (isFriend) {
+    // Note, we need this connection even if the friend doesn't have a body.
+    // Its body may exist but not have been attached yet due to deferred
+    // parsing.
+    // FIXME: It might be cleaner to set this when attaching the body to the
+    // friend function declaration, however that would require finding all the
+    // instantiations and modifying them.
+    Function->setInstantiationOfMemberFunction(D, TSK_ImplicitInstantiation);
+  }
+
+  if (InitFunctionInstantiation(Function, D))
+    Function->setInvalidDecl();
+
+  bool isExplicitSpecialization = false;
+
+  LookupResult Previous(SemaRef, Function->getDeclName(), SourceLocation(),
+                        Sema::LookupOrdinaryName, Sema::ForRedeclaration);
+
+  if (DependentFunctionTemplateSpecializationInfo *Info
+        = D->getDependentSpecializationInfo()) {
+    assert(isFriend && "non-friend has dependent specialization info?");
+
+    // This needs to be set now for future sanity.
+    Function->setObjectOfFriendDecl(/*HasPrevious*/ true);
+
+    // Instantiate the explicit template arguments.
+    TemplateArgumentListInfo ExplicitArgs(Info->getLAngleLoc(),
+                                          Info->getRAngleLoc());
+    if (SemaRef.Subst(Info->getTemplateArgs(), Info->getNumTemplateArgs(),
+                      ExplicitArgs, TemplateArgs))
+      return 0;
+
+    // Map the candidate templates to their instantiations.
+    for (unsigned I = 0, E = Info->getNumTemplates(); I != E; ++I) {
+      Decl *Temp = SemaRef.FindInstantiatedDecl(D->getLocation(),
+                                                Info->getTemplate(I),
+                                                TemplateArgs);
+      if (!Temp) return 0;
+
+      Previous.addDecl(cast<FunctionTemplateDecl>(Temp));
+    }
+
+    if (SemaRef.CheckFunctionTemplateSpecialization(Function,
+                                                    &ExplicitArgs,
+                                                    Previous))
+      Function->setInvalidDecl();
+
+    isExplicitSpecialization = true;
+
+  } else if (TemplateParams || !FunctionTemplate) {
+    // Look only into the namespace where the friend would be declared to
+    // find a previous declaration. This is the innermost enclosing namespace,
+    // as described in ActOnFriendFunctionDecl.
+    SemaRef.LookupQualifiedName(Previous, DC);
+
+    // In C++, the previous declaration we find might be a tag type
+    // (class or enum). In this case, the new declaration will hide the
+    // tag type. Note that this does does not apply if we're declaring a
+    // typedef (C++ [dcl.typedef]p4).
+    if (Previous.isSingleTagDecl())
+      Previous.clear();
+  }
+
+  SemaRef.CheckFunctionDeclaration(/*Scope*/ 0, Function, Previous,
+                                   isExplicitSpecialization);
+
+  NamedDecl *PrincipalDecl = (TemplateParams
+                              ? cast<NamedDecl>(FunctionTemplate)
+                              : Function);
+
+  // If the original function was part of a friend declaration,
+  // inherit its namespace state and add it to the owner.
+  if (isFriend) {
+    NamedDecl *PrevDecl;
+    if (TemplateParams)
+      PrevDecl = FunctionTemplate->getPreviousDecl();
+    else
+      PrevDecl = Function->getPreviousDecl();
+
+    PrincipalDecl->setObjectOfFriendDecl(PrevDecl != 0);
+    DC->makeDeclVisibleInContext(PrincipalDecl);
+
+    bool queuedInstantiation = false;
+
+    // C++98 [temp.friend]p5: When a function is defined in a friend function
+    //   declaration in a class template, the function is defined at each
+    //   instantiation of the class template. The function is defined even if it
+    //   is never used.
+    // C++11 [temp.friend]p4: When a function is defined in a friend function
+    //   declaration in a class template, the function is instantiated when the
+    //   function is odr-used.
+    //
+    // If -Wc++98-compat is enabled, we go through the motions of checking for a
+    // redefinition, but don't instantiate the function.
+    if ((!SemaRef.getLangOpts().CPlusPlus0x ||
+         SemaRef.Diags.getDiagnosticLevel(
+             diag::warn_cxx98_compat_friend_redefinition,
+             Function->getLocation())
+           != DiagnosticsEngine::Ignored) &&
+        D->isThisDeclarationADefinition()) {
+      // Check for a function body.
+      const FunctionDecl *Definition = 0;
+      if (Function->isDefined(Definition) &&
+          Definition->getTemplateSpecializationKind() == TSK_Undeclared) {
+        SemaRef.Diag(Function->getLocation(),
+                     SemaRef.getLangOpts().CPlusPlus0x ?
+                       diag::warn_cxx98_compat_friend_redefinition :
+                       diag::err_redefinition) << Function->getDeclName();
+        SemaRef.Diag(Definition->getLocation(), diag::note_previous_definition);
+        if (!SemaRef.getLangOpts().CPlusPlus0x)
+          Function->setInvalidDecl();
+      }
+      // Check for redefinitions due to other instantiations of this or
+      // a similar friend function.
+      else for (FunctionDecl::redecl_iterator R = Function->redecls_begin(),
+                                           REnd = Function->redecls_end();
+                R != REnd; ++R) {
+        if (*R == Function)
+          continue;
+        switch (R->getFriendObjectKind()) {
+        case Decl::FOK_None:
+          if (!SemaRef.getLangOpts().CPlusPlus0x &&
+              !queuedInstantiation && R->isUsed(false)) {
+            if (MemberSpecializationInfo *MSInfo
+                = Function->getMemberSpecializationInfo()) {
+              if (MSInfo->getPointOfInstantiation().isInvalid()) {
+                SourceLocation Loc = R->getLocation(); // FIXME
+                MSInfo->setPointOfInstantiation(Loc);
+                SemaRef.PendingLocalImplicitInstantiations.push_back(
+                                                 std::make_pair(Function, Loc));
+                queuedInstantiation = true;
+              }
+            }
+          }
+          break;
+        default:
+          if (const FunctionDecl *RPattern
+              = R->getTemplateInstantiationPattern())
+            if (RPattern->isDefined(RPattern)) {
+              SemaRef.Diag(Function->getLocation(),
+                           SemaRef.getLangOpts().CPlusPlus0x ?
+                             diag::warn_cxx98_compat_friend_redefinition :
+                             diag::err_redefinition)
+                << Function->getDeclName();
+              SemaRef.Diag(R->getLocation(), diag::note_previous_definition);
+              if (!SemaRef.getLangOpts().CPlusPlus0x)
+                Function->setInvalidDecl();
+              break;
+            }
+        }
+      }
+    }
+  }
+
+  if (Function->isOverloadedOperator() && !DC->isRecord() &&
+      PrincipalDecl->isInIdentifierNamespace(Decl::IDNS_Ordinary))
+    PrincipalDecl->setNonMemberOperator();
+
+  assert(!D->isDefaulted() && "only methods should be defaulted");
+  return Function;
+}
+
+Decl *
+TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D,
+                                      TemplateParameterList *TemplateParams,
+                                      bool IsClassScopeSpecialization) {
+  FunctionTemplateDecl *FunctionTemplate = D->getDescribedFunctionTemplate();
+  if (FunctionTemplate && !TemplateParams) {
+    // We are creating a function template specialization from a function
+    // template. Check whether there is already a function template
+    // specialization for this particular set of template arguments.
+    std::pair<const TemplateArgument *, unsigned> Innermost
+      = TemplateArgs.getInnermost();
+
+    void *InsertPos = 0;
+    FunctionDecl *SpecFunc
+      = FunctionTemplate->findSpecialization(Innermost.first, Innermost.second,
+                                             InsertPos);
+
+    // If we already have a function template specialization, return it.
+    if (SpecFunc)
+      return SpecFunc;
+  }
+
+  bool isFriend;
+  if (FunctionTemplate)
+    isFriend = (FunctionTemplate->getFriendObjectKind() != Decl::FOK_None);
+  else
+    isFriend = (D->getFriendObjectKind() != Decl::FOK_None);
+
+  bool MergeWithParentScope = (TemplateParams != 0) ||
+    !(isa<Decl>(Owner) &&
+      cast<Decl>(Owner)->isDefinedOutsideFunctionOrMethod());
+  LocalInstantiationScope Scope(SemaRef, MergeWithParentScope);
+
+  // Instantiate enclosing template arguments for friends.
+  SmallVector<TemplateParameterList *, 4> TempParamLists;
+  unsigned NumTempParamLists = 0;
+  if (isFriend && (NumTempParamLists = D->getNumTemplateParameterLists())) {
+    TempParamLists.set_size(NumTempParamLists);
+    for (unsigned I = 0; I != NumTempParamLists; ++I) {
+      TemplateParameterList *TempParams = D->getTemplateParameterList(I);
+      TemplateParameterList *InstParams = SubstTemplateParams(TempParams);
+      if (!InstParams)
+        return NULL;
+      TempParamLists[I] = InstParams;
+    }
+  }
+
+  SmallVector<ParmVarDecl *, 4> Params;
+  TypeSourceInfo *TInfo = SubstFunctionType(D, Params);
+  if (!TInfo)
+    return 0;
+  QualType T = TInfo->getType();
+
+  // \brief If the type of this function, after ignoring parentheses,
+  // is not *directly* a function type, then we're instantiating a function
+  // that was declared via a typedef, e.g.,
+  //
+  //   typedef int functype(int, int);
+  //   functype func;
+  //
+  // In this case, we'll just go instantiate the ParmVarDecls that we
+  // synthesized in the method declaration.
+  if (!isa<FunctionProtoType>(T.IgnoreParens())) {
+    assert(!Params.size() && "Instantiating type could not yield parameters");
+    SmallVector<QualType, 4> ParamTypes;
+    if (SemaRef.SubstParmTypes(D->getLocation(), D->param_begin(),
+                               D->getNumParams(), TemplateArgs, ParamTypes,
+                               &Params))
+      return 0;
+  }
+
+  NestedNameSpecifierLoc QualifierLoc = D->getQualifierLoc();
+  if (QualifierLoc) {
+    QualifierLoc = SemaRef.SubstNestedNameSpecifierLoc(QualifierLoc,
+                                                 TemplateArgs);
+    if (!QualifierLoc)
+      return 0;
+  }
+
+  DeclContext *DC = Owner;
+  if (isFriend) {
+    if (QualifierLoc) {
+      CXXScopeSpec SS;
+      SS.Adopt(QualifierLoc);
+      DC = SemaRef.computeDeclContext(SS);
+
+      if (DC && SemaRef.RequireCompleteDeclContext(SS, DC))
+        return 0;
+    } else {
+      DC = SemaRef.FindInstantiatedContext(D->getLocation(),
+                                           D->getDeclContext(),
+                                           TemplateArgs);
+    }
+    if (!DC) return 0;
+  }
+
+  // Build the instantiated method declaration.
+  CXXRecordDecl *Record = cast<CXXRecordDecl>(DC);
+  CXXMethodDecl *Method = 0;
+
+  SourceLocation StartLoc = D->getInnerLocStart();
+  DeclarationNameInfo NameInfo
+    = SemaRef.SubstDeclarationNameInfo(D->getNameInfo(), TemplateArgs);
+  if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(D)) {
+    Method = CXXConstructorDecl::Create(SemaRef.Context, Record,
+                                        StartLoc, NameInfo, T, TInfo,
+                                        Constructor->isExplicit(),
+                                        Constructor->isInlineSpecified(),
+                                        false, Constructor->isConstexpr());
+  } else if (CXXDestructorDecl *Destructor = dyn_cast<CXXDestructorDecl>(D)) {
+    Method = CXXDestructorDecl::Create(SemaRef.Context, Record,
+                                       StartLoc, NameInfo, T, TInfo,
+                                       Destructor->isInlineSpecified(),
+                                       false);
+  } else if (CXXConversionDecl *Conversion = dyn_cast<CXXConversionDecl>(D)) {
+    Method = CXXConversionDecl::Create(SemaRef.Context, Record,
+                                       StartLoc, NameInfo, T, TInfo,
+                                       Conversion->isInlineSpecified(),
+                                       Conversion->isExplicit(),
+                                       Conversion->isConstexpr(),
+                                       Conversion->getLocEnd());
+  } else {
+    Method = CXXMethodDecl::Create(SemaRef.Context, Record,
+                                   StartLoc, NameInfo, T, TInfo,
+                                   D->isStatic(),
+                                   D->getStorageClassAsWritten(),
+                                   D->isInlineSpecified(),
+                                   D->isConstexpr(), D->getLocEnd());
+  }
+
+  if (QualifierLoc)
+    Method->setQualifierInfo(QualifierLoc);
+
+  if (TemplateParams) {
+    // Our resulting instantiation is actually a function template, since we
+    // are substituting only the outer template parameters. For example, given
+    //
+    //   template<typename T>
+    //   struct X {
+    //     template<typename U> void f(T, U);
+    //   };
+    //
+    //   X<int> x;
+    //
+    // We are instantiating the member template "f" within X<int>, which means
+    // substituting int for T, but leaving "f" as a member function template.
+    // Build the function template itself.
+    FunctionTemplate = FunctionTemplateDecl::Create(SemaRef.Context, Record,
+                                                    Method->getLocation(),
+                                                    Method->getDeclName(),
+                                                    TemplateParams, Method);
+    if (isFriend) {
+      FunctionTemplate->setLexicalDeclContext(Owner);
+      FunctionTemplate->setObjectOfFriendDecl(true);
+    } else if (D->isOutOfLine())
+      FunctionTemplate->setLexicalDeclContext(D->getLexicalDeclContext());
+    Method->setDescribedFunctionTemplate(FunctionTemplate);
+  } else if (FunctionTemplate) {
+    // Record this function template specialization.
+    std::pair<const TemplateArgument *, unsigned> Innermost
+      = TemplateArgs.getInnermost();
+    Method->setFunctionTemplateSpecialization(FunctionTemplate,
+                         TemplateArgumentList::CreateCopy(SemaRef.Context,
+                                                          Innermost.first,
+                                                          Innermost.second),
+                                              /*InsertPos=*/0);
+  } else if (!isFriend) {
+    // Record that this is an instantiation of a member function.
+    Method->setInstantiationOfMemberFunction(D, TSK_ImplicitInstantiation);
+  }
+
+  // If we are instantiating a member function defined
+  // out-of-line, the instantiation will have the same lexical
+  // context (which will be a namespace scope) as the template.
+  if (isFriend) {
+    if (NumTempParamLists)
+      Method->setTemplateParameterListsInfo(SemaRef.Context,
+                                            NumTempParamLists,
+                                            TempParamLists.data());
+
+    Method->setLexicalDeclContext(Owner);
+    Method->setObjectOfFriendDecl(true);
+  } else if (D->isOutOfLine())
+    Method->setLexicalDeclContext(D->getLexicalDeclContext());
+
+  // Attach the parameters
+  for (unsigned P = 0; P < Params.size(); ++P)
+    Params[P]->setOwningFunction(Method);
+  Method->setParams(Params);
+
+  if (InitMethodInstantiation(Method, D))
+    Method->setInvalidDecl();
+
+  LookupResult Previous(SemaRef, NameInfo, Sema::LookupOrdinaryName,
+                        Sema::ForRedeclaration);
+
+  if (!FunctionTemplate || TemplateParams || isFriend) {
+    SemaRef.LookupQualifiedName(Previous, Record);
+
+    // In C++, the previous declaration we find might be a tag type
+    // (class or enum). In this case, the new declaration will hide the
+    // tag type. Note that this does does not apply if we're declaring a
+    // typedef (C++ [dcl.typedef]p4).
+    if (Previous.isSingleTagDecl())
+      Previous.clear();
+  }
+
+  if (!IsClassScopeSpecialization)
+    SemaRef.CheckFunctionDeclaration(0, Method, Previous, false);
+
+  if (D->isPure())
+    SemaRef.CheckPureMethod(Method, SourceRange());
+
+  Method->setAccess(D->getAccess());
+
+  SemaRef.CheckOverrideControl(Method);
+
+  // If a function is defined as defaulted or deleted, mark it as such now.
+  if (D->isDefaulted())
+    Method->setDefaulted();
+  if (D->isDeletedAsWritten())
+    Method->setDeletedAsWritten();
+
+  if (FunctionTemplate) {
+    // If there's a function template, let our caller handle it.
+  } else if (Method->isInvalidDecl() && !Previous.empty()) {
+    // Don't hide a (potentially) valid declaration with an invalid one.
+  } else {
+    NamedDecl *DeclToAdd = (TemplateParams
+                            ? cast<NamedDecl>(FunctionTemplate)
+                            : Method);
+    if (isFriend)
+      Record->makeDeclVisibleInContext(DeclToAdd);
+    else if (!IsClassScopeSpecialization)
+      Owner->addDecl(DeclToAdd);
+  }
+
+  if (D->isExplicitlyDefaulted()) {
+    SemaRef.SetDeclDefaulted(Method, Method->getLocation());
+  } else {
+    assert(!D->isDefaulted() &&
+           "should not implicitly default uninstantiated function");
+  }
+
+  return Method;
+}
+
+Decl *TemplateDeclInstantiator::VisitCXXConstructorDecl(CXXConstructorDecl *D) {
+  return VisitCXXMethodDecl(D);
+}
+
+Decl *TemplateDeclInstantiator::VisitCXXDestructorDecl(CXXDestructorDecl *D) {
+  return VisitCXXMethodDecl(D);
+}
+
+Decl *TemplateDeclInstantiator::VisitCXXConversionDecl(CXXConversionDecl *D) {
+  return VisitCXXMethodDecl(D);
+}
+
+ParmVarDecl *TemplateDeclInstantiator::VisitParmVarDecl(ParmVarDecl *D) {
+  return SemaRef.SubstParmVarDecl(D, TemplateArgs, /*indexAdjustment*/ 0,
+                                  llvm::Optional<unsigned>(),
+                                  /*ExpectParameterPack=*/false);
+}
+
+Decl *TemplateDeclInstantiator::VisitTemplateTypeParmDecl(
+                                                    TemplateTypeParmDecl *D) {
+  // TODO: don't always clone when decls are refcounted.
+  assert(D->getTypeForDecl()->isTemplateTypeParmType());
+
+  TemplateTypeParmDecl *Inst =
+    TemplateTypeParmDecl::Create(SemaRef.Context, Owner,
+                                 D->getLocStart(), D->getLocation(),
+                                 D->getDepth() - TemplateArgs.getNumLevels(),
+                                 D->getIndex(), D->getIdentifier(),
+                                 D->wasDeclaredWithTypename(),
+                                 D->isParameterPack());
+  Inst->setAccess(AS_public);
+
+  if (D->hasDefaultArgument())
+    Inst->setDefaultArgument(D->getDefaultArgumentInfo(), false);
+
+  // Introduce this template parameter's instantiation into the instantiation
+  // scope.
+  SemaRef.CurrentInstantiationScope->InstantiatedLocal(D, Inst);
+
+  return Inst;
+}
+
+Decl *TemplateDeclInstantiator::VisitNonTypeTemplateParmDecl(
+                                                 NonTypeTemplateParmDecl *D) {
+  // Substitute into the type of the non-type template parameter.
+  TypeLoc TL = D->getTypeSourceInfo()->getTypeLoc();
+  SmallVector<TypeSourceInfo *, 4> ExpandedParameterPackTypesAsWritten;
+  SmallVector<QualType, 4> ExpandedParameterPackTypes;
+  bool IsExpandedParameterPack = false;
+  TypeSourceInfo *DI;
+  QualType T;
+  bool Invalid = false;
+
+  if (D->isExpandedParameterPack()) {
+    // The non-type template parameter pack is an already-expanded pack
+    // expansion of types. Substitute into each of the expanded types.
+    ExpandedParameterPackTypes.reserve(D->getNumExpansionTypes());
+    ExpandedParameterPackTypesAsWritten.reserve(D->getNumExpansionTypes());
+    for (unsigned I = 0, N = D->getNumExpansionTypes(); I != N; ++I) {
+      TypeSourceInfo *NewDI =SemaRef.SubstType(D->getExpansionTypeSourceInfo(I),
+                                               TemplateArgs,
+                                               D->getLocation(),
+                                               D->getDeclName());
+      if (!NewDI)
+        return 0;
+
+      ExpandedParameterPackTypesAsWritten.push_back(NewDI);
+      QualType NewT =SemaRef.CheckNonTypeTemplateParameterType(NewDI->getType(),
+                                                              D->getLocation());
+      if (NewT.isNull())
+        return 0;
+      ExpandedParameterPackTypes.push_back(NewT);
+    }
+
+    IsExpandedParameterPack = true;
+    DI = D->getTypeSourceInfo();
+    T = DI->getType();
+  } else if (isa<PackExpansionTypeLoc>(TL)) {
+    // The non-type template parameter pack's type is a pack expansion of types.
+    // Determine whether we need to expand this parameter pack into separate
+    // types.
+    PackExpansionTypeLoc Expansion = cast<PackExpansionTypeLoc>(TL);
+    TypeLoc Pattern = Expansion.getPatternLoc();
+    SmallVector<UnexpandedParameterPack, 2> Unexpanded;
+    SemaRef.collectUnexpandedParameterPacks(Pattern, Unexpanded);
+
+    // Determine whether the set of unexpanded parameter packs can and should
+    // be expanded.
+    bool Expand = true;
+    bool RetainExpansion = false;
+    llvm::Optional<unsigned> OrigNumExpansions
+      = Expansion.getTypePtr()->getNumExpansions();
+    llvm::Optional<unsigned> NumExpansions = OrigNumExpansions;
+    if (SemaRef.CheckParameterPacksForExpansion(Expansion.getEllipsisLoc(),
+                                                Pattern.getSourceRange(),
+                                                Unexpanded,
+                                                TemplateArgs,
+                                                Expand, RetainExpansion,
+                                                NumExpansions))
+      return 0;
+
+    if (Expand) {
+      for (unsigned I = 0; I != *NumExpansions; ++I) {
+        Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(SemaRef, I);
+        TypeSourceInfo *NewDI = SemaRef.SubstType(Pattern, TemplateArgs,
+                                                  D->getLocation(),
+                                                  D->getDeclName());
+        if (!NewDI)
+          return 0;
+
+        ExpandedParameterPackTypesAsWritten.push_back(NewDI);
+        QualType NewT = SemaRef.CheckNonTypeTemplateParameterType(
+                                                              NewDI->getType(),
+                                                              D->getLocation());
+        if (NewT.isNull())
+          return 0;
+        ExpandedParameterPackTypes.push_back(NewT);
+      }
+
+      // Note that we have an expanded parameter pack. The "type" of this
+      // expanded parameter pack is the original expansion type, but callers
+      // will end up using the expanded parameter pack types for type-checking.
+      IsExpandedParameterPack = true;
+      DI = D->getTypeSourceInfo();
+      T = DI->getType();
+    } else {
+      // We cannot fully expand the pack expansion now, so substitute into the
+      // pattern and create a new pack expansion type.
+      Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(SemaRef, -1);
+      TypeSourceInfo *NewPattern = SemaRef.SubstType(Pattern, TemplateArgs,
+                                                     D->getLocation(),
+                                                     D->getDeclName());
+      if (!NewPattern)
+        return 0;
+
+      DI = SemaRef.CheckPackExpansion(NewPattern, Expansion.getEllipsisLoc(),
+                                      NumExpansions);
+      if (!DI)
+        return 0;
+
+      T = DI->getType();
+    }
+  } else {
+    // Simple case: substitution into a parameter that is not a parameter pack.
+    DI = SemaRef.SubstType(D->getTypeSourceInfo(), TemplateArgs,
+                           D->getLocation(), D->getDeclName());
+    if (!DI)
+      return 0;
+
+    // Check that this type is acceptable for a non-type template parameter.
+    T = SemaRef.CheckNonTypeTemplateParameterType(DI->getType(),
+                                                  D->getLocation());
+    if (T.isNull()) {
+      T = SemaRef.Context.IntTy;
+      Invalid = true;
+    }
+  }
+
+  NonTypeTemplateParmDecl *Param;
+  if (IsExpandedParameterPack)
+    Param = NonTypeTemplateParmDecl::Create(SemaRef.Context, Owner,
+                                            D->getInnerLocStart(),
+                                            D->getLocation(),
+                                    D->getDepth() - TemplateArgs.getNumLevels(),
+                                            D->getPosition(),
+                                            D->getIdentifier(), T,
+                                            DI,
+                                            ExpandedParameterPackTypes.data(),
+                                            ExpandedParameterPackTypes.size(),
+                                    ExpandedParameterPackTypesAsWritten.data());
+  else
+    Param = NonTypeTemplateParmDecl::Create(SemaRef.Context, Owner,
+                                            D->getInnerLocStart(),
+                                            D->getLocation(),
+                                    D->getDepth() - TemplateArgs.getNumLevels(),
+                                            D->getPosition(),
+                                            D->getIdentifier(), T,
+                                            D->isParameterPack(), DI);
+
+  Param->setAccess(AS_public);
+  if (Invalid)
+    Param->setInvalidDecl();
+
+  Param->setDefaultArgument(D->getDefaultArgument(), false);
+
+  // Introduce this template parameter's instantiation into the instantiation
+  // scope.
+  SemaRef.CurrentInstantiationScope->InstantiatedLocal(D, Param);
+  return Param;
+}
+
+Decl *
+TemplateDeclInstantiator::VisitTemplateTemplateParmDecl(
+                                                  TemplateTemplateParmDecl *D) {
+  // Instantiate the template parameter list of the template template parameter.
+  TemplateParameterList *TempParams = D->getTemplateParameters();
+  TemplateParameterList *InstParams;
+  {
+    // Perform the actual substitution of template parameters within a new,
+    // local instantiation scope.
+    LocalInstantiationScope Scope(SemaRef);
+    InstParams = SubstTemplateParams(TempParams);
+    if (!InstParams)
+      return NULL;
+  }
+
+  // Build the template template parameter.
+  TemplateTemplateParmDecl *Param
+    = TemplateTemplateParmDecl::Create(SemaRef.Context, Owner, D->getLocation(),
+                                   D->getDepth() - TemplateArgs.getNumLevels(),
+                                       D->getPosition(), D->isParameterPack(),
+                                       D->getIdentifier(), InstParams);
+  Param->setDefaultArgument(D->getDefaultArgument(), false);
+  Param->setAccess(AS_public);
+
+  // Introduce this template parameter's instantiation into the instantiation
+  // scope.
+  SemaRef.CurrentInstantiationScope->InstantiatedLocal(D, Param);
+
+  return Param;
+}
+
+Decl *TemplateDeclInstantiator::VisitUsingDirectiveDecl(UsingDirectiveDecl *D) {
+  // Using directives are never dependent (and never contain any types or
+  // expressions), so they require no explicit instantiation work.
+
+  UsingDirectiveDecl *Inst
+    = UsingDirectiveDecl::Create(SemaRef.Context, Owner, D->getLocation(),
+                                 D->getNamespaceKeyLocation(),
+                                 D->getQualifierLoc(),
+                                 D->getIdentLocation(),
+                                 D->getNominatedNamespace(),
+                                 D->getCommonAncestor());
+  Owner->addDecl(Inst);
+  return Inst;
+}
+
+Decl *TemplateDeclInstantiator::VisitUsingDecl(UsingDecl *D) {
+
+  // The nested name specifier may be dependent, for example
+  //     template <typename T> struct t {
+  //       struct s1 { T f1(); };
+  //       struct s2 : s1 { using s1::f1; };
+  //     };
+  //     template struct t<int>;
+  // Here, in using s1::f1, s1 refers to t<T>::s1;
+  // we need to substitute for t<int>::s1.
+  NestedNameSpecifierLoc QualifierLoc
+    = SemaRef.SubstNestedNameSpecifierLoc(D->getQualifierLoc(),
+                                          TemplateArgs);
+  if (!QualifierLoc)
+    return 0;
+
+  // The name info is non-dependent, so no transformation
+  // is required.
+  DeclarationNameInfo NameInfo = D->getNameInfo();
+
+  // We only need to do redeclaration lookups if we're in a class
+  // scope (in fact, it's not really even possible in non-class
+  // scopes).
+  bool CheckRedeclaration = Owner->isRecord();
+
+  LookupResult Prev(SemaRef, NameInfo, Sema::LookupUsingDeclName,
+                    Sema::ForRedeclaration);
+
+  UsingDecl *NewUD = UsingDecl::Create(SemaRef.Context, Owner,
+                                       D->getUsingLocation(),
+                                       QualifierLoc,
+                                       NameInfo,
+                                       D->isTypeName());
+
+  CXXScopeSpec SS;
+  SS.Adopt(QualifierLoc);
+  if (CheckRedeclaration) {
+    Prev.setHideTags(false);
+    SemaRef.LookupQualifiedName(Prev, Owner);
+
+    // Check for invalid redeclarations.
+    if (SemaRef.CheckUsingDeclRedeclaration(D->getUsingLocation(),
+                                            D->isTypeName(), SS,
+                                            D->getLocation(), Prev))
+      NewUD->setInvalidDecl();
+
+  }
+
+  if (!NewUD->isInvalidDecl() &&
+      SemaRef.CheckUsingDeclQualifier(D->getUsingLocation(), SS,
+                                      D->getLocation()))
+    NewUD->setInvalidDecl();
+
+  SemaRef.Context.setInstantiatedFromUsingDecl(NewUD, D);
+  NewUD->setAccess(D->getAccess());
+  Owner->addDecl(NewUD);
+
+  // Don't process the shadow decls for an invalid decl.
+  if (NewUD->isInvalidDecl())
+    return NewUD;
+
+  if (NameInfo.getName().getNameKind() == DeclarationName::CXXConstructorName) {
+    if (SemaRef.CheckInheritingConstructorUsingDecl(NewUD))
+      NewUD->setInvalidDecl();
+    return NewUD;
+  }
+
+  bool isFunctionScope = Owner->isFunctionOrMethod();
+
+  // Process the shadow decls.
+  for (UsingDecl::shadow_iterator I = D->shadow_begin(), E = D->shadow_end();
+         I != E; ++I) {
+    UsingShadowDecl *Shadow = *I;
+    NamedDecl *InstTarget =
+      cast_or_null<NamedDecl>(SemaRef.FindInstantiatedDecl(
+                                                          Shadow->getLocation(),
+                                                        Shadow->getTargetDecl(),
+                                                           TemplateArgs));
+    if (!InstTarget)
+      return 0;
+
+    if (CheckRedeclaration &&
+        SemaRef.CheckUsingShadowDecl(NewUD, InstTarget, Prev))
+      continue;
+
+    UsingShadowDecl *InstShadow
+      = SemaRef.BuildUsingShadowDecl(/*Scope*/ 0, NewUD, InstTarget);
+    SemaRef.Context.setInstantiatedFromUsingShadowDecl(InstShadow, Shadow);
+
+    if (isFunctionScope)
+      SemaRef.CurrentInstantiationScope->InstantiatedLocal(Shadow, InstShadow);
+  }
+
+  return NewUD;
+}
+
+Decl *TemplateDeclInstantiator::VisitUsingShadowDecl(UsingShadowDecl *D) {
+  // Ignore these;  we handle them in bulk when processing the UsingDecl.
+  return 0;
+}
+
+Decl * TemplateDeclInstantiator
+    ::VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D) {
+  NestedNameSpecifierLoc QualifierLoc
+    = SemaRef.SubstNestedNameSpecifierLoc(D->getQualifierLoc(),
+                                          TemplateArgs);
+  if (!QualifierLoc)
+    return 0;
+
+  CXXScopeSpec SS;
+  SS.Adopt(QualifierLoc);
+
+  // Since NameInfo refers to a typename, it cannot be a C++ special name.
+  // Hence, no tranformation is required for it.
+  DeclarationNameInfo NameInfo(D->getDeclName(), D->getLocation());
+  NamedDecl *UD =
+    SemaRef.BuildUsingDeclaration(/*Scope*/ 0, D->getAccess(),
+                                  D->getUsingLoc(), SS, NameInfo, 0,
+                                  /*instantiation*/ true,
+                                  /*typename*/ true, D->getTypenameLoc());
+  if (UD)
+    SemaRef.Context.setInstantiatedFromUsingDecl(cast<UsingDecl>(UD), D);
+
+  return UD;
+}
+
+Decl * TemplateDeclInstantiator
+    ::VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D) {
+  NestedNameSpecifierLoc QualifierLoc
+      = SemaRef.SubstNestedNameSpecifierLoc(D->getQualifierLoc(), TemplateArgs);
+  if (!QualifierLoc)
+    return 0;
+
+  CXXScopeSpec SS;
+  SS.Adopt(QualifierLoc);
+
+  DeclarationNameInfo NameInfo
+    = SemaRef.SubstDeclarationNameInfo(D->getNameInfo(), TemplateArgs);
+
+  NamedDecl *UD =
+    SemaRef.BuildUsingDeclaration(/*Scope*/ 0, D->getAccess(),
+                                  D->getUsingLoc(), SS, NameInfo, 0,
+                                  /*instantiation*/ true,
+                                  /*typename*/ false, SourceLocation());
+  if (UD)
+    SemaRef.Context.setInstantiatedFromUsingDecl(cast<UsingDecl>(UD), D);
+
+  return UD;
+}
+
+
+Decl *TemplateDeclInstantiator::VisitClassScopeFunctionSpecializationDecl(
+                                     ClassScopeFunctionSpecializationDecl *Decl) {
+  CXXMethodDecl *OldFD = Decl->getSpecialization();
+  CXXMethodDecl *NewFD = cast<CXXMethodDecl>(VisitCXXMethodDecl(OldFD, 0, true));
+
+  LookupResult Previous(SemaRef, NewFD->getNameInfo(), Sema::LookupOrdinaryName,
+                        Sema::ForRedeclaration);
+
+  SemaRef.LookupQualifiedName(Previous, SemaRef.CurContext);
+  if (SemaRef.CheckFunctionTemplateSpecialization(NewFD, 0, Previous)) {
+    NewFD->setInvalidDecl();
+    return NewFD;
+  }
+
+  // Associate the specialization with the pattern.
+  FunctionDecl *Specialization = cast<FunctionDecl>(Previous.getFoundDecl());
+  assert(Specialization && "Class scope Specialization is null");
+  SemaRef.Context.setClassScopeSpecializationPattern(Specialization, OldFD);
+
+  return NewFD;
+}
+
+Decl *Sema::SubstDecl(Decl *D, DeclContext *Owner,
+                      const MultiLevelTemplateArgumentList &TemplateArgs) {
+  TemplateDeclInstantiator Instantiator(*this, Owner, TemplateArgs);
+  if (D->isInvalidDecl())
+    return 0;
+
+  return Instantiator.Visit(D);
+}
+
+/// \brief Instantiates a nested template parameter list in the current
+/// instantiation context.
+///
+/// \param L The parameter list to instantiate
+///
+/// \returns NULL if there was an error
+TemplateParameterList *
+TemplateDeclInstantiator::SubstTemplateParams(TemplateParameterList *L) {
+  // Get errors for all the parameters before bailing out.
+  bool Invalid = false;
+
+  unsigned N = L->size();
+  typedef SmallVector<NamedDecl *, 8> ParamVector;
+  ParamVector Params;
+  Params.reserve(N);
+  for (TemplateParameterList::iterator PI = L->begin(), PE = L->end();
+       PI != PE; ++PI) {
+    NamedDecl *D = cast_or_null<NamedDecl>(Visit(*PI));
+    Params.push_back(D);
+    Invalid = Invalid || !D || D->isInvalidDecl();
+  }
+
+  // Clean up if we had an error.
+  if (Invalid)
+    return NULL;
+
+  TemplateParameterList *InstL
+    = TemplateParameterList::Create(SemaRef.Context, L->getTemplateLoc(),
+                                    L->getLAngleLoc(), &Params.front(), N,
+                                    L->getRAngleLoc());
+  return InstL;
+}
+
+/// \brief Instantiate the declaration of a class template partial
+/// specialization.
+///
+/// \param ClassTemplate the (instantiated) class template that is partially
+// specialized by the instantiation of \p PartialSpec.
+///
+/// \param PartialSpec the (uninstantiated) class template partial
+/// specialization that we are instantiating.
+///
+/// \returns The instantiated partial specialization, if successful; otherwise,
+/// NULL to indicate an error.
+ClassTemplatePartialSpecializationDecl *
+TemplateDeclInstantiator::InstantiateClassTemplatePartialSpecialization(
+                                            ClassTemplateDecl *ClassTemplate,
+                          ClassTemplatePartialSpecializationDecl *PartialSpec) {
+  // Create a local instantiation scope for this class template partial
+  // specialization, which will contain the instantiations of the template
+  // parameters.
+  LocalInstantiationScope Scope(SemaRef);
+
+  // Substitute into the template parameters of the class template partial
+  // specialization.
+  TemplateParameterList *TempParams = PartialSpec->getTemplateParameters();
+  TemplateParameterList *InstParams = SubstTemplateParams(TempParams);
+  if (!InstParams)
+    return 0;
+
+  // Substitute into the template arguments of the class template partial
+  // specialization.
+  TemplateArgumentListInfo InstTemplateArgs; // no angle locations
+  if (SemaRef.Subst(PartialSpec->getTemplateArgsAsWritten(),
+                    PartialSpec->getNumTemplateArgsAsWritten(),
+                    InstTemplateArgs, TemplateArgs))
+    return 0;
+
+  // Check that the template argument list is well-formed for this
+  // class template.
+  SmallVector<TemplateArgument, 4> Converted;
+  if (SemaRef.CheckTemplateArgumentList(ClassTemplate,
+                                        PartialSpec->getLocation(),
+                                        InstTemplateArgs,
+                                        false,
+                                        Converted))
+    return 0;
+
+  // Figure out where to insert this class template partial specialization
+  // in the member template's set of class template partial specializations.
+  void *InsertPos = 0;
+  ClassTemplateSpecializationDecl *PrevDecl
+    = ClassTemplate->findPartialSpecialization(Converted.data(),
+                                               Converted.size(), InsertPos);
+
+  // Build the canonical type that describes the converted template
+  // arguments of the class template partial specialization.
+  QualType CanonType
+    = SemaRef.Context.getTemplateSpecializationType(TemplateName(ClassTemplate),
+                                                    Converted.data(),
+                                                    Converted.size());
+
+  // Build the fully-sugared type for this class template
+  // specialization as the user wrote in the specialization
+  // itself. This means that we'll pretty-print the type retrieved
+  // from the specialization's declaration the way that the user
+  // actually wrote the specialization, rather than formatting the
+  // name based on the "canonical" representation used to store the
+  // template arguments in the specialization.
+  TypeSourceInfo *WrittenTy
+    = SemaRef.Context.getTemplateSpecializationTypeInfo(
+                                                    TemplateName(ClassTemplate),
+                                                    PartialSpec->getLocation(),
+                                                    InstTemplateArgs,
+                                                    CanonType);
+
+  if (PrevDecl) {
+    // We've already seen a partial specialization with the same template
+    // parameters and template arguments. This can happen, for example, when
+    // substituting the outer template arguments ends up causing two
+    // class template partial specializations of a member class template
+    // to have identical forms, e.g.,
+    //
+    //   template<typename T, typename U>
+    //   struct Outer {
+    //     template<typename X, typename Y> struct Inner;
+    //     template<typename Y> struct Inner<T, Y>;
+    //     template<typename Y> struct Inner<U, Y>;
+    //   };
+    //
+    //   Outer<int, int> outer; // error: the partial specializations of Inner
+    //                          // have the same signature.
+    SemaRef.Diag(PartialSpec->getLocation(), diag::err_partial_spec_redeclared)
+      << WrittenTy->getType();
+    SemaRef.Diag(PrevDecl->getLocation(), diag::note_prev_partial_spec_here)
+      << SemaRef.Context.getTypeDeclType(PrevDecl);
+    return 0;
+  }
+
+
+  // Create the class template partial specialization declaration.
+  ClassTemplatePartialSpecializationDecl *InstPartialSpec
+    = ClassTemplatePartialSpecializationDecl::Create(SemaRef.Context,
+                                                     PartialSpec->getTagKind(),
+                                                     Owner,
+                                                     PartialSpec->getLocStart(),
+                                                     PartialSpec->getLocation(),
+                                                     InstParams,
+                                                     ClassTemplate,
+                                                     Converted.data(),
+                                                     Converted.size(),
+                                                     InstTemplateArgs,
+                                                     CanonType,
+                                                     0,
+                             ClassTemplate->getNextPartialSpecSequenceNumber());
+  // Substitute the nested name specifier, if any.
+  if (SubstQualifier(PartialSpec, InstPartialSpec))
+    return 0;
+
+  InstPartialSpec->setInstantiatedFromMember(PartialSpec);
+  InstPartialSpec->setTypeAsWritten(WrittenTy);
+
+  // Add this partial specialization to the set of class template partial
+  // specializations.
+  ClassTemplate->AddPartialSpecialization(InstPartialSpec, /*InsertPos=*/0);
+  return InstPartialSpec;
+}
+
+TypeSourceInfo*
+TemplateDeclInstantiator::SubstFunctionType(FunctionDecl *D,
+                              SmallVectorImpl<ParmVarDecl *> &Params) {
+  TypeSourceInfo *OldTInfo = D->getTypeSourceInfo();
+  assert(OldTInfo && "substituting function without type source info");
+  assert(Params.empty() && "parameter vector is non-empty at start");
+  
+  CXXRecordDecl *ThisContext = 0;
+  unsigned ThisTypeQuals = 0;
+  if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(D)) {
+    ThisContext = Method->getParent();
+    ThisTypeQuals = Method->getTypeQualifiers();
+  }
+  
+  TypeSourceInfo *NewTInfo
+    = SemaRef.SubstFunctionDeclType(OldTInfo, TemplateArgs,
+                                    D->getTypeSpecStartLoc(),
+                                    D->getDeclName(),
+                                    ThisContext, ThisTypeQuals);
+  if (!NewTInfo)
+    return 0;
+
+  if (NewTInfo != OldTInfo) {
+    // Get parameters from the new type info.
+    TypeLoc OldTL = OldTInfo->getTypeLoc().IgnoreParens();
+    if (FunctionProtoTypeLoc *OldProtoLoc
+                                  = dyn_cast<FunctionProtoTypeLoc>(&OldTL)) {
+      TypeLoc NewTL = NewTInfo->getTypeLoc().IgnoreParens();
+      FunctionProtoTypeLoc *NewProtoLoc = cast<FunctionProtoTypeLoc>(&NewTL);
+      assert(NewProtoLoc && "Missing prototype?");
+      unsigned NewIdx = 0, NumNewParams = NewProtoLoc->getNumArgs();
+      for (unsigned OldIdx = 0, NumOldParams = OldProtoLoc->getNumArgs();
+           OldIdx != NumOldParams; ++OldIdx) {
+        ParmVarDecl *OldParam = OldProtoLoc->getArg(OldIdx);
+        if (!OldParam->isParameterPack() ||
+            // FIXME: Is this right? OldParam could expand to an empty parameter
+            // pack and the next parameter could be an unexpanded parameter pack
+            (NewIdx < NumNewParams &&
+             NewProtoLoc->getArg(NewIdx)->isParameterPack())) {
+          // Simple case: normal parameter, or a parameter pack that's
+          // instantiated to a (still-dependent) parameter pack.
+          ParmVarDecl *NewParam = NewProtoLoc->getArg(NewIdx++);
+          Params.push_back(NewParam);
+          SemaRef.CurrentInstantiationScope->InstantiatedLocal(OldParam,
+                                                               NewParam);
+          continue;
+        }
+
+        // Parameter pack: make the instantiation an argument pack.
+        SemaRef.CurrentInstantiationScope->MakeInstantiatedLocalArgPack(
+                                                                      OldParam);
+        unsigned NumArgumentsInExpansion
+          = SemaRef.getNumArgumentsInExpansion(OldParam->getType(),
+                                               TemplateArgs);
+        while (NumArgumentsInExpansion--) {
+          ParmVarDecl *NewParam = NewProtoLoc->getArg(NewIdx++);
+          Params.push_back(NewParam);
+          SemaRef.CurrentInstantiationScope->InstantiatedLocalPackArg(OldParam,
+                                                                      NewParam);
+        }
+      }
+    }
+  } else {
+    // The function type itself was not dependent and therefore no
+    // substitution occurred. However, we still need to instantiate
+    // the function parameters themselves.
+    TypeLoc OldTL = OldTInfo->getTypeLoc().IgnoreParens();
+    if (FunctionProtoTypeLoc *OldProtoLoc
+                                    = dyn_cast<FunctionProtoTypeLoc>(&OldTL)) {
+      for (unsigned i = 0, i_end = OldProtoLoc->getNumArgs(); i != i_end; ++i) {
+        ParmVarDecl *Parm = VisitParmVarDecl(OldProtoLoc->getArg(i));
+        if (!Parm)
+          return 0;
+        Params.push_back(Parm);
+      }
+    }
+  }
+  return NewTInfo;
+}
+
+/// Introduce the instantiated function parameters into the local
+/// instantiation scope, and set the parameter names to those used
+/// in the template.
+static void addInstantiatedParametersToScope(Sema &S, FunctionDecl *Function,
+                                             const FunctionDecl *PatternDecl,
+                                             LocalInstantiationScope &Scope,
+                           const MultiLevelTemplateArgumentList &TemplateArgs) {
+  unsigned FParamIdx = 0;
+  for (unsigned I = 0, N = PatternDecl->getNumParams(); I != N; ++I) {
+    const ParmVarDecl *PatternParam = PatternDecl->getParamDecl(I);
+    if (!PatternParam->isParameterPack()) {
+      // Simple case: not a parameter pack.
+      assert(FParamIdx < Function->getNumParams());
+      ParmVarDecl *FunctionParam = Function->getParamDecl(FParamIdx);
+      FunctionParam->setDeclName(PatternParam->getDeclName());
+      Scope.InstantiatedLocal(PatternParam, FunctionParam);
+      ++FParamIdx;
+      continue;
+    }
+
+    // Expand the parameter pack.
+    Scope.MakeInstantiatedLocalArgPack(PatternParam);
+    unsigned NumArgumentsInExpansion
+      = S.getNumArgumentsInExpansion(PatternParam->getType(), TemplateArgs);
+    for (unsigned Arg = 0; Arg < NumArgumentsInExpansion; ++Arg) {
+      ParmVarDecl *FunctionParam = Function->getParamDecl(FParamIdx);
+      FunctionParam->setDeclName(PatternParam->getDeclName());
+      Scope.InstantiatedLocalPackArg(PatternParam, FunctionParam);
+      ++FParamIdx;
+    }
+  }
+}
+
+static void InstantiateExceptionSpec(Sema &SemaRef, FunctionDecl *New,
+                                     const FunctionProtoType *Proto,
+                           const MultiLevelTemplateArgumentList &TemplateArgs) {
+  assert(Proto->getExceptionSpecType() != EST_Uninstantiated);
+
+  // C++11 [expr.prim.general]p3:
+  //   If a declaration declares a member function or member function 
+  //   template of a class X, the expression this is a prvalue of type 
+  //   "pointer to cv-qualifier-seq X" between the optional cv-qualifer-seq
+  //   and the end of the function-definition, member-declarator, or 
+  //   declarator.    
+  CXXRecordDecl *ThisContext = 0;
+  unsigned ThisTypeQuals = 0;
+  if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(New)) {
+    ThisContext = Method->getParent();
+    ThisTypeQuals = Method->getTypeQualifiers();
+  }
+  Sema::CXXThisScopeRAII ThisScope(SemaRef, ThisContext, ThisTypeQuals,
+                                   SemaRef.getLangOpts().CPlusPlus0x);
+
+  // The function has an exception specification or a "noreturn"
+  // attribute. Substitute into each of the exception types.
+  SmallVector<QualType, 4> Exceptions;
+  for (unsigned I = 0, N = Proto->getNumExceptions(); I != N; ++I) {
+    // FIXME: Poor location information!
+    if (const PackExpansionType *PackExpansion
+          = Proto->getExceptionType(I)->getAs<PackExpansionType>()) {
+      // We have a pack expansion. Instantiate it.
+      SmallVector<UnexpandedParameterPack, 2> Unexpanded;
+      SemaRef.collectUnexpandedParameterPacks(PackExpansion->getPattern(),
+                                              Unexpanded);
+      assert(!Unexpanded.empty() &&
+             "Pack expansion without parameter packs?");
+
+      bool Expand = false;
+      bool RetainExpansion = false;
+      llvm::Optional<unsigned> NumExpansions
+                                        = PackExpansion->getNumExpansions();
+      if (SemaRef.CheckParameterPacksForExpansion(New->getLocation(),
+                                                  SourceRange(),
+                                                  Unexpanded,
+                                                  TemplateArgs,
+                                                  Expand,
+                                                  RetainExpansion,
+                                                  NumExpansions))
+        break;
+
+      if (!Expand) {
+        // We can't expand this pack expansion into separate arguments yet;
+        // just substitute into the pattern and create a new pack expansion
+        // type.
+        Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(SemaRef, -1);
+        QualType T = SemaRef.SubstType(PackExpansion->getPattern(),
+                                       TemplateArgs,
+                                     New->getLocation(), New->getDeclName());
+        if (T.isNull())
+          break;
+
+        T = SemaRef.Context.getPackExpansionType(T, NumExpansions);
+        Exceptions.push_back(T);
+        continue;
+      }
+
+      // Substitute into the pack expansion pattern for each template
+      bool Invalid = false;
+      for (unsigned ArgIdx = 0; ArgIdx != *NumExpansions; ++ArgIdx) {
+        Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(SemaRef, ArgIdx);
+
+        QualType T = SemaRef.SubstType(PackExpansion->getPattern(),
+                                       TemplateArgs,
+                                     New->getLocation(), New->getDeclName());
+        if (T.isNull()) {
+          Invalid = true;
+          break;
+        }
+
+        Exceptions.push_back(T);
+      }
+
+      if (Invalid)
+        break;
+
+      continue;
+    }
+
+    QualType T
+      = SemaRef.SubstType(Proto->getExceptionType(I), TemplateArgs,
+                          New->getLocation(), New->getDeclName());
+    if (T.isNull() ||
+        SemaRef.CheckSpecifiedExceptionType(T, New->getLocation()))
+      continue;
+
+    Exceptions.push_back(T);
+  }
+  Expr *NoexceptExpr = 0;
+  if (Expr *OldNoexceptExpr = Proto->getNoexceptExpr()) {
+    EnterExpressionEvaluationContext Unevaluated(SemaRef,
+                                                 Sema::ConstantEvaluated);
+    ExprResult E = SemaRef.SubstExpr(OldNoexceptExpr, TemplateArgs);
+    if (E.isUsable())
+      E = SemaRef.CheckBooleanCondition(E.get(), E.get()->getLocStart());
+
+    if (E.isUsable()) {
+      NoexceptExpr = E.take();
+      if (!NoexceptExpr->isTypeDependent() &&
+          !NoexceptExpr->isValueDependent())
+        NoexceptExpr = SemaRef.VerifyIntegerConstantExpression(NoexceptExpr,
+          0, SemaRef.PDiag(diag::err_noexcept_needs_constant_expression),
+          /*AllowFold*/ false).take();
+    }
+  }
+
+  // Rebuild the function type
+  const FunctionProtoType *NewProto
+    = New->getType()->getAs<FunctionProtoType>();
+  assert(NewProto && "Template instantiation without function prototype?");
+
+  FunctionProtoType::ExtProtoInfo EPI = NewProto->getExtProtoInfo();
+  EPI.ExceptionSpecType = Proto->getExceptionSpecType();
+  EPI.NumExceptions = Exceptions.size();
+  EPI.Exceptions = Exceptions.data();
+  EPI.NoexceptExpr = NoexceptExpr;
+
+  New->setType(SemaRef.Context.getFunctionType(NewProto->getResultType(),
+                                               NewProto->arg_type_begin(),
+                                               NewProto->getNumArgs(),
+                                               EPI));
+}
+
+void Sema::InstantiateExceptionSpec(SourceLocation PointOfInstantiation,
+                                    FunctionDecl *Decl) {
+  const FunctionProtoType *Proto = Decl->getType()->castAs<FunctionProtoType>();
+  if (Proto->getExceptionSpecType() != EST_Uninstantiated)
+    return;
+
+  InstantiatingTemplate Inst(*this, PointOfInstantiation, Decl,
+                             InstantiatingTemplate::ExceptionSpecification());
+  if (Inst)
+    return;
+
+  // Enter the scope of this instantiation. We don't use
+  // PushDeclContext because we don't have a scope.
+  Sema::ContextRAII savedContext(*this, Decl);
+  LocalInstantiationScope Scope(*this);
+
+  MultiLevelTemplateArgumentList TemplateArgs =
+    getTemplateInstantiationArgs(Decl, 0, /*RelativeToPrimary*/true);
+
+  FunctionDecl *Template = Proto->getExceptionSpecTemplate();
+  addInstantiatedParametersToScope(*this, Decl, Template, Scope, TemplateArgs);
+
+  ::InstantiateExceptionSpec(*this, Decl,
+                             Template->getType()->castAs<FunctionProtoType>(),
+                             TemplateArgs);
+}
+
+/// \brief Initializes the common fields of an instantiation function
+/// declaration (New) from the corresponding fields of its template (Tmpl).
+///
+/// \returns true if there was an error
+bool
+TemplateDeclInstantiator::InitFunctionInstantiation(FunctionDecl *New,
+                                                    FunctionDecl *Tmpl) {
+  if (Tmpl->isDeletedAsWritten())
+    New->setDeletedAsWritten();
+
+  // If we are performing substituting explicitly-specified template arguments
+  // or deduced template arguments into a function template and we reach this
+  // point, we are now past the point where SFINAE applies and have committed
+  // to keeping the new function template specialization. We therefore
+  // convert the active template instantiation for the function template
+  // into a template instantiation for this specific function template
+  // specialization, which is not a SFINAE context, so that we diagnose any
+  // further errors in the declaration itself.
+  typedef Sema::ActiveTemplateInstantiation ActiveInstType;
+  ActiveInstType &ActiveInst = SemaRef.ActiveTemplateInstantiations.back();
+  if (ActiveInst.Kind == ActiveInstType::ExplicitTemplateArgumentSubstitution ||
+      ActiveInst.Kind == ActiveInstType::DeducedTemplateArgumentSubstitution) {
+    if (FunctionTemplateDecl *FunTmpl
+          = dyn_cast<FunctionTemplateDecl>((Decl *)ActiveInst.Entity)) {
+      assert(FunTmpl->getTemplatedDecl() == Tmpl &&
+             "Deduction from the wrong function template?");
+      (void) FunTmpl;
+      ActiveInst.Kind = ActiveInstType::TemplateInstantiation;
+      ActiveInst.Entity = reinterpret_cast<uintptr_t>(New);
+      --SemaRef.NonInstantiationEntries;
+    }
+  }
+
+  const FunctionProtoType *Proto = Tmpl->getType()->getAs<FunctionProtoType>();
+  assert(Proto && "Function template without prototype?");
+
+  if (Proto->hasExceptionSpec() || Proto->getNoReturnAttr()) {
+    FunctionProtoType::ExtProtoInfo EPI = Proto->getExtProtoInfo();
+
+    // DR1330: In C++11, defer instantiation of a non-trivial
+    // exception specification.
+    if (SemaRef.getLangOpts().CPlusPlus0x &&
+        EPI.ExceptionSpecType != EST_None &&
+        EPI.ExceptionSpecType != EST_DynamicNone &&
+        EPI.ExceptionSpecType != EST_BasicNoexcept) {
+      FunctionDecl *ExceptionSpecTemplate = Tmpl;
+      if (EPI.ExceptionSpecType == EST_Uninstantiated)
+        ExceptionSpecTemplate = EPI.ExceptionSpecTemplate;
+
+      // Mark the function has having an uninstantiated exception specification.
+      const FunctionProtoType *NewProto
+        = New->getType()->getAs<FunctionProtoType>();
+      assert(NewProto && "Template instantiation without function prototype?");
+      EPI = NewProto->getExtProtoInfo();
+      EPI.ExceptionSpecType = EST_Uninstantiated;
+      EPI.ExceptionSpecDecl = New;
+      EPI.ExceptionSpecTemplate = ExceptionSpecTemplate;
+      New->setType(SemaRef.Context.getFunctionType(NewProto->getResultType(),
+                                                   NewProto->arg_type_begin(),
+                                                   NewProto->getNumArgs(),
+                                                   EPI));
+    } else {
+      ::InstantiateExceptionSpec(SemaRef, New, Proto, TemplateArgs);
+    }
+  }
+
+  // Get the definition. Leaves the variable unchanged if undefined.
+  const FunctionDecl *Definition = Tmpl;
+  Tmpl->isDefined(Definition);
+
+  SemaRef.InstantiateAttrs(TemplateArgs, Definition, New,
+                           LateAttrs, StartingScope);
+
+  return false;
+}
+
+/// \brief Initializes common fields of an instantiated method
+/// declaration (New) from the corresponding fields of its template
+/// (Tmpl).
+///
+/// \returns true if there was an error
+bool
+TemplateDeclInstantiator::InitMethodInstantiation(CXXMethodDecl *New,
+                                                  CXXMethodDecl *Tmpl) {
+  if (InitFunctionInstantiation(New, Tmpl))
+    return true;
+
+  New->setAccess(Tmpl->getAccess());
+  if (Tmpl->isVirtualAsWritten())
+    New->setVirtualAsWritten(true);
+
+  // FIXME: attributes
+  // FIXME: New needs a pointer to Tmpl
+  return false;
+}
+
+/// \brief Instantiate the definition of the given function from its
+/// template.
+///
+/// \param PointOfInstantiation the point at which the instantiation was
+/// required. Note that this is not precisely a "point of instantiation"
+/// for the function, but it's close.
+///
+/// \param Function the already-instantiated declaration of a
+/// function template specialization or member function of a class template
+/// specialization.
+///
+/// \param Recursive if true, recursively instantiates any functions that
+/// are required by this instantiation.
+///
+/// \param DefinitionRequired if true, then we are performing an explicit
+/// instantiation where the body of the function is required. Complain if
+/// there is no such body.
+void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,
+                                         FunctionDecl *Function,
+                                         bool Recursive,
+                                         bool DefinitionRequired) {
+  if (Function->isInvalidDecl() || Function->isDefined())
+    return;
+
+  // Never instantiate an explicit specialization except if it is a class scope
+  // explicit specialization.
+  if (Function->getTemplateSpecializationKind() == TSK_ExplicitSpecialization &&
+      !Function->getClassScopeSpecializationPattern())
+    return;
+
+  // Find the function body that we'll be substituting.
+  const FunctionDecl *PatternDecl = Function->getTemplateInstantiationPattern();
+  assert(PatternDecl && "instantiating a non-template");
+
+  Stmt *Pattern = PatternDecl->getBody(PatternDecl);
+  assert(PatternDecl && "template definition is not a template");
+  if (!Pattern) {
+    // Try to find a defaulted definition
+    PatternDecl->isDefined(PatternDecl);
+  }
+  assert(PatternDecl && "template definition is not a template");
+
+  // Postpone late parsed template instantiations.
+  if (PatternDecl->isLateTemplateParsed() &&
+      !LateTemplateParser) {
+    PendingInstantiations.push_back(
+      std::make_pair(Function, PointOfInstantiation));
+    return;
+  }
+
+  // Call the LateTemplateParser callback if there a need to late parse
+  // a templated function definition.
+  if (!Pattern && PatternDecl->isLateTemplateParsed() &&
+      LateTemplateParser) {
+    LateTemplateParser(OpaqueParser, PatternDecl);
+    Pattern = PatternDecl->getBody(PatternDecl);
+  }
+
+  if (!Pattern && !PatternDecl->isDefaulted()) {
+    if (DefinitionRequired) {
+      if (Function->getPrimaryTemplate())
+        Diag(PointOfInstantiation,
+             diag::err_explicit_instantiation_undefined_func_template)
+          << Function->getPrimaryTemplate();
+      else
+        Diag(PointOfInstantiation,
+             diag::err_explicit_instantiation_undefined_member)
+          << 1 << Function->getDeclName() << Function->getDeclContext();
+
+      if (PatternDecl)
+        Diag(PatternDecl->getLocation(),
+             diag::note_explicit_instantiation_here);
+      Function->setInvalidDecl();
+    } else if (Function->getTemplateSpecializationKind()
+                 == TSK_ExplicitInstantiationDefinition) {
+      PendingInstantiations.push_back(
+        std::make_pair(Function, PointOfInstantiation));
+    }
+
+    return;
+  }
+
+  // C++0x [temp.explicit]p9:
+  //   Except for inline functions, other explicit instantiation declarations
+  //   have the effect of suppressing the implicit instantiation of the entity
+  //   to which they refer.
+  if (Function->getTemplateSpecializationKind()
+        == TSK_ExplicitInstantiationDeclaration &&
+      !PatternDecl->isInlined())
+    return;
+
+  InstantiatingTemplate Inst(*this, PointOfInstantiation, Function);
+  if (Inst)
+    return;
+
+  // Copy the inner loc start from the pattern.
+  Function->setInnerLocStart(PatternDecl->getInnerLocStart());
+
+  // If we're performing recursive template instantiation, create our own
+  // queue of pending implicit instantiations that we will instantiate later,
+  // while we're still within our own instantiation context.
+  SmallVector<VTableUse, 16> SavedVTableUses;
+  std::deque<PendingImplicitInstantiation> SavedPendingInstantiations;
+  if (Recursive) {
+    VTableUses.swap(SavedVTableUses);
+    PendingInstantiations.swap(SavedPendingInstantiations);
+  }
+
+  EnterExpressionEvaluationContext EvalContext(*this,
+                                               Sema::PotentiallyEvaluated);
+  ActOnStartOfFunctionDef(0, Function);
+
+  // Introduce a new scope where local variable instantiations will be
+  // recorded, unless we're actually a member function within a local
+  // class, in which case we need to merge our results with the parent
+  // scope (of the enclosing function).
+  bool MergeWithParentScope = false;
+  if (CXXRecordDecl *Rec = dyn_cast<CXXRecordDecl>(Function->getDeclContext()))
+    MergeWithParentScope = Rec->isLocalClass();
+
+  LocalInstantiationScope Scope(*this, MergeWithParentScope);
+
+  // Enter the scope of this instantiation. We don't use
+  // PushDeclContext because we don't have a scope.
+  Sema::ContextRAII savedContext(*this, Function);
+
+  MultiLevelTemplateArgumentList TemplateArgs =
+    getTemplateInstantiationArgs(Function, 0, false, PatternDecl);
+
+  addInstantiatedParametersToScope(*this, Function, PatternDecl, Scope,
+                                   TemplateArgs);
+
+  if (PatternDecl->isDefaulted()) {
+    ActOnFinishFunctionBody(Function, 0, /*IsInstantiation=*/true);
+
+    SetDeclDefaulted(Function, PatternDecl->getLocation());
+  } else {
+    // If this is a constructor, instantiate the member initializers.
+    if (const CXXConstructorDecl *Ctor =
+          dyn_cast<CXXConstructorDecl>(PatternDecl)) {
+      InstantiateMemInitializers(cast<CXXConstructorDecl>(Function), Ctor,
+                                 TemplateArgs);
+    }
+
+    // Instantiate the function body.
+    StmtResult Body = SubstStmt(Pattern, TemplateArgs);
+
+    if (Body.isInvalid())
+      Function->setInvalidDecl();
+
+    ActOnFinishFunctionBody(Function, Body.get(),
+                            /*IsInstantiation=*/true);
+  }
+
+  PerformDependentDiagnostics(PatternDecl, TemplateArgs);
+
+  savedContext.pop();
+
+  DeclGroupRef DG(Function);
+  Consumer.HandleTopLevelDecl(DG);
+
+  // This class may have local implicit instantiations that need to be
+  // instantiation within this scope.
+  PerformPendingInstantiations(/*LocalOnly=*/true);
+  Scope.Exit();
+
+  if (Recursive) {
+    // Define any pending vtables.
+    DefineUsedVTables();
+
+    // Instantiate any pending implicit instantiations found during the
+    // instantiation of this template.
+    PerformPendingInstantiations();
+
+    // Restore the set of pending vtables.
+    assert(VTableUses.empty() &&
+           "VTableUses should be empty before it is discarded.");
+    VTableUses.swap(SavedVTableUses);
+
+    // Restore the set of pending implicit instantiations.
+    assert(PendingInstantiations.empty() &&
+           "PendingInstantiations should be empty before it is discarded.");
+    PendingInstantiations.swap(SavedPendingInstantiations);
+  }
+}
+
+/// \brief Instantiate the definition of the given variable from its
+/// template.
+///
+/// \param PointOfInstantiation the point at which the instantiation was
+/// required. Note that this is not precisely a "point of instantiation"
+/// for the function, but it's close.
+///
+/// \param Var the already-instantiated declaration of a static member
+/// variable of a class template specialization.
+///
+/// \param Recursive if true, recursively instantiates any functions that
+/// are required by this instantiation.
+///
+/// \param DefinitionRequired if true, then we are performing an explicit
+/// instantiation where an out-of-line definition of the member variable
+/// is required. Complain if there is no such definition.
+void Sema::InstantiateStaticDataMemberDefinition(
+                                          SourceLocation PointOfInstantiation,
+                                                 VarDecl *Var,
+                                                 bool Recursive,
+                                                 bool DefinitionRequired) {
+  if (Var->isInvalidDecl())
+    return;
+
+  // Find the out-of-line definition of this static data member.
+  VarDecl *Def = Var->getInstantiatedFromStaticDataMember();
+  assert(Def && "This data member was not instantiated from a template?");
+  assert(Def->isStaticDataMember() && "Not a static data member?");
+  Def = Def->getOutOfLineDefinition();
+
+  if (!Def) {
+    // We did not find an out-of-line definition of this static data member,
+    // so we won't perform any instantiation. Rather, we rely on the user to
+    // instantiate this definition (or provide a specialization for it) in
+    // another translation unit.
+    if (DefinitionRequired) {
+      Def = Var->getInstantiatedFromStaticDataMember();
+      Diag(PointOfInstantiation,
+           diag::err_explicit_instantiation_undefined_member)
+        << 2 << Var->getDeclName() << Var->getDeclContext();
+      Diag(Def->getLocation(), diag::note_explicit_instantiation_here);
+    } else if (Var->getTemplateSpecializationKind()
+                 == TSK_ExplicitInstantiationDefinition) {
+      PendingInstantiations.push_back(
+        std::make_pair(Var, PointOfInstantiation));
+    }
+
+    return;
+  }
+
+  TemplateSpecializationKind TSK = Var->getTemplateSpecializationKind();
+
+  // Never instantiate an explicit specialization.
+  if (TSK == TSK_ExplicitSpecialization)
+    return;
+
+  // C++0x [temp.explicit]p9:
+  //   Except for inline functions, other explicit instantiation declarations
+  //   have the effect of suppressing the implicit instantiation of the entity
+  //   to which they refer.
+  if (TSK == TSK_ExplicitInstantiationDeclaration)
+    return;
+
+  Consumer.HandleCXXStaticMemberVarInstantiation(Var);
+
+  // If we already have a definition, we're done.
+  if (VarDecl *Def = Var->getDefinition()) {
+    // We may be explicitly instantiating something we've already implicitly
+    // instantiated.
+    Def->setTemplateSpecializationKind(Var->getTemplateSpecializationKind(),
+                                       PointOfInstantiation);
+    return;
+  }
+
+  InstantiatingTemplate Inst(*this, PointOfInstantiation, Var);
+  if (Inst)
+    return;
+
+  // If we're performing recursive template instantiation, create our own
+  // queue of pending implicit instantiations that we will instantiate later,
+  // while we're still within our own instantiation context.
+  SmallVector<VTableUse, 16> SavedVTableUses;
+  std::deque<PendingImplicitInstantiation> SavedPendingInstantiations;
+  if (Recursive) {
+    VTableUses.swap(SavedVTableUses);
+    PendingInstantiations.swap(SavedPendingInstantiations);
+  }
+
+  // Enter the scope of this instantiation. We don't use
+  // PushDeclContext because we don't have a scope.
+  ContextRAII previousContext(*this, Var->getDeclContext());
+  LocalInstantiationScope Local(*this);
+  
+  VarDecl *OldVar = Var;
+  Var = cast_or_null<VarDecl>(SubstDecl(Def, Var->getDeclContext(),
+                                        getTemplateInstantiationArgs(Var)));
+
+  previousContext.pop();
+
+  if (Var) {
+    MemberSpecializationInfo *MSInfo = OldVar->getMemberSpecializationInfo();
+    assert(MSInfo && "Missing member specialization information?");
+    Var->setTemplateSpecializationKind(MSInfo->getTemplateSpecializationKind(),
+                                       MSInfo->getPointOfInstantiation());
+    DeclGroupRef DG(Var);
+    Consumer.HandleTopLevelDecl(DG);
+  }
+  Local.Exit();
+  
+  if (Recursive) {
+    // Define any newly required vtables.
+    DefineUsedVTables();
+
+    // Instantiate any pending implicit instantiations found during the
+    // instantiation of this template.
+    PerformPendingInstantiations();
+
+    // Restore the set of pending vtables.
+    assert(VTableUses.empty() &&
+           "VTableUses should be empty before it is discarded, "
+           "while instantiating static data member.");
+    VTableUses.swap(SavedVTableUses);
+
+    // Restore the set of pending implicit instantiations.
+    assert(PendingInstantiations.empty() &&
+           "PendingInstantiations should be empty before it is discarded, "
+           "while instantiating static data member.");
+    PendingInstantiations.swap(SavedPendingInstantiations);
+  }
+}
+
+void
+Sema::InstantiateMemInitializers(CXXConstructorDecl *New,
+                                 const CXXConstructorDecl *Tmpl,
+                           const MultiLevelTemplateArgumentList &TemplateArgs) {
+
+  SmallVector<CXXCtorInitializer*, 4> NewInits;
+  bool AnyErrors = false;
+
+  // Instantiate all the initializers.
+  for (CXXConstructorDecl::init_const_iterator Inits = Tmpl->init_begin(),
+                                            InitsEnd = Tmpl->init_end();
+       Inits != InitsEnd; ++Inits) {
+    CXXCtorInitializer *Init = *Inits;
+
+    // Only instantiate written initializers, let Sema re-construct implicit
+    // ones.
+    if (!Init->isWritten())
+      continue;
+
+    SourceLocation EllipsisLoc;
+
+    if (Init->isPackExpansion()) {
+      // This is a pack expansion. We should expand it now.
+      TypeLoc BaseTL = Init->getTypeSourceInfo()->getTypeLoc();
+      SmallVector<UnexpandedParameterPack, 2> Unexpanded;
+      collectUnexpandedParameterPacks(BaseTL, Unexpanded);
+      bool ShouldExpand = false;
+      bool RetainExpansion = false;
+      llvm::Optional<unsigned> NumExpansions;
+      if (CheckParameterPacksForExpansion(Init->getEllipsisLoc(),
+                                          BaseTL.getSourceRange(),
+                                          Unexpanded,
+                                          TemplateArgs, ShouldExpand,
+                                          RetainExpansion,
+                                          NumExpansions)) {
+        AnyErrors = true;
+        New->setInvalidDecl();
+        continue;
+      }
+      assert(ShouldExpand && "Partial instantiation of base initializer?");
+
+      // Loop over all of the arguments in the argument pack(s),
+      for (unsigned I = 0; I != *NumExpansions; ++I) {
+        Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(*this, I);
+
+        // Instantiate the initializer.
+        ExprResult TempInit = SubstInitializer(Init->getInit(), TemplateArgs,
+                                               /*CXXDirectInit=*/true);
+        if (TempInit.isInvalid()) {
+          AnyErrors = true;
+          break;
+        }
+
+        // Instantiate the base type.
+        TypeSourceInfo *BaseTInfo = SubstType(Init->getTypeSourceInfo(),
+                                              TemplateArgs,
+                                              Init->getSourceLocation(),
+                                              New->getDeclName());
+        if (!BaseTInfo) {
+          AnyErrors = true;
+          break;
+        }
+
+        // Build the initializer.
+        MemInitResult NewInit = BuildBaseInitializer(BaseTInfo->getType(),
+                                                     BaseTInfo, TempInit.take(),
+                                                     New->getParent(),
+                                                     SourceLocation());
+        if (NewInit.isInvalid()) {
+          AnyErrors = true;
+          break;
+        }
+
+        NewInits.push_back(NewInit.get());
+      }
+
+      continue;
+    }
+
+    // Instantiate the initializer.
+    ExprResult TempInit = SubstInitializer(Init->getInit(), TemplateArgs,
+                                           /*CXXDirectInit=*/true);
+    if (TempInit.isInvalid()) {
+      AnyErrors = true;
+      continue;
+    }
+
+    MemInitResult NewInit;
+    if (Init->isDelegatingInitializer() || Init->isBaseInitializer()) {
+      TypeSourceInfo *TInfo = SubstType(Init->getTypeSourceInfo(),
+                                        TemplateArgs,
+                                        Init->getSourceLocation(),
+                                        New->getDeclName());
+      if (!TInfo) {
+        AnyErrors = true;
+        New->setInvalidDecl();
+        continue;
+      }
+
+      if (Init->isBaseInitializer())
+        NewInit = BuildBaseInitializer(TInfo->getType(), TInfo, TempInit.take(),
+                                       New->getParent(), EllipsisLoc);
+      else
+        NewInit = BuildDelegatingInitializer(TInfo, TempInit.take(),
+                                  cast<CXXRecordDecl>(CurContext->getParent()));
+    } else if (Init->isMemberInitializer()) {
+      FieldDecl *Member = cast_or_null<FieldDecl>(FindInstantiatedDecl(
+                                                     Init->getMemberLocation(),
+                                                     Init->getMember(),
+                                                     TemplateArgs));
+      if (!Member) {
+        AnyErrors = true;
+        New->setInvalidDecl();
+        continue;
+      }
+
+      NewInit = BuildMemberInitializer(Member, TempInit.take(),
+                                       Init->getSourceLocation());
+    } else if (Init->isIndirectMemberInitializer()) {
+      IndirectFieldDecl *IndirectMember =
+         cast_or_null<IndirectFieldDecl>(FindInstantiatedDecl(
+                                 Init->getMemberLocation(),
+                                 Init->getIndirectMember(), TemplateArgs));
+
+      if (!IndirectMember) {
+        AnyErrors = true;
+        New->setInvalidDecl();
+        continue;
+      }
+
+      NewInit = BuildMemberInitializer(IndirectMember, TempInit.take(),
+                                       Init->getSourceLocation());
+    }
+
+    if (NewInit.isInvalid()) {
+      AnyErrors = true;
+      New->setInvalidDecl();
+    } else {
+      NewInits.push_back(NewInit.get());
+    }
+  }
+
+  // Assign all the initializers to the new constructor.
+  ActOnMemInitializers(New,
+                       /*FIXME: ColonLoc */
+                       SourceLocation(),
+                       NewInits.data(), NewInits.size(),
+                       AnyErrors);
+}
+
+ExprResult Sema::SubstInitializer(Expr *Init,
+                          const MultiLevelTemplateArgumentList &TemplateArgs,
+                          bool CXXDirectInit) {
+  // Initializers are instantiated like expressions, except that various outer
+  // layers are stripped.
+  if (!Init)
+    return Owned(Init);
+
+  if (ExprWithCleanups *ExprTemp = dyn_cast<ExprWithCleanups>(Init))
+    Init = ExprTemp->getSubExpr();
+
+  while (CXXBindTemporaryExpr *Binder = dyn_cast<CXXBindTemporaryExpr>(Init))
+    Init = Binder->getSubExpr();
+
+  if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(Init))
+    Init = ICE->getSubExprAsWritten();
+
+  // If this is a direct-initializer, we take apart CXXConstructExprs.
+  // Everything else is passed through.
+  CXXConstructExpr *Construct;
+  if (!CXXDirectInit || !(Construct = dyn_cast<CXXConstructExpr>(Init)) ||
+      isa<CXXTemporaryObjectExpr>(Construct))
+    return SubstExpr(Init, TemplateArgs);
+
+  ASTOwningVector<Expr*> NewArgs(*this);
+  if (SubstExprs(Construct->getArgs(), Construct->getNumArgs(), true,
+                 TemplateArgs, NewArgs))
+    return ExprError();
+
+  // Treat an empty initializer like none.
+  if (NewArgs.empty())
+    return Owned((Expr*)0);
+
+  // Build a ParenListExpr to represent anything else.
+  // FIXME: Fake locations!
+  SourceLocation Loc = PP.getLocForEndOfToken(Init->getLocStart());
+  return ActOnParenListExpr(Loc, Loc, move_arg(NewArgs));
+}
+
+// TODO: this could be templated if the various decl types used the
+// same method name.
+static bool isInstantiationOf(ClassTemplateDecl *Pattern,
+                              ClassTemplateDecl *Instance) {
+  Pattern = Pattern->getCanonicalDecl();
+
+  do {
+    Instance = Instance->getCanonicalDecl();
+    if (Pattern == Instance) return true;
+    Instance = Instance->getInstantiatedFromMemberTemplate();
+  } while (Instance);
+
+  return false;
+}
+
+static bool isInstantiationOf(FunctionTemplateDecl *Pattern,
+                              FunctionTemplateDecl *Instance) {
+  Pattern = Pattern->getCanonicalDecl();
+
+  do {
+    Instance = Instance->getCanonicalDecl();
+    if (Pattern == Instance) return true;
+    Instance = Instance->getInstantiatedFromMemberTemplate();
+  } while (Instance);
+
+  return false;
+}
+
+static bool
+isInstantiationOf(ClassTemplatePartialSpecializationDecl *Pattern,
+                  ClassTemplatePartialSpecializationDecl *Instance) {
+  Pattern
+    = cast<ClassTemplatePartialSpecializationDecl>(Pattern->getCanonicalDecl());
+  do {
+    Instance = cast<ClassTemplatePartialSpecializationDecl>(
+                                                Instance->getCanonicalDecl());
+    if (Pattern == Instance)
+      return true;
+    Instance = Instance->getInstantiatedFromMember();
+  } while (Instance);
+
+  return false;
+}
+
+static bool isInstantiationOf(CXXRecordDecl *Pattern,
+                              CXXRecordDecl *Instance) {
+  Pattern = Pattern->getCanonicalDecl();
+
+  do {
+    Instance = Instance->getCanonicalDecl();
+    if (Pattern == Instance) return true;
+    Instance = Instance->getInstantiatedFromMemberClass();
+  } while (Instance);
+
+  return false;
+}
+
+static bool isInstantiationOf(FunctionDecl *Pattern,
+                              FunctionDecl *Instance) {
+  Pattern = Pattern->getCanonicalDecl();
+
+  do {
+    Instance = Instance->getCanonicalDecl();
+    if (Pattern == Instance) return true;
+    Instance = Instance->getInstantiatedFromMemberFunction();
+  } while (Instance);
+
+  return false;
+}
+
+static bool isInstantiationOf(EnumDecl *Pattern,
+                              EnumDecl *Instance) {
+  Pattern = Pattern->getCanonicalDecl();
+
+  do {
+    Instance = Instance->getCanonicalDecl();
+    if (Pattern == Instance) return true;
+    Instance = Instance->getInstantiatedFromMemberEnum();
+  } while (Instance);
+
+  return false;
+}
+
+static bool isInstantiationOf(UsingShadowDecl *Pattern,
+                              UsingShadowDecl *Instance,
+                              ASTContext &C) {
+  return C.getInstantiatedFromUsingShadowDecl(Instance) == Pattern;
+}
+
+static bool isInstantiationOf(UsingDecl *Pattern,
+                              UsingDecl *Instance,
+                              ASTContext &C) {
+  return C.getInstantiatedFromUsingDecl(Instance) == Pattern;
+}
+
+static bool isInstantiationOf(UnresolvedUsingValueDecl *Pattern,
+                              UsingDecl *Instance,
+                              ASTContext &C) {
+  return C.getInstantiatedFromUsingDecl(Instance) == Pattern;
+}
+
+static bool isInstantiationOf(UnresolvedUsingTypenameDecl *Pattern,
+                              UsingDecl *Instance,
+                              ASTContext &C) {
+  return C.getInstantiatedFromUsingDecl(Instance) == Pattern;
+}
+
+static bool isInstantiationOfStaticDataMember(VarDecl *Pattern,
+                                              VarDecl *Instance) {
+  assert(Instance->isStaticDataMember());
+
+  Pattern = Pattern->getCanonicalDecl();
+
+  do {
+    Instance = Instance->getCanonicalDecl();
+    if (Pattern == Instance) return true;
+    Instance = Instance->getInstantiatedFromStaticDataMember();
+  } while (Instance);
+
+  return false;
+}
+
+// Other is the prospective instantiation
+// D is the prospective pattern
+static bool isInstantiationOf(ASTContext &Ctx, NamedDecl *D, Decl *Other) {
+  if (D->getKind() != Other->getKind()) {
+    if (UnresolvedUsingTypenameDecl *UUD
+          = dyn_cast<UnresolvedUsingTypenameDecl>(D)) {
+      if (UsingDecl *UD = dyn_cast<UsingDecl>(Other)) {
+        return isInstantiationOf(UUD, UD, Ctx);
+      }
+    }
+
+    if (UnresolvedUsingValueDecl *UUD
+          = dyn_cast<UnresolvedUsingValueDecl>(D)) {
+      if (UsingDecl *UD = dyn_cast<UsingDecl>(Other)) {
+        return isInstantiationOf(UUD, UD, Ctx);
+      }
+    }
+
+    return false;
+  }
+
+  if (CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(Other))
+    return isInstantiationOf(cast<CXXRecordDecl>(D), Record);
+
+  if (FunctionDecl *Function = dyn_cast<FunctionDecl>(Other))
+    return isInstantiationOf(cast<FunctionDecl>(D), Function);
+
+  if (EnumDecl *Enum = dyn_cast<EnumDecl>(Other))
+    return isInstantiationOf(cast<EnumDecl>(D), Enum);
+
+  if (VarDecl *Var = dyn_cast<VarDecl>(Other))
+    if (Var->isStaticDataMember())
+      return isInstantiationOfStaticDataMember(cast<VarDecl>(D), Var);
+
+  if (ClassTemplateDecl *Temp = dyn_cast<ClassTemplateDecl>(Other))
+    return isInstantiationOf(cast<ClassTemplateDecl>(D), Temp);
+
+  if (FunctionTemplateDecl *Temp = dyn_cast<FunctionTemplateDecl>(Other))
+    return isInstantiationOf(cast<FunctionTemplateDecl>(D), Temp);
+
+  if (ClassTemplatePartialSpecializationDecl *PartialSpec
+        = dyn_cast<ClassTemplatePartialSpecializationDecl>(Other))
+    return isInstantiationOf(cast<ClassTemplatePartialSpecializationDecl>(D),
+                             PartialSpec);
+
+  if (FieldDecl *Field = dyn_cast<FieldDecl>(Other)) {
+    if (!Field->getDeclName()) {
+      // This is an unnamed field.
+      return Ctx.getInstantiatedFromUnnamedFieldDecl(Field) ==
+        cast<FieldDecl>(D);
+    }
+  }
+
+  if (UsingDecl *Using = dyn_cast<UsingDecl>(Other))
+    return isInstantiationOf(cast<UsingDecl>(D), Using, Ctx);
+
+  if (UsingShadowDecl *Shadow = dyn_cast<UsingShadowDecl>(Other))
+    return isInstantiationOf(cast<UsingShadowDecl>(D), Shadow, Ctx);
+
+  return D->getDeclName() && isa<NamedDecl>(Other) &&
+    D->getDeclName() == cast<NamedDecl>(Other)->getDeclName();
+}
+
+template<typename ForwardIterator>
+static NamedDecl *findInstantiationOf(ASTContext &Ctx,
+                                      NamedDecl *D,
+                                      ForwardIterator first,
+                                      ForwardIterator last) {
+  for (; first != last; ++first)
+    if (isInstantiationOf(Ctx, D, *first))
+      return cast<NamedDecl>(*first);
+
+  return 0;
+}
+
+/// \brief Finds the instantiation of the given declaration context
+/// within the current instantiation.
+///
+/// \returns NULL if there was an error
+DeclContext *Sema::FindInstantiatedContext(SourceLocation Loc, DeclContext* DC,
+                          const MultiLevelTemplateArgumentList &TemplateArgs) {
+  if (NamedDecl *D = dyn_cast<NamedDecl>(DC)) {
+    Decl* ID = FindInstantiatedDecl(Loc, D, TemplateArgs);
+    return cast_or_null<DeclContext>(ID);
+  } else return DC;
+}
+
+/// \brief Find the instantiation of the given declaration within the
+/// current instantiation.
+///
+/// This routine is intended to be used when \p D is a declaration
+/// referenced from within a template, that needs to mapped into the
+/// corresponding declaration within an instantiation. For example,
+/// given:
+///
+/// \code
+/// template<typename T>
+/// struct X {
+///   enum Kind {
+///     KnownValue = sizeof(T)
+///   };
+///
+///   bool getKind() const { return KnownValue; }
+/// };
+///
+/// template struct X<int>;
+/// \endcode
+///
+/// In the instantiation of X<int>::getKind(), we need to map the
+/// EnumConstantDecl for KnownValue (which refers to
+/// X<T>::<Kind>::KnownValue) to its instantiation
+/// (X<int>::<Kind>::KnownValue). InstantiateCurrentDeclRef() performs
+/// this mapping from within the instantiation of X<int>.
+NamedDecl *Sema::FindInstantiatedDecl(SourceLocation Loc, NamedDecl *D,
+                          const MultiLevelTemplateArgumentList &TemplateArgs) {
+  DeclContext *ParentDC = D->getDeclContext();
+  if (isa<ParmVarDecl>(D) || isa<NonTypeTemplateParmDecl>(D) ||
+      isa<TemplateTypeParmDecl>(D) || isa<TemplateTemplateParmDecl>(D) ||
+      (ParentDC->isFunctionOrMethod() && ParentDC->isDependentContext()) ||
+      (isa<CXXRecordDecl>(D) && cast<CXXRecordDecl>(D)->isLambda())) {
+    // D is a local of some kind. Look into the map of local
+    // declarations to their instantiations.
+    typedef LocalInstantiationScope::DeclArgumentPack DeclArgumentPack;
+    llvm::PointerUnion<Decl *, DeclArgumentPack *> *Found
+      = CurrentInstantiationScope->findInstantiationOf(D);
+
+    if (Found) {
+      if (Decl *FD = Found->dyn_cast<Decl *>())
+        return cast<NamedDecl>(FD);
+
+      unsigned PackIdx = ArgumentPackSubstitutionIndex;
+      return cast<NamedDecl>((*Found->get<DeclArgumentPack *>())[PackIdx]);
+    }
+
+    // If we didn't find the decl, then we must have a label decl that hasn't
+    // been found yet.  Lazily instantiate it and return it now.
+    assert(isa<LabelDecl>(D));
+
+    Decl *Inst = SubstDecl(D, CurContext, TemplateArgs);
+    assert(Inst && "Failed to instantiate label??");
+
+    CurrentInstantiationScope->InstantiatedLocal(D, Inst);
+    return cast<LabelDecl>(Inst);
+  }
+
+  if (CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(D)) {
+    if (!Record->isDependentContext())
+      return D;
+
+    // Determine whether this record is the "templated" declaration describing
+    // a class template or class template partial specialization.
+    ClassTemplateDecl *ClassTemplate = Record->getDescribedClassTemplate();
+    if (ClassTemplate)
+      ClassTemplate = ClassTemplate->getCanonicalDecl();
+    else if (ClassTemplatePartialSpecializationDecl *PartialSpec
+               = dyn_cast<ClassTemplatePartialSpecializationDecl>(Record))
+      ClassTemplate = PartialSpec->getSpecializedTemplate()->getCanonicalDecl();
+    
+    // Walk the current context to find either the record or an instantiation of
+    // it.
+    DeclContext *DC = CurContext;
+    while (!DC->isFileContext()) {
+      // If we're performing substitution while we're inside the template
+      // definition, we'll find our own context. We're done.
+      if (DC->Equals(Record))
+        return Record;
+      
+      if (CXXRecordDecl *InstRecord = dyn_cast<CXXRecordDecl>(DC)) {
+        // Check whether we're in the process of instantiating a class template
+        // specialization of the template we're mapping.
+        if (ClassTemplateSpecializationDecl *InstSpec
+                      = dyn_cast<ClassTemplateSpecializationDecl>(InstRecord)){
+          ClassTemplateDecl *SpecTemplate = InstSpec->getSpecializedTemplate();
+          if (ClassTemplate && isInstantiationOf(ClassTemplate, SpecTemplate))
+            return InstRecord;
+        }
+      
+        // Check whether we're in the process of instantiating a member class.
+        if (isInstantiationOf(Record, InstRecord))
+          return InstRecord;
+      }
+      
+      
+      // Move to the outer template scope.
+      if (FunctionDecl *FD = dyn_cast<FunctionDecl>(DC)) {
+        if (FD->getFriendObjectKind() && FD->getDeclContext()->isFileContext()){
+          DC = FD->getLexicalDeclContext();
+          continue;
+        }
+      }
+      
+      DC = DC->getParent();
+    }
+
+    // Fall through to deal with other dependent record types (e.g.,
+    // anonymous unions in class templates).
+  }
+
+  if (!ParentDC->isDependentContext())
+    return D;
+
+  ParentDC = FindInstantiatedContext(Loc, ParentDC, TemplateArgs);
+  if (!ParentDC)
+    return 0;
+
+  if (ParentDC != D->getDeclContext()) {
+    // We performed some kind of instantiation in the parent context,
+    // so now we need to look into the instantiated parent context to
+    // find the instantiation of the declaration D.
+
+    // If our context used to be dependent, we may need to instantiate
+    // it before performing lookup into that context.
+    bool IsBeingInstantiated = false;
+    if (CXXRecordDecl *Spec = dyn_cast<CXXRecordDecl>(ParentDC)) {
+      if (!Spec->isDependentContext()) {
+        QualType T = Context.getTypeDeclType(Spec);
+        const RecordType *Tag = T->getAs<RecordType>();
+        assert(Tag && "type of non-dependent record is not a RecordType");
+        if (Tag->isBeingDefined())
+          IsBeingInstantiated = true;
+        if (!Tag->isBeingDefined() &&
+            RequireCompleteType(Loc, T, diag::err_incomplete_type))
+          return 0;
+
+        ParentDC = Tag->getDecl();
+      }
+    }
+
+    NamedDecl *Result = 0;
+    if (D->getDeclName()) {
+      DeclContext::lookup_result Found = ParentDC->lookup(D->getDeclName());
+      Result = findInstantiationOf(Context, D, Found.first, Found.second);
+    } else {
+      // Since we don't have a name for the entity we're looking for,
+      // our only option is to walk through all of the declarations to
+      // find that name. This will occur in a few cases:
+      //
+      //   - anonymous struct/union within a template
+      //   - unnamed class/struct/union/enum within a template
+      //
+      // FIXME: Find a better way to find these instantiations!
+      Result = findInstantiationOf(Context, D,
+                                   ParentDC->decls_begin(),
+                                   ParentDC->decls_end());
+    }
+
+    if (!Result) {
+      if (isa<UsingShadowDecl>(D)) {
+        // UsingShadowDecls can instantiate to nothing because of using hiding.
+      } else if (Diags.hasErrorOccurred()) {
+        // We've already complained about something, so most likely this
+        // declaration failed to instantiate. There's no point in complaining
+        // further, since this is normal in invalid code.
+      } else if (IsBeingInstantiated) {
+        // The class in which this member exists is currently being
+        // instantiated, and we haven't gotten around to instantiating this
+        // member yet. This can happen when the code uses forward declarations
+        // of member classes, and introduces ordering dependencies via
+        // template instantiation.
+        Diag(Loc, diag::err_member_not_yet_instantiated)
+          << D->getDeclName()
+          << Context.getTypeDeclType(cast<CXXRecordDecl>(ParentDC));
+        Diag(D->getLocation(), diag::note_non_instantiated_member_here);
+      } else if (EnumConstantDecl *ED = dyn_cast<EnumConstantDecl>(D)) {
+        // This enumeration constant was found when the template was defined,
+        // but can't be found in the instantiation. This can happen if an
+        // unscoped enumeration member is explicitly specialized.
+        EnumDecl *Enum = cast<EnumDecl>(ED->getLexicalDeclContext());
+        EnumDecl *Spec = cast<EnumDecl>(FindInstantiatedDecl(Loc, Enum,
+                                                             TemplateArgs));
+        assert(Spec->getTemplateSpecializationKind() ==
+                 TSK_ExplicitSpecialization);
+        Diag(Loc, diag::err_enumerator_does_not_exist)
+          << D->getDeclName()
+          << Context.getTypeDeclType(cast<TypeDecl>(Spec->getDeclContext()));
+        Diag(Spec->getLocation(), diag::note_enum_specialized_here)
+          << Context.getTypeDeclType(Spec);
+      } else {
+        // We should have found something, but didn't.
+        llvm_unreachable("Unable to find instantiation of declaration!");
+      }
+    }
+
+    D = Result;
+  }
+
+  return D;
+}
+
+/// \brief Performs template instantiation for all implicit template
+/// instantiations we have seen until this point.
+void Sema::PerformPendingInstantiations(bool LocalOnly) {
+  // Load pending instantiations from the external source.
+  if (!LocalOnly && ExternalSource) {
+    SmallVector<std::pair<ValueDecl *, SourceLocation>, 4> Pending;
+    ExternalSource->ReadPendingInstantiations(Pending);
+    PendingInstantiations.insert(PendingInstantiations.begin(),
+                                 Pending.begin(), Pending.end());
+  }
+
+  while (!PendingLocalImplicitInstantiations.empty() ||
+         (!LocalOnly && !PendingInstantiations.empty())) {
+    PendingImplicitInstantiation Inst;
+
+    if (PendingLocalImplicitInstantiations.empty()) {
+      Inst = PendingInstantiations.front();
+      PendingInstantiations.pop_front();
+    } else {
+      Inst = PendingLocalImplicitInstantiations.front();
+      PendingLocalImplicitInstantiations.pop_front();
+    }
+
+    // Instantiate function definitions
+    if (FunctionDecl *Function = dyn_cast<FunctionDecl>(Inst.first)) {
+      PrettyDeclStackTraceEntry CrashInfo(*this, Function, SourceLocation(),
+                                          "instantiating function definition");
+      bool DefinitionRequired = Function->getTemplateSpecializationKind() ==
+                                TSK_ExplicitInstantiationDefinition;
+      InstantiateFunctionDefinition(/*FIXME:*/Inst.second, Function, true,
+                                    DefinitionRequired);
+      continue;
+    }
+
+    // Instantiate static data member definitions.
+    VarDecl *Var = cast<VarDecl>(Inst.first);
+    assert(Var->isStaticDataMember() && "Not a static data member?");
+
+    // Don't try to instantiate declarations if the most recent redeclaration
+    // is invalid.
+    if (Var->getMostRecentDecl()->isInvalidDecl())
+      continue;
+
+    // Check if the most recent declaration has changed the specialization kind
+    // and removed the need for implicit instantiation.
+    switch (Var->getMostRecentDecl()->getTemplateSpecializationKind()) {
+    case TSK_Undeclared:
+      llvm_unreachable("Cannot instantitiate an undeclared specialization.");
+    case TSK_ExplicitInstantiationDeclaration:
+    case TSK_ExplicitSpecialization:
+      continue;  // No longer need to instantiate this type.
+    case TSK_ExplicitInstantiationDefinition:
+      // We only need an instantiation if the pending instantiation *is* the
+      // explicit instantiation.
+      if (Var != Var->getMostRecentDecl()) continue;
+    case TSK_ImplicitInstantiation:
+      break;
+    }
+
+    PrettyDeclStackTraceEntry CrashInfo(*this, Var, Var->getLocation(),
+                                        "instantiating static data member "
+                                        "definition");
+
+    bool DefinitionRequired = Var->getTemplateSpecializationKind() ==
+                              TSK_ExplicitInstantiationDefinition;
+    InstantiateStaticDataMemberDefinition(/*FIXME:*/Inst.second, Var, true,
+                                          DefinitionRequired);
+  }
+}
+
+void Sema::PerformDependentDiagnostics(const DeclContext *Pattern,
+                       const MultiLevelTemplateArgumentList &TemplateArgs) {
+  for (DeclContext::ddiag_iterator I = Pattern->ddiag_begin(),
+         E = Pattern->ddiag_end(); I != E; ++I) {
+    DependentDiagnostic *DD = *I;
+
+    switch (DD->getKind()) {
+    case DependentDiagnostic::Access:
+      HandleDependentAccessCheck(*DD, TemplateArgs);
+      break;
+    }
+  }
+}
diff --git a/clang/lib/Sema/SemaTemplateVariadic.cpp b/clang/lib/Sema/SemaTemplateVariadic.cpp
new file mode 100644
index 0000000..a40100c
--- /dev/null
+++ b/clang/lib/Sema/SemaTemplateVariadic.cpp
@@ -0,0 +1,794 @@
+//===------- SemaTemplateVariadic.cpp - C++ Variadic Templates ------------===/
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//===----------------------------------------------------------------------===/
+//
+//  This file implements semantic analysis for C++0x variadic templates.
+//===----------------------------------------------------------------------===/
+
+#include "clang/Sema/Sema.h"
+#include "clang/Sema/Lookup.h"
+#include "clang/Sema/ParsedTemplate.h"
+#include "clang/Sema/SemaInternal.h"
+#include "clang/Sema/Template.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/RecursiveASTVisitor.h"
+#include "clang/AST/TypeLoc.h"
+
+using namespace clang;
+
+//----------------------------------------------------------------------------
+// Visitor that collects unexpanded parameter packs
+//----------------------------------------------------------------------------
+
+namespace {
+  /// \brief A class that collects unexpanded parameter packs.
+  class CollectUnexpandedParameterPacksVisitor :
+    public RecursiveASTVisitor<CollectUnexpandedParameterPacksVisitor> 
+  {
+    typedef RecursiveASTVisitor<CollectUnexpandedParameterPacksVisitor>
+      inherited;
+
+    SmallVectorImpl<UnexpandedParameterPack> &Unexpanded;
+
+  public:
+    explicit CollectUnexpandedParameterPacksVisitor(
+                  SmallVectorImpl<UnexpandedParameterPack> &Unexpanded)
+      : Unexpanded(Unexpanded) { }
+
+    bool shouldWalkTypesOfTypeLocs() const { return false; }
+    
+    //------------------------------------------------------------------------
+    // Recording occurrences of (unexpanded) parameter packs.
+    //------------------------------------------------------------------------
+
+    /// \brief Record occurrences of template type parameter packs.
+    bool VisitTemplateTypeParmTypeLoc(TemplateTypeParmTypeLoc TL) {
+      if (TL.getTypePtr()->isParameterPack())
+        Unexpanded.push_back(std::make_pair(TL.getTypePtr(), TL.getNameLoc()));
+      return true;
+    }
+
+    /// \brief Record occurrences of template type parameter packs
+    /// when we don't have proper source-location information for
+    /// them.
+    ///
+    /// Ideally, this routine would never be used.
+    bool VisitTemplateTypeParmType(TemplateTypeParmType *T) {
+      if (T->isParameterPack())
+        Unexpanded.push_back(std::make_pair(T, SourceLocation()));
+
+      return true;
+    }
+
+    /// \brief Record occurrences of function and non-type template
+    /// parameter packs in an expression.
+    bool VisitDeclRefExpr(DeclRefExpr *E) {
+      if (E->getDecl()->isParameterPack())
+        Unexpanded.push_back(std::make_pair(E->getDecl(), E->getLocation()));
+      
+      return true;
+    }
+    
+    /// \brief Record occurrences of template template parameter packs.
+    bool TraverseTemplateName(TemplateName Template) {
+      if (TemplateTemplateParmDecl *TTP 
+            = dyn_cast_or_null<TemplateTemplateParmDecl>(
+                                                  Template.getAsTemplateDecl()))
+        if (TTP->isParameterPack())
+          Unexpanded.push_back(std::make_pair(TTP, SourceLocation()));
+      
+      return inherited::TraverseTemplateName(Template);
+    }
+
+    /// \brief Suppress traversal into Objective-C container literal
+    /// elements that are pack expansions.
+    bool TraverseObjCDictionaryLiteral(ObjCDictionaryLiteral *E) {
+      if (!E->containsUnexpandedParameterPack())
+        return true;
+
+      for (unsigned I = 0, N = E->getNumElements(); I != N; ++I) {
+        ObjCDictionaryElement Element = E->getKeyValueElement(I);
+        if (Element.isPackExpansion())
+          continue;
+
+        TraverseStmt(Element.Key);
+        TraverseStmt(Element.Value);
+      }
+      return true;
+    }
+    //------------------------------------------------------------------------
+    // Pruning the search for unexpanded parameter packs.
+    //------------------------------------------------------------------------
+
+    /// \brief Suppress traversal into statements and expressions that
+    /// do not contain unexpanded parameter packs.
+    bool TraverseStmt(Stmt *S) { 
+      if (Expr *E = dyn_cast_or_null<Expr>(S))
+        if (E->containsUnexpandedParameterPack())
+          return inherited::TraverseStmt(E);
+
+      return true; 
+    }
+
+    /// \brief Suppress traversal into types that do not contain
+    /// unexpanded parameter packs.
+    bool TraverseType(QualType T) {
+      if (!T.isNull() && T->containsUnexpandedParameterPack())
+        return inherited::TraverseType(T);
+
+      return true;
+    }
+
+    /// \brief Suppress traversel into types with location information
+    /// that do not contain unexpanded parameter packs.
+    bool TraverseTypeLoc(TypeLoc TL) {
+      if (!TL.getType().isNull() && 
+          TL.getType()->containsUnexpandedParameterPack())
+        return inherited::TraverseTypeLoc(TL);
+
+      return true;
+    }
+
+    /// \brief Suppress traversal of non-parameter declarations, since
+    /// they cannot contain unexpanded parameter packs.
+    bool TraverseDecl(Decl *D) { 
+      if (D && isa<ParmVarDecl>(D))
+        return inherited::TraverseDecl(D);
+
+      return true; 
+    }
+
+    /// \brief Suppress traversal of template argument pack expansions.
+    bool TraverseTemplateArgument(const TemplateArgument &Arg) {
+      if (Arg.isPackExpansion())
+        return true;
+
+      return inherited::TraverseTemplateArgument(Arg);
+    }
+
+    /// \brief Suppress traversal of template argument pack expansions.
+    bool TraverseTemplateArgumentLoc(const TemplateArgumentLoc &ArgLoc) {
+      if (ArgLoc.getArgument().isPackExpansion())
+        return true;
+      
+      return inherited::TraverseTemplateArgumentLoc(ArgLoc);
+    }
+  };
+}
+
+/// \brief Diagnose all of the unexpanded parameter packs in the given
+/// vector.
+void
+Sema::DiagnoseUnexpandedParameterPacks(SourceLocation Loc,
+                                       UnexpandedParameterPackContext UPPC,
+                                 ArrayRef<UnexpandedParameterPack> Unexpanded) {
+  if (Unexpanded.empty())
+    return;
+  
+  SmallVector<SourceLocation, 4> Locations;
+  SmallVector<IdentifierInfo *, 4> Names;
+  llvm::SmallPtrSet<IdentifierInfo *, 4> NamesKnown;
+
+  for (unsigned I = 0, N = Unexpanded.size(); I != N; ++I) {
+    IdentifierInfo *Name = 0;
+    if (const TemplateTypeParmType *TTP
+          = Unexpanded[I].first.dyn_cast<const TemplateTypeParmType *>())
+      Name = TTP->getIdentifier();
+    else
+      Name = Unexpanded[I].first.get<NamedDecl *>()->getIdentifier();
+
+    if (Name && NamesKnown.insert(Name))
+      Names.push_back(Name);
+
+    if (Unexpanded[I].second.isValid())
+      Locations.push_back(Unexpanded[I].second);
+  }
+
+  DiagnosticBuilder DB
+    = Names.size() == 0? Diag(Loc, diag::err_unexpanded_parameter_pack_0)
+                           << (int)UPPC
+    : Names.size() == 1? Diag(Loc, diag::err_unexpanded_parameter_pack_1)
+                           << (int)UPPC << Names[0]
+    : Names.size() == 2? Diag(Loc, diag::err_unexpanded_parameter_pack_2)
+                           << (int)UPPC << Names[0] << Names[1]
+    : Diag(Loc, diag::err_unexpanded_parameter_pack_3_or_more)
+        << (int)UPPC << Names[0] << Names[1];
+
+  for (unsigned I = 0, N = Locations.size(); I != N; ++I)
+    DB << SourceRange(Locations[I]);
+}
+
+bool Sema::DiagnoseUnexpandedParameterPack(SourceLocation Loc, 
+                                           TypeSourceInfo *T,
+                                         UnexpandedParameterPackContext UPPC) {
+  // C++0x [temp.variadic]p5:
+  //   An appearance of a name of a parameter pack that is not expanded is 
+  //   ill-formed.
+  if (!T->getType()->containsUnexpandedParameterPack())
+    return false;
+
+  SmallVector<UnexpandedParameterPack, 2> Unexpanded;
+  CollectUnexpandedParameterPacksVisitor(Unexpanded).TraverseTypeLoc(
+                                                              T->getTypeLoc());
+  assert(!Unexpanded.empty() && "Unable to find unexpanded parameter packs");
+  DiagnoseUnexpandedParameterPacks(Loc, UPPC, Unexpanded);
+  return true;
+}
+
+bool Sema::DiagnoseUnexpandedParameterPack(Expr *E,
+                                        UnexpandedParameterPackContext UPPC) {
+  // C++0x [temp.variadic]p5:
+  //   An appearance of a name of a parameter pack that is not expanded is 
+  //   ill-formed.
+  if (!E->containsUnexpandedParameterPack())
+    return false;
+
+  SmallVector<UnexpandedParameterPack, 2> Unexpanded;
+  CollectUnexpandedParameterPacksVisitor(Unexpanded).TraverseStmt(E);
+  assert(!Unexpanded.empty() && "Unable to find unexpanded parameter packs");
+  DiagnoseUnexpandedParameterPacks(E->getLocStart(), UPPC, Unexpanded);
+  return true;
+}
+
+bool Sema::DiagnoseUnexpandedParameterPack(const CXXScopeSpec &SS,
+                                        UnexpandedParameterPackContext UPPC) {
+  // C++0x [temp.variadic]p5:
+  //   An appearance of a name of a parameter pack that is not expanded is 
+  //   ill-formed.
+  if (!SS.getScopeRep() || 
+      !SS.getScopeRep()->containsUnexpandedParameterPack())
+    return false;
+
+  SmallVector<UnexpandedParameterPack, 2> Unexpanded;
+  CollectUnexpandedParameterPacksVisitor(Unexpanded)
+    .TraverseNestedNameSpecifier(SS.getScopeRep());
+  assert(!Unexpanded.empty() && "Unable to find unexpanded parameter packs");
+  DiagnoseUnexpandedParameterPacks(SS.getRange().getBegin(), 
+                                   UPPC, Unexpanded);
+  return true;
+}
+
+bool Sema::DiagnoseUnexpandedParameterPack(const DeclarationNameInfo &NameInfo,
+                                         UnexpandedParameterPackContext UPPC) {
+  // C++0x [temp.variadic]p5:
+  //   An appearance of a name of a parameter pack that is not expanded is 
+  //   ill-formed.
+  switch (NameInfo.getName().getNameKind()) {
+  case DeclarationName::Identifier:
+  case DeclarationName::ObjCZeroArgSelector:
+  case DeclarationName::ObjCOneArgSelector:
+  case DeclarationName::ObjCMultiArgSelector:
+  case DeclarationName::CXXOperatorName:
+  case DeclarationName::CXXLiteralOperatorName:
+  case DeclarationName::CXXUsingDirective:
+    return false;
+
+  case DeclarationName::CXXConstructorName:
+  case DeclarationName::CXXDestructorName:
+  case DeclarationName::CXXConversionFunctionName:
+    // FIXME: We shouldn't need this null check!
+    if (TypeSourceInfo *TSInfo = NameInfo.getNamedTypeInfo())
+      return DiagnoseUnexpandedParameterPack(NameInfo.getLoc(), TSInfo, UPPC);
+
+    if (!NameInfo.getName().getCXXNameType()->containsUnexpandedParameterPack())
+      return false;
+
+    break;
+  }
+
+  SmallVector<UnexpandedParameterPack, 2> Unexpanded;
+  CollectUnexpandedParameterPacksVisitor(Unexpanded)
+    .TraverseType(NameInfo.getName().getCXXNameType());
+  assert(!Unexpanded.empty() && "Unable to find unexpanded parameter packs");
+  DiagnoseUnexpandedParameterPacks(NameInfo.getLoc(), UPPC, Unexpanded);
+  return true;
+}
+
+bool Sema::DiagnoseUnexpandedParameterPack(SourceLocation Loc,
+                                           TemplateName Template,
+                                       UnexpandedParameterPackContext UPPC) {
+  
+  if (Template.isNull() || !Template.containsUnexpandedParameterPack())
+    return false;
+
+  SmallVector<UnexpandedParameterPack, 2> Unexpanded;
+  CollectUnexpandedParameterPacksVisitor(Unexpanded)
+    .TraverseTemplateName(Template);
+  assert(!Unexpanded.empty() && "Unable to find unexpanded parameter packs");
+  DiagnoseUnexpandedParameterPacks(Loc, UPPC, Unexpanded);
+  return true;
+}
+
+bool Sema::DiagnoseUnexpandedParameterPack(TemplateArgumentLoc Arg,
+                                         UnexpandedParameterPackContext UPPC) {
+  if (Arg.getArgument().isNull() || 
+      !Arg.getArgument().containsUnexpandedParameterPack())
+    return false;
+  
+  SmallVector<UnexpandedParameterPack, 2> Unexpanded;
+  CollectUnexpandedParameterPacksVisitor(Unexpanded)
+    .TraverseTemplateArgumentLoc(Arg);
+  assert(!Unexpanded.empty() && "Unable to find unexpanded parameter packs");
+  DiagnoseUnexpandedParameterPacks(Arg.getLocation(), UPPC, Unexpanded);
+  return true;  
+}
+
+void Sema::collectUnexpandedParameterPacks(TemplateArgument Arg,
+                   SmallVectorImpl<UnexpandedParameterPack> &Unexpanded) {
+  CollectUnexpandedParameterPacksVisitor(Unexpanded)
+    .TraverseTemplateArgument(Arg);
+}
+
+void Sema::collectUnexpandedParameterPacks(TemplateArgumentLoc Arg,
+                   SmallVectorImpl<UnexpandedParameterPack> &Unexpanded) {
+  CollectUnexpandedParameterPacksVisitor(Unexpanded)
+    .TraverseTemplateArgumentLoc(Arg);
+}
+
+void Sema::collectUnexpandedParameterPacks(QualType T,
+                   SmallVectorImpl<UnexpandedParameterPack> &Unexpanded) {
+  CollectUnexpandedParameterPacksVisitor(Unexpanded).TraverseType(T);  
+}  
+
+void Sema::collectUnexpandedParameterPacks(TypeLoc TL,
+                   SmallVectorImpl<UnexpandedParameterPack> &Unexpanded) {
+  CollectUnexpandedParameterPacksVisitor(Unexpanded).TraverseTypeLoc(TL);  
+}  
+
+void Sema::collectUnexpandedParameterPacks(CXXScopeSpec &SS,
+                                           SmallVectorImpl<UnexpandedParameterPack> &Unexpanded) {
+  NestedNameSpecifier *Qualifier = SS.getScopeRep();
+  if (!Qualifier)
+    return;
+  
+  NestedNameSpecifierLoc QualifierLoc(Qualifier, SS.location_data());
+  CollectUnexpandedParameterPacksVisitor(Unexpanded)
+    .TraverseNestedNameSpecifierLoc(QualifierLoc);
+}
+
+void Sema::collectUnexpandedParameterPacks(const DeclarationNameInfo &NameInfo,
+                         SmallVectorImpl<UnexpandedParameterPack> &Unexpanded) {
+  CollectUnexpandedParameterPacksVisitor(Unexpanded)
+    .TraverseDeclarationNameInfo(NameInfo);
+}
+
+
+ParsedTemplateArgument 
+Sema::ActOnPackExpansion(const ParsedTemplateArgument &Arg,
+                         SourceLocation EllipsisLoc) {
+  if (Arg.isInvalid())
+    return Arg;
+
+  switch (Arg.getKind()) {
+  case ParsedTemplateArgument::Type: {
+    TypeResult Result = ActOnPackExpansion(Arg.getAsType(), EllipsisLoc);
+    if (Result.isInvalid())
+      return ParsedTemplateArgument();
+
+    return ParsedTemplateArgument(Arg.getKind(), Result.get().getAsOpaquePtr(), 
+                                  Arg.getLocation());
+  }
+
+  case ParsedTemplateArgument::NonType: {
+    ExprResult Result = ActOnPackExpansion(Arg.getAsExpr(), EllipsisLoc);
+    if (Result.isInvalid())
+      return ParsedTemplateArgument();
+    
+    return ParsedTemplateArgument(Arg.getKind(), Result.get(), 
+                                  Arg.getLocation());
+  }
+    
+  case ParsedTemplateArgument::Template:
+    if (!Arg.getAsTemplate().get().containsUnexpandedParameterPack()) {
+      SourceRange R(Arg.getLocation());
+      if (Arg.getScopeSpec().isValid())
+        R.setBegin(Arg.getScopeSpec().getBeginLoc());
+      Diag(EllipsisLoc, diag::err_pack_expansion_without_parameter_packs)
+        << R;
+      return ParsedTemplateArgument();
+    }
+      
+    return Arg.getTemplatePackExpansion(EllipsisLoc);
+  }
+  llvm_unreachable("Unhandled template argument kind?");
+}
+
+TypeResult Sema::ActOnPackExpansion(ParsedType Type, 
+                                    SourceLocation EllipsisLoc) {
+  TypeSourceInfo *TSInfo;
+  GetTypeFromParser(Type, &TSInfo);
+  if (!TSInfo)
+    return true;
+
+  TypeSourceInfo *TSResult = CheckPackExpansion(TSInfo, EllipsisLoc,
+                                                llvm::Optional<unsigned>());
+  if (!TSResult)
+    return true;
+  
+  return CreateParsedType(TSResult->getType(), TSResult);
+}
+
+TypeSourceInfo *Sema::CheckPackExpansion(TypeSourceInfo *Pattern,
+                                         SourceLocation EllipsisLoc,
+                                       llvm::Optional<unsigned> NumExpansions) {
+  // Create the pack expansion type and source-location information.
+  QualType Result = CheckPackExpansion(Pattern->getType(), 
+                                       Pattern->getTypeLoc().getSourceRange(),
+                                       EllipsisLoc, NumExpansions);
+  if (Result.isNull())
+    return 0;
+  
+  TypeSourceInfo *TSResult = Context.CreateTypeSourceInfo(Result);
+  PackExpansionTypeLoc TL = cast<PackExpansionTypeLoc>(TSResult->getTypeLoc());
+  TL.setEllipsisLoc(EllipsisLoc);
+  
+  // Copy over the source-location information from the type.
+  memcpy(TL.getNextTypeLoc().getOpaqueData(),
+         Pattern->getTypeLoc().getOpaqueData(),
+         Pattern->getTypeLoc().getFullDataSize());
+  return TSResult;
+}
+
+QualType Sema::CheckPackExpansion(QualType Pattern,
+                                  SourceRange PatternRange,
+                                  SourceLocation EllipsisLoc,
+                                  llvm::Optional<unsigned> NumExpansions) {
+  // C++0x [temp.variadic]p5:
+  //   The pattern of a pack expansion shall name one or more
+  //   parameter packs that are not expanded by a nested pack
+  //   expansion.
+  if (!Pattern->containsUnexpandedParameterPack()) {
+    Diag(EllipsisLoc, diag::err_pack_expansion_without_parameter_packs)
+      << PatternRange;
+    return QualType();
+  }
+
+  return Context.getPackExpansionType(Pattern, NumExpansions);
+}
+
+ExprResult Sema::ActOnPackExpansion(Expr *Pattern, SourceLocation EllipsisLoc) {
+  return CheckPackExpansion(Pattern, EllipsisLoc, llvm::Optional<unsigned>());
+}
+
+ExprResult Sema::CheckPackExpansion(Expr *Pattern, SourceLocation EllipsisLoc,
+                                    llvm::Optional<unsigned> NumExpansions) {
+  if (!Pattern)
+    return ExprError();
+  
+  // C++0x [temp.variadic]p5:
+  //   The pattern of a pack expansion shall name one or more
+  //   parameter packs that are not expanded by a nested pack
+  //   expansion.
+  if (!Pattern->containsUnexpandedParameterPack()) {
+    Diag(EllipsisLoc, diag::err_pack_expansion_without_parameter_packs)
+    << Pattern->getSourceRange();
+    return ExprError();
+  }
+  
+  // Create the pack expansion expression and source-location information.
+  return Owned(new (Context) PackExpansionExpr(Context.DependentTy, Pattern,
+                                               EllipsisLoc, NumExpansions));
+}
+
+/// \brief Retrieve the depth and index of a parameter pack.
+static std::pair<unsigned, unsigned> 
+getDepthAndIndex(NamedDecl *ND) {
+  if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(ND))
+    return std::make_pair(TTP->getDepth(), TTP->getIndex());
+  
+  if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(ND))
+    return std::make_pair(NTTP->getDepth(), NTTP->getIndex());
+  
+  TemplateTemplateParmDecl *TTP = cast<TemplateTemplateParmDecl>(ND);
+  return std::make_pair(TTP->getDepth(), TTP->getIndex());
+}
+
+bool Sema::CheckParameterPacksForExpansion(SourceLocation EllipsisLoc,
+                                           SourceRange PatternRange,
+                                   ArrayRef<UnexpandedParameterPack> Unexpanded,
+                             const MultiLevelTemplateArgumentList &TemplateArgs,
+                                           bool &ShouldExpand,
+                                           bool &RetainExpansion,
+                                     llvm::Optional<unsigned> &NumExpansions) {                                        
+  ShouldExpand = true;
+  RetainExpansion = false;
+  std::pair<IdentifierInfo *, SourceLocation> FirstPack;
+  bool HaveFirstPack = false;
+  
+  for (ArrayRef<UnexpandedParameterPack>::iterator i = Unexpanded.begin(),
+                                                 end = Unexpanded.end();
+                                                  i != end; ++i) {
+    // Compute the depth and index for this parameter pack.
+    unsigned Depth = 0, Index = 0;
+    IdentifierInfo *Name;
+    bool IsFunctionParameterPack = false;
+    
+    if (const TemplateTypeParmType *TTP
+        = i->first.dyn_cast<const TemplateTypeParmType *>()) {
+      Depth = TTP->getDepth();
+      Index = TTP->getIndex();
+      Name = TTP->getIdentifier();
+    } else {
+      NamedDecl *ND = i->first.get<NamedDecl *>();
+      if (isa<ParmVarDecl>(ND))
+        IsFunctionParameterPack = true;
+      else
+        llvm::tie(Depth, Index) = getDepthAndIndex(ND);        
+      
+      Name = ND->getIdentifier();
+    }
+    
+    // Determine the size of this argument pack.
+    unsigned NewPackSize;    
+    if (IsFunctionParameterPack) {
+      // Figure out whether we're instantiating to an argument pack or not.
+      typedef LocalInstantiationScope::DeclArgumentPack DeclArgumentPack;
+      
+      llvm::PointerUnion<Decl *, DeclArgumentPack *> *Instantiation
+        = CurrentInstantiationScope->findInstantiationOf(
+                                        i->first.get<NamedDecl *>());
+      if (Instantiation->is<DeclArgumentPack *>()) {
+        // We could expand this function parameter pack.
+        NewPackSize = Instantiation->get<DeclArgumentPack *>()->size();
+      } else {
+        // We can't expand this function parameter pack, so we can't expand
+        // the pack expansion.
+        ShouldExpand = false;
+        continue;
+      }
+    } else {
+      // If we don't have a template argument at this depth/index, then we 
+      // cannot expand the pack expansion. Make a note of this, but we still 
+      // want to check any parameter packs we *do* have arguments for.
+      if (Depth >= TemplateArgs.getNumLevels() ||
+          !TemplateArgs.hasTemplateArgument(Depth, Index)) {
+        ShouldExpand = false;
+        continue;
+      }
+      
+      // Determine the size of the argument pack.
+      NewPackSize = TemplateArgs(Depth, Index).pack_size();
+    }
+    
+    // C++0x [temp.arg.explicit]p9:
+    //   Template argument deduction can extend the sequence of template 
+    //   arguments corresponding to a template parameter pack, even when the
+    //   sequence contains explicitly specified template arguments.
+    if (!IsFunctionParameterPack) {
+      if (NamedDecl *PartialPack 
+                    = CurrentInstantiationScope->getPartiallySubstitutedPack()){
+        unsigned PartialDepth, PartialIndex;
+        llvm::tie(PartialDepth, PartialIndex) = getDepthAndIndex(PartialPack);
+        if (PartialDepth == Depth && PartialIndex == Index)
+          RetainExpansion = true;
+      }
+    }
+    
+    if (!NumExpansions) {
+      // The is the first pack we've seen for which we have an argument. 
+      // Record it.
+      NumExpansions = NewPackSize;
+      FirstPack.first = Name;
+      FirstPack.second = i->second;
+      HaveFirstPack = true;
+      continue;
+    }
+    
+    if (NewPackSize != *NumExpansions) {
+      // C++0x [temp.variadic]p5:
+      //   All of the parameter packs expanded by a pack expansion shall have 
+      //   the same number of arguments specified.
+      if (HaveFirstPack)
+        Diag(EllipsisLoc, diag::err_pack_expansion_length_conflict)
+          << FirstPack.first << Name << *NumExpansions << NewPackSize
+          << SourceRange(FirstPack.second) << SourceRange(i->second);
+      else
+        Diag(EllipsisLoc, diag::err_pack_expansion_length_conflict_multilevel)
+          << Name << *NumExpansions << NewPackSize
+          << SourceRange(i->second);
+      return true;
+    }
+  }
+  
+  return false;
+}
+
+unsigned Sema::getNumArgumentsInExpansion(QualType T, 
+                          const MultiLevelTemplateArgumentList &TemplateArgs) {
+  QualType Pattern = cast<PackExpansionType>(T)->getPattern();
+  SmallVector<UnexpandedParameterPack, 2> Unexpanded;
+  CollectUnexpandedParameterPacksVisitor(Unexpanded).TraverseType(Pattern);
+
+  for (unsigned I = 0, N = Unexpanded.size(); I != N; ++I) {
+    // Compute the depth and index for this parameter pack.
+    unsigned Depth;
+    unsigned Index;
+    
+    if (const TemplateTypeParmType *TTP
+          = Unexpanded[I].first.dyn_cast<const TemplateTypeParmType *>()) {
+      Depth = TTP->getDepth();
+      Index = TTP->getIndex();
+    } else {      
+      NamedDecl *ND = Unexpanded[I].first.get<NamedDecl *>();
+      if (isa<ParmVarDecl>(ND)) {
+        // Function parameter pack.
+        typedef LocalInstantiationScope::DeclArgumentPack DeclArgumentPack;
+        
+        llvm::PointerUnion<Decl *, DeclArgumentPack *> *Instantiation
+          = CurrentInstantiationScope->findInstantiationOf(
+                                        Unexpanded[I].first.get<NamedDecl *>());
+        if (Instantiation->is<DeclArgumentPack *>())
+          return Instantiation->get<DeclArgumentPack *>()->size();
+        
+        continue;
+      }
+      
+      llvm::tie(Depth, Index) = getDepthAndIndex(ND);        
+    }
+    if (Depth >= TemplateArgs.getNumLevels() ||
+        !TemplateArgs.hasTemplateArgument(Depth, Index))
+      continue;
+    
+    // Determine the size of the argument pack.
+    return TemplateArgs(Depth, Index).pack_size();
+  }
+  
+  llvm_unreachable("No unexpanded parameter packs in type expansion.");
+}
+
+bool Sema::containsUnexpandedParameterPacks(Declarator &D) {
+  const DeclSpec &DS = D.getDeclSpec();
+  switch (DS.getTypeSpecType()) {
+  case TST_typename:
+  case TST_typeofType:
+  case TST_underlyingType:
+  case TST_atomic: {
+    QualType T = DS.getRepAsType().get();
+    if (!T.isNull() && T->containsUnexpandedParameterPack())
+      return true;
+    break;
+  }
+      
+  case TST_typeofExpr:
+  case TST_decltype:
+    if (DS.getRepAsExpr() && 
+        DS.getRepAsExpr()->containsUnexpandedParameterPack())
+      return true;
+    break;
+      
+  case TST_unspecified:
+  case TST_void:
+  case TST_char:
+  case TST_wchar:
+  case TST_char16:
+  case TST_char32:
+  case TST_int:
+  case TST_int128:
+  case TST_half:
+  case TST_float:
+  case TST_double:
+  case TST_bool:
+  case TST_decimal32:
+  case TST_decimal64:
+  case TST_decimal128:
+  case TST_enum:
+  case TST_union:
+  case TST_struct:
+  case TST_class:
+  case TST_auto:
+  case TST_unknown_anytype:
+  case TST_error:
+    break;
+  }
+  
+  for (unsigned I = 0, N = D.getNumTypeObjects(); I != N; ++I) {
+    const DeclaratorChunk &Chunk = D.getTypeObject(I);
+    switch (Chunk.Kind) {
+    case DeclaratorChunk::Pointer:
+    case DeclaratorChunk::Reference:
+    case DeclaratorChunk::Paren:
+      // These declarator chunks cannot contain any parameter packs.
+      break;
+        
+    case DeclaratorChunk::Array:
+    case DeclaratorChunk::Function:
+    case DeclaratorChunk::BlockPointer:
+      // Syntactically, these kinds of declarator chunks all come after the
+      // declarator-id (conceptually), so the parser should not invoke this
+      // routine at this time.
+      llvm_unreachable("Could not have seen this kind of declarator chunk");
+        
+    case DeclaratorChunk::MemberPointer:
+      if (Chunk.Mem.Scope().getScopeRep() &&
+          Chunk.Mem.Scope().getScopeRep()->containsUnexpandedParameterPack())
+        return true;
+      break;
+    }
+  }
+  
+  return false;
+}
+
+namespace {
+
+// Callback to only accept typo corrections that refer to parameter packs.
+class ParameterPackValidatorCCC : public CorrectionCandidateCallback {
+ public:
+  virtual bool ValidateCandidate(const TypoCorrection &candidate) {
+    NamedDecl *ND = candidate.getCorrectionDecl();
+    return ND && ND->isParameterPack();
+  }
+};
+
+}
+
+/// \brief Called when an expression computing the size of a parameter pack
+/// is parsed.
+///
+/// \code
+/// template<typename ...Types> struct count {
+///   static const unsigned value = sizeof...(Types);
+/// };
+/// \endcode
+///
+//
+/// \param OpLoc The location of the "sizeof" keyword.
+/// \param Name The name of the parameter pack whose size will be determined.
+/// \param NameLoc The source location of the name of the parameter pack.
+/// \param RParenLoc The location of the closing parentheses.
+ExprResult Sema::ActOnSizeofParameterPackExpr(Scope *S,
+                                              SourceLocation OpLoc,
+                                              IdentifierInfo &Name,
+                                              SourceLocation NameLoc,
+                                              SourceLocation RParenLoc) {
+  // C++0x [expr.sizeof]p5:
+  //   The identifier in a sizeof... expression shall name a parameter pack.
+  LookupResult R(*this, &Name, NameLoc, LookupOrdinaryName);
+  LookupName(R, S);
+  
+  NamedDecl *ParameterPack = 0;
+  ParameterPackValidatorCCC Validator;
+  switch (R.getResultKind()) {
+  case LookupResult::Found:
+    ParameterPack = R.getFoundDecl();
+    break;
+    
+  case LookupResult::NotFound:
+  case LookupResult::NotFoundInCurrentInstantiation:
+    if (TypoCorrection Corrected = CorrectTypo(R.getLookupNameInfo(),
+                                               R.getLookupKind(), S, 0,
+                                               Validator)) {
+      std::string CorrectedQuotedStr(Corrected.getQuoted(getLangOpts()));
+      ParameterPack = Corrected.getCorrectionDecl();
+      Diag(NameLoc, diag::err_sizeof_pack_no_pack_name_suggest)
+        << &Name << CorrectedQuotedStr
+        << FixItHint::CreateReplacement(
+            NameLoc, Corrected.getAsString(getLangOpts()));
+      Diag(ParameterPack->getLocation(), diag::note_parameter_pack_here)
+        << CorrectedQuotedStr;
+    }
+      
+  case LookupResult::FoundOverloaded:
+  case LookupResult::FoundUnresolvedValue:
+    break;
+    
+  case LookupResult::Ambiguous:
+    DiagnoseAmbiguousLookup(R);
+    return ExprError();
+  }
+  
+  if (!ParameterPack || !ParameterPack->isParameterPack()) {
+    Diag(NameLoc, diag::err_sizeof_pack_no_pack_name)
+      << &Name;
+    return ExprError();
+  }
+
+  MarkAnyDeclReferenced(OpLoc, ParameterPack);
+
+  return new (Context) SizeOfPackExpr(Context.getSizeType(), OpLoc, 
+                                      ParameterPack, NameLoc, RParenLoc);
+}
diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp
new file mode 100644
index 0000000..1400e7e
--- /dev/null
+++ b/clang/lib/Sema/SemaType.cpp
@@ -0,0 +1,4514 @@
+//===--- SemaType.cpp - Semantic Analysis for Types -----------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+//  This file implements type-related semantic analysis.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Sema/ScopeInfo.h"
+#include "clang/Sema/SemaInternal.h"
+#include "clang/Sema/Template.h"
+#include "clang/Basic/OpenCL.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/ASTMutationListener.h"
+#include "clang/AST/CXXInheritance.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/AST/DeclTemplate.h"
+#include "clang/AST/TypeLoc.h"
+#include "clang/AST/TypeLocVisitor.h"
+#include "clang/AST/Expr.h"
+#include "clang/Basic/PartialDiagnostic.h"
+#include "clang/Basic/TargetInfo.h"
+#include "clang/Lex/Preprocessor.h"
+#include "clang/Parse/ParseDiagnostic.h"
+#include "clang/Sema/DeclSpec.h"
+#include "clang/Sema/DelayedDiagnostic.h"
+#include "clang/Sema/Lookup.h"
+#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/Support/ErrorHandling.h"
+using namespace clang;
+
+/// isOmittedBlockReturnType - Return true if this declarator is missing a
+/// return type because this is a omitted return type on a block literal. 
+static bool isOmittedBlockReturnType(const Declarator &D) {
+  if (D.getContext() != Declarator::BlockLiteralContext ||
+      D.getDeclSpec().hasTypeSpecifier())
+    return false;
+  
+  if (D.getNumTypeObjects() == 0)
+    return true;   // ^{ ... }
+  
+  if (D.getNumTypeObjects() == 1 &&
+      D.getTypeObject(0).Kind == DeclaratorChunk::Function)
+    return true;   // ^(int X, float Y) { ... }
+  
+  return false;
+}
+
+/// diagnoseBadTypeAttribute - Diagnoses a type attribute which
+/// doesn't apply to the given type.
+static void diagnoseBadTypeAttribute(Sema &S, const AttributeList &attr,
+                                     QualType type) {
+  bool useExpansionLoc = false;
+
+  unsigned diagID = 0;
+  switch (attr.getKind()) {
+  case AttributeList::AT_objc_gc:
+    diagID = diag::warn_pointer_attribute_wrong_type;
+    useExpansionLoc = true;
+    break;
+
+  case AttributeList::AT_objc_ownership:
+    diagID = diag::warn_objc_object_attribute_wrong_type;
+    useExpansionLoc = true;
+    break;
+
+  default:
+    // Assume everything else was a function attribute.
+    diagID = diag::warn_function_attribute_wrong_type;
+    break;
+  }
+
+  SourceLocation loc = attr.getLoc();
+  StringRef name = attr.getName()->getName();
+
+  // The GC attributes are usually written with macros;  special-case them.
+  if (useExpansionLoc && loc.isMacroID() && attr.getParameterName()) {
+    if (attr.getParameterName()->isStr("strong")) {
+      if (S.findMacroSpelling(loc, "__strong")) name = "__strong";
+    } else if (attr.getParameterName()->isStr("weak")) {
+      if (S.findMacroSpelling(loc, "__weak")) name = "__weak";
+    }
+  }
+
+  S.Diag(loc, diagID) << name << type;
+}
+
+// objc_gc applies to Objective-C pointers or, otherwise, to the
+// smallest available pointer type (i.e. 'void*' in 'void**').
+#define OBJC_POINTER_TYPE_ATTRS_CASELIST \
+    case AttributeList::AT_objc_gc: \
+    case AttributeList::AT_objc_ownership
+
+// Function type attributes.
+#define FUNCTION_TYPE_ATTRS_CASELIST \
+    case AttributeList::AT_noreturn: \
+    case AttributeList::AT_cdecl: \
+    case AttributeList::AT_fastcall: \
+    case AttributeList::AT_stdcall: \
+    case AttributeList::AT_thiscall: \
+    case AttributeList::AT_pascal: \
+    case AttributeList::AT_regparm: \
+    case AttributeList::AT_pcs \
+
+namespace {
+  /// An object which stores processing state for the entire
+  /// GetTypeForDeclarator process.
+  class TypeProcessingState {
+    Sema &sema;
+
+    /// The declarator being processed.
+    Declarator &declarator;
+
+    /// The index of the declarator chunk we're currently processing.
+    /// May be the total number of valid chunks, indicating the
+    /// DeclSpec.
+    unsigned chunkIndex;
+
+    /// Whether there are non-trivial modifications to the decl spec.
+    bool trivial;
+
+    /// Whether we saved the attributes in the decl spec.
+    bool hasSavedAttrs;
+
+    /// The original set of attributes on the DeclSpec.
+    SmallVector<AttributeList*, 2> savedAttrs;
+
+    /// A list of attributes to diagnose the uselessness of when the
+    /// processing is complete.
+    SmallVector<AttributeList*, 2> ignoredTypeAttrs;
+
+  public:
+    TypeProcessingState(Sema &sema, Declarator &declarator)
+      : sema(sema), declarator(declarator),
+        chunkIndex(declarator.getNumTypeObjects()),
+        trivial(true), hasSavedAttrs(false) {}
+
+    Sema &getSema() const {
+      return sema;
+    }
+
+    Declarator &getDeclarator() const {
+      return declarator;
+    }
+
+    unsigned getCurrentChunkIndex() const {
+      return chunkIndex;
+    }
+
+    void setCurrentChunkIndex(unsigned idx) {
+      assert(idx <= declarator.getNumTypeObjects());
+      chunkIndex = idx;
+    }
+
+    AttributeList *&getCurrentAttrListRef() const {
+      assert(chunkIndex <= declarator.getNumTypeObjects());
+      if (chunkIndex == declarator.getNumTypeObjects())
+        return getMutableDeclSpec().getAttributes().getListRef();
+      return declarator.getTypeObject(chunkIndex).getAttrListRef();
+    }
+
+    /// Save the current set of attributes on the DeclSpec.
+    void saveDeclSpecAttrs() {
+      // Don't try to save them multiple times.
+      if (hasSavedAttrs) return;
+
+      DeclSpec &spec = getMutableDeclSpec();
+      for (AttributeList *attr = spec.getAttributes().getList(); attr;
+             attr = attr->getNext())
+        savedAttrs.push_back(attr);
+      trivial &= savedAttrs.empty();
+      hasSavedAttrs = true;
+    }
+
+    /// Record that we had nowhere to put the given type attribute.
+    /// We will diagnose such attributes later.
+    void addIgnoredTypeAttr(AttributeList &attr) {
+      ignoredTypeAttrs.push_back(&attr);
+    }
+
+    /// Diagnose all the ignored type attributes, given that the
+    /// declarator worked out to the given type.
+    void diagnoseIgnoredTypeAttrs(QualType type) const {
+      for (SmallVectorImpl<AttributeList*>::const_iterator
+             i = ignoredTypeAttrs.begin(), e = ignoredTypeAttrs.end();
+           i != e; ++i)
+        diagnoseBadTypeAttribute(getSema(), **i, type);
+    }
+
+    ~TypeProcessingState() {
+      if (trivial) return;
+
+      restoreDeclSpecAttrs();
+    }
+
+  private:
+    DeclSpec &getMutableDeclSpec() const {
+      return const_cast<DeclSpec&>(declarator.getDeclSpec());
+    }
+
+    void restoreDeclSpecAttrs() {
+      assert(hasSavedAttrs);
+
+      if (savedAttrs.empty()) {
+        getMutableDeclSpec().getAttributes().set(0);
+        return;
+      }
+
+      getMutableDeclSpec().getAttributes().set(savedAttrs[0]);
+      for (unsigned i = 0, e = savedAttrs.size() - 1; i != e; ++i)
+        savedAttrs[i]->setNext(savedAttrs[i+1]);
+      savedAttrs.back()->setNext(0);
+    }
+  };
+
+  /// Basically std::pair except that we really want to avoid an
+  /// implicit operator= for safety concerns.  It's also a minor
+  /// link-time optimization for this to be a private type.
+  struct AttrAndList {
+    /// The attribute.
+    AttributeList &first;
+
+    /// The head of the list the attribute is currently in.
+    AttributeList *&second;
+
+    AttrAndList(AttributeList &attr, AttributeList *&head)
+      : first(attr), second(head) {}
+  };
+}
+
+namespace llvm {
+  template <> struct isPodLike<AttrAndList> {
+    static const bool value = true;
+  };
+}
+
+static void spliceAttrIntoList(AttributeList &attr, AttributeList *&head) {
+  attr.setNext(head);
+  head = &attr;
+}
+
+static void spliceAttrOutOfList(AttributeList &attr, AttributeList *&head) {
+  if (head == &attr) {
+    head = attr.getNext();
+    return;
+  }
+
+  AttributeList *cur = head;
+  while (true) {
+    assert(cur && cur->getNext() && "ran out of attrs?");
+    if (cur->getNext() == &attr) {
+      cur->setNext(attr.getNext());
+      return;
+    }
+    cur = cur->getNext();
+  }
+}
+
+static void moveAttrFromListToList(AttributeList &attr,
+                                   AttributeList *&fromList,
+                                   AttributeList *&toList) {
+  spliceAttrOutOfList(attr, fromList);
+  spliceAttrIntoList(attr, toList);
+}
+
+static void processTypeAttrs(TypeProcessingState &state,
+                             QualType &type, bool isDeclSpec,
+                             AttributeList *attrs);
+
+static bool handleFunctionTypeAttr(TypeProcessingState &state,
+                                   AttributeList &attr,
+                                   QualType &type);
+
+static bool handleObjCGCTypeAttr(TypeProcessingState &state,
+                                 AttributeList &attr, QualType &type);
+
+static bool handleObjCOwnershipTypeAttr(TypeProcessingState &state,
+                                       AttributeList &attr, QualType &type);
+
+static bool handleObjCPointerTypeAttr(TypeProcessingState &state,
+                                      AttributeList &attr, QualType &type) {
+  if (attr.getKind() == AttributeList::AT_objc_gc)
+    return handleObjCGCTypeAttr(state, attr, type);
+  assert(attr.getKind() == AttributeList::AT_objc_ownership);
+  return handleObjCOwnershipTypeAttr(state, attr, type);
+}
+
+/// Given that an objc_gc attribute was written somewhere on a
+/// declaration *other* than on the declarator itself (for which, use
+/// distributeObjCPointerTypeAttrFromDeclarator), and given that it
+/// didn't apply in whatever position it was written in, try to move
+/// it to a more appropriate position.
+static void distributeObjCPointerTypeAttr(TypeProcessingState &state,
+                                          AttributeList &attr,
+                                          QualType type) {
+  Declarator &declarator = state.getDeclarator();
+  for (unsigned i = state.getCurrentChunkIndex(); i != 0; --i) {
+    DeclaratorChunk &chunk = declarator.getTypeObject(i-1);
+    switch (chunk.Kind) {
+    case DeclaratorChunk::Pointer:
+    case DeclaratorChunk::BlockPointer:
+      moveAttrFromListToList(attr, state.getCurrentAttrListRef(),
+                             chunk.getAttrListRef());
+      return;
+
+    case DeclaratorChunk::Paren:
+    case DeclaratorChunk::Array:
+      continue;
+
+    // Don't walk through these.
+    case DeclaratorChunk::Reference:
+    case DeclaratorChunk::Function:
+    case DeclaratorChunk::MemberPointer:
+      goto error;
+    }
+  }
+ error:
+
+  diagnoseBadTypeAttribute(state.getSema(), attr, type);
+}
+
+/// Distribute an objc_gc type attribute that was written on the
+/// declarator.
+static void
+distributeObjCPointerTypeAttrFromDeclarator(TypeProcessingState &state,
+                                            AttributeList &attr,
+                                            QualType &declSpecType) {
+  Declarator &declarator = state.getDeclarator();
+
+  // objc_gc goes on the innermost pointer to something that's not a
+  // pointer.
+  unsigned innermost = -1U;
+  bool considerDeclSpec = true;
+  for (unsigned i = 0, e = declarator.getNumTypeObjects(); i != e; ++i) {
+    DeclaratorChunk &chunk = declarator.getTypeObject(i);
+    switch (chunk.Kind) {
+    case DeclaratorChunk::Pointer:
+    case DeclaratorChunk::BlockPointer:
+      innermost = i;
+      continue;
+
+    case DeclaratorChunk::Reference:
+    case DeclaratorChunk::MemberPointer:
+    case DeclaratorChunk::Paren:
+    case DeclaratorChunk::Array:
+      continue;
+
+    case DeclaratorChunk::Function:
+      considerDeclSpec = false;
+      goto done;
+    }
+  }
+ done:
+
+  // That might actually be the decl spec if we weren't blocked by
+  // anything in the declarator.
+  if (considerDeclSpec) {
+    if (handleObjCPointerTypeAttr(state, attr, declSpecType)) {
+      // Splice the attribute into the decl spec.  Prevents the
+      // attribute from being applied multiple times and gives
+      // the source-location-filler something to work with.
+      state.saveDeclSpecAttrs();
+      moveAttrFromListToList(attr, declarator.getAttrListRef(),
+               declarator.getMutableDeclSpec().getAttributes().getListRef());
+      return;
+    }
+  }
+
+  // Otherwise, if we found an appropriate chunk, splice the attribute
+  // into it.
+  if (innermost != -1U) {
+    moveAttrFromListToList(attr, declarator.getAttrListRef(),
+                       declarator.getTypeObject(innermost).getAttrListRef());
+    return;
+  }
+
+  // Otherwise, diagnose when we're done building the type.
+  spliceAttrOutOfList(attr, declarator.getAttrListRef());
+  state.addIgnoredTypeAttr(attr);
+}
+
+/// A function type attribute was written somewhere in a declaration
+/// *other* than on the declarator itself or in the decl spec.  Given
+/// that it didn't apply in whatever position it was written in, try
+/// to move it to a more appropriate position.
+static void distributeFunctionTypeAttr(TypeProcessingState &state,
+                                       AttributeList &attr,
+                                       QualType type) {
+  Declarator &declarator = state.getDeclarator();
+
+  // Try to push the attribute from the return type of a function to
+  // the function itself.
+  for (unsigned i = state.getCurrentChunkIndex(); i != 0; --i) {
+    DeclaratorChunk &chunk = declarator.getTypeObject(i-1);
+    switch (chunk.Kind) {
+    case DeclaratorChunk::Function:
+      moveAttrFromListToList(attr, state.getCurrentAttrListRef(),
+                             chunk.getAttrListRef());
+      return;
+
+    case DeclaratorChunk::Paren:
+    case DeclaratorChunk::Pointer:
+    case DeclaratorChunk::BlockPointer:
+    case DeclaratorChunk::Array:
+    case DeclaratorChunk::Reference:
+    case DeclaratorChunk::MemberPointer:
+      continue;
+    }
+  }
+  
+  diagnoseBadTypeAttribute(state.getSema(), attr, type);
+}
+
+/// Try to distribute a function type attribute to the innermost
+/// function chunk or type.  Returns true if the attribute was
+/// distributed, false if no location was found.
+static bool
+distributeFunctionTypeAttrToInnermost(TypeProcessingState &state,
+                                      AttributeList &attr,
+                                      AttributeList *&attrList,
+                                      QualType &declSpecType) {
+  Declarator &declarator = state.getDeclarator();
+
+  // Put it on the innermost function chunk, if there is one.
+  for (unsigned i = 0, e = declarator.getNumTypeObjects(); i != e; ++i) {
+    DeclaratorChunk &chunk = declarator.getTypeObject(i);
+    if (chunk.Kind != DeclaratorChunk::Function) continue;
+
+    moveAttrFromListToList(attr, attrList, chunk.getAttrListRef());
+    return true;
+  }
+
+  if (handleFunctionTypeAttr(state, attr, declSpecType)) {
+    spliceAttrOutOfList(attr, attrList);
+    return true;
+  }
+
+  return false;
+}
+
+/// A function type attribute was written in the decl spec.  Try to
+/// apply it somewhere.
+static void
+distributeFunctionTypeAttrFromDeclSpec(TypeProcessingState &state,
+                                       AttributeList &attr,
+                                       QualType &declSpecType) {
+  state.saveDeclSpecAttrs();
+
+  // Try to distribute to the innermost.
+  if (distributeFunctionTypeAttrToInnermost(state, attr,
+                                            state.getCurrentAttrListRef(),
+                                            declSpecType))
+    return;
+
+  // If that failed, diagnose the bad attribute when the declarator is
+  // fully built.
+  state.addIgnoredTypeAttr(attr);
+}
+
+/// A function type attribute was written on the declarator.  Try to
+/// apply it somewhere.
+static void
+distributeFunctionTypeAttrFromDeclarator(TypeProcessingState &state,
+                                         AttributeList &attr,
+                                         QualType &declSpecType) {
+  Declarator &declarator = state.getDeclarator();
+
+  // Try to distribute to the innermost.
+  if (distributeFunctionTypeAttrToInnermost(state, attr,
+                                            declarator.getAttrListRef(),
+                                            declSpecType))
+    return;
+
+  // If that failed, diagnose the bad attribute when the declarator is
+  // fully built.
+  spliceAttrOutOfList(attr, declarator.getAttrListRef());
+  state.addIgnoredTypeAttr(attr);
+}
+
+/// \brief Given that there are attributes written on the declarator
+/// itself, try to distribute any type attributes to the appropriate
+/// declarator chunk.
+///
+/// These are attributes like the following:
+///   int f ATTR;
+///   int (f ATTR)();
+/// but not necessarily this:
+///   int f() ATTR;
+static void distributeTypeAttrsFromDeclarator(TypeProcessingState &state,
+                                              QualType &declSpecType) {
+  // Collect all the type attributes from the declarator itself.
+  assert(state.getDeclarator().getAttributes() && "declarator has no attrs!");
+  AttributeList *attr = state.getDeclarator().getAttributes();
+  AttributeList *next;
+  do {
+    next = attr->getNext();
+
+    switch (attr->getKind()) {
+    OBJC_POINTER_TYPE_ATTRS_CASELIST:
+      distributeObjCPointerTypeAttrFromDeclarator(state, *attr, declSpecType);
+      break;
+
+    case AttributeList::AT_ns_returns_retained:
+      if (!state.getSema().getLangOpts().ObjCAutoRefCount)
+        break;
+      // fallthrough
+
+    FUNCTION_TYPE_ATTRS_CASELIST:
+      distributeFunctionTypeAttrFromDeclarator(state, *attr, declSpecType);
+      break;
+
+    default:
+      break;
+    }
+  } while ((attr = next));
+}
+
+/// Add a synthetic '()' to a block-literal declarator if it is
+/// required, given the return type.
+static void maybeSynthesizeBlockSignature(TypeProcessingState &state,
+                                          QualType declSpecType) {
+  Declarator &declarator = state.getDeclarator();
+
+  // First, check whether the declarator would produce a function,
+  // i.e. whether the innermost semantic chunk is a function.
+  if (declarator.isFunctionDeclarator()) {
+    // If so, make that declarator a prototyped declarator.
+    declarator.getFunctionTypeInfo().hasPrototype = true;
+    return;
+  }
+
+  // If there are any type objects, the type as written won't name a
+  // function, regardless of the decl spec type.  This is because a
+  // block signature declarator is always an abstract-declarator, and
+  // abstract-declarators can't just be parentheses chunks.  Therefore
+  // we need to build a function chunk unless there are no type
+  // objects and the decl spec type is a function.
+  if (!declarator.getNumTypeObjects() && declSpecType->isFunctionType())
+    return;
+
+  // Note that there *are* cases with invalid declarators where
+  // declarators consist solely of parentheses.  In general, these
+  // occur only in failed efforts to make function declarators, so
+  // faking up the function chunk is still the right thing to do.
+
+  // Otherwise, we need to fake up a function declarator.
+  SourceLocation loc = declarator.getLocStart();
+
+  // ...and *prepend* it to the declarator.
+  declarator.AddInnermostTypeInfo(DeclaratorChunk::getFunction(
+                             /*proto*/ true,
+                             /*variadic*/ false, SourceLocation(),
+                             /*args*/ 0, 0,
+                             /*type quals*/ 0,
+                             /*ref-qualifier*/true, SourceLocation(),
+                             /*const qualifier*/SourceLocation(),
+                             /*volatile qualifier*/SourceLocation(),
+                             /*mutable qualifier*/SourceLocation(),
+                             /*EH*/ EST_None, SourceLocation(), 0, 0, 0, 0,
+                             /*parens*/ loc, loc,
+                             declarator));
+
+  // For consistency, make sure the state still has us as processing
+  // the decl spec.
+  assert(state.getCurrentChunkIndex() == declarator.getNumTypeObjects() - 1);
+  state.setCurrentChunkIndex(declarator.getNumTypeObjects());
+}
+
+/// \brief Convert the specified declspec to the appropriate type
+/// object.
+/// \param D  the declarator containing the declaration specifier.
+/// \returns The type described by the declaration specifiers.  This function
+/// never returns null.
+static QualType ConvertDeclSpecToType(TypeProcessingState &state) {
+  // FIXME: Should move the logic from DeclSpec::Finish to here for validity
+  // checking.
+
+  Sema &S = state.getSema();
+  Declarator &declarator = state.getDeclarator();
+  const DeclSpec &DS = declarator.getDeclSpec();
+  SourceLocation DeclLoc = declarator.getIdentifierLoc();
+  if (DeclLoc.isInvalid())
+    DeclLoc = DS.getLocStart();
+  
+  ASTContext &Context = S.Context;
+
+  QualType Result;
+  switch (DS.getTypeSpecType()) {
+  case DeclSpec::TST_void:
+    Result = Context.VoidTy;
+    break;
+  case DeclSpec::TST_char:
+    if (DS.getTypeSpecSign() == DeclSpec::TSS_unspecified)
+      Result = Context.CharTy;
+    else if (DS.getTypeSpecSign() == DeclSpec::TSS_signed)
+      Result = Context.SignedCharTy;
+    else {
+      assert(DS.getTypeSpecSign() == DeclSpec::TSS_unsigned &&
+             "Unknown TSS value");
+      Result = Context.UnsignedCharTy;
+    }
+    break;
+  case DeclSpec::TST_wchar:
+    if (DS.getTypeSpecSign() == DeclSpec::TSS_unspecified)
+      Result = Context.WCharTy;
+    else if (DS.getTypeSpecSign() == DeclSpec::TSS_signed) {
+      S.Diag(DS.getTypeSpecSignLoc(), diag::ext_invalid_sign_spec)
+        << DS.getSpecifierName(DS.getTypeSpecType());
+      Result = Context.getSignedWCharType();
+    } else {
+      assert(DS.getTypeSpecSign() == DeclSpec::TSS_unsigned &&
+        "Unknown TSS value");
+      S.Diag(DS.getTypeSpecSignLoc(), diag::ext_invalid_sign_spec)
+        << DS.getSpecifierName(DS.getTypeSpecType());
+      Result = Context.getUnsignedWCharType();
+    }
+    break;
+  case DeclSpec::TST_char16:
+      assert(DS.getTypeSpecSign() == DeclSpec::TSS_unspecified &&
+        "Unknown TSS value");
+      Result = Context.Char16Ty;
+    break;
+  case DeclSpec::TST_char32:
+      assert(DS.getTypeSpecSign() == DeclSpec::TSS_unspecified &&
+        "Unknown TSS value");
+      Result = Context.Char32Ty;
+    break;
+  case DeclSpec::TST_unspecified:
+    // "<proto1,proto2>" is an objc qualified ID with a missing id.
+    if (DeclSpec::ProtocolQualifierListTy PQ = DS.getProtocolQualifiers()) {
+      Result = Context.getObjCObjectType(Context.ObjCBuiltinIdTy,
+                                         (ObjCProtocolDecl**)PQ,
+                                         DS.getNumProtocolQualifiers());
+      Result = Context.getObjCObjectPointerType(Result);
+      break;
+    }
+    
+    // If this is a missing declspec in a block literal return context, then it
+    // is inferred from the return statements inside the block.
+    // The declspec is always missing in a lambda expr context; it is either
+    // specified with a trailing return type or inferred.
+    if (declarator.getContext() == Declarator::LambdaExprContext ||
+        isOmittedBlockReturnType(declarator)) {
+      Result = Context.DependentTy;
+      break;
+    }
+
+    // Unspecified typespec defaults to int in C90.  However, the C90 grammar
+    // [C90 6.5] only allows a decl-spec if there was *some* type-specifier,
+    // type-qualifier, or storage-class-specifier.  If not, emit an extwarn.
+    // Note that the one exception to this is function definitions, which are
+    // allowed to be completely missing a declspec.  This is handled in the
+    // parser already though by it pretending to have seen an 'int' in this
+    // case.
+    if (S.getLangOpts().ImplicitInt) {
+      // In C89 mode, we only warn if there is a completely missing declspec
+      // when one is not allowed.
+      if (DS.isEmpty()) {
+        S.Diag(DeclLoc, diag::ext_missing_declspec)
+          << DS.getSourceRange()
+        << FixItHint::CreateInsertion(DS.getLocStart(), "int");
+      }
+    } else if (!DS.hasTypeSpecifier()) {
+      // C99 and C++ require a type specifier.  For example, C99 6.7.2p2 says:
+      // "At least one type specifier shall be given in the declaration
+      // specifiers in each declaration, and in the specifier-qualifier list in
+      // each struct declaration and type name."
+      // FIXME: Does Microsoft really have the implicit int extension in C++?
+      if (S.getLangOpts().CPlusPlus &&
+          !S.getLangOpts().MicrosoftExt) {
+        S.Diag(DeclLoc, diag::err_missing_type_specifier)
+          << DS.getSourceRange();
+
+        // When this occurs in C++ code, often something is very broken with the
+        // value being declared, poison it as invalid so we don't get chains of
+        // errors.
+        declarator.setInvalidType(true);
+      } else {
+        S.Diag(DeclLoc, diag::ext_missing_type_specifier)
+          << DS.getSourceRange();
+      }
+    }
+
+    // FALL THROUGH.
+  case DeclSpec::TST_int: {
+    if (DS.getTypeSpecSign() != DeclSpec::TSS_unsigned) {
+      switch (DS.getTypeSpecWidth()) {
+      case DeclSpec::TSW_unspecified: Result = Context.IntTy; break;
+      case DeclSpec::TSW_short:       Result = Context.ShortTy; break;
+      case DeclSpec::TSW_long:        Result = Context.LongTy; break;
+      case DeclSpec::TSW_longlong:
+        Result = Context.LongLongTy;
+          
+        // long long is a C99 feature.
+        if (!S.getLangOpts().C99)
+          S.Diag(DS.getTypeSpecWidthLoc(),
+                 S.getLangOpts().CPlusPlus0x ?
+                   diag::warn_cxx98_compat_longlong : diag::ext_longlong);
+        break;
+      }
+    } else {
+      switch (DS.getTypeSpecWidth()) {
+      case DeclSpec::TSW_unspecified: Result = Context.UnsignedIntTy; break;
+      case DeclSpec::TSW_short:       Result = Context.UnsignedShortTy; break;
+      case DeclSpec::TSW_long:        Result = Context.UnsignedLongTy; break;
+      case DeclSpec::TSW_longlong:
+        Result = Context.UnsignedLongLongTy;
+          
+        // long long is a C99 feature.
+        if (!S.getLangOpts().C99)
+          S.Diag(DS.getTypeSpecWidthLoc(),
+                 S.getLangOpts().CPlusPlus0x ?
+                   diag::warn_cxx98_compat_longlong : diag::ext_longlong);
+        break;
+      }
+    }
+    break;
+  }
+  case DeclSpec::TST_int128:
+    if (DS.getTypeSpecSign() == DeclSpec::TSS_unsigned)
+      Result = Context.UnsignedInt128Ty;
+    else
+      Result = Context.Int128Ty;
+    break;
+  case DeclSpec::TST_half: Result = Context.HalfTy; break;
+  case DeclSpec::TST_float: Result = Context.FloatTy; break;
+  case DeclSpec::TST_double:
+    if (DS.getTypeSpecWidth() == DeclSpec::TSW_long)
+      Result = Context.LongDoubleTy;
+    else
+      Result = Context.DoubleTy;
+
+    if (S.getLangOpts().OpenCL && !S.getOpenCLOptions().cl_khr_fp64) {
+      S.Diag(DS.getTypeSpecTypeLoc(), diag::err_double_requires_fp64);
+      declarator.setInvalidType(true);
+    }
+    break;
+  case DeclSpec::TST_bool: Result = Context.BoolTy; break; // _Bool or bool
+  case DeclSpec::TST_decimal32:    // _Decimal32
+  case DeclSpec::TST_decimal64:    // _Decimal64
+  case DeclSpec::TST_decimal128:   // _Decimal128
+    S.Diag(DS.getTypeSpecTypeLoc(), diag::err_decimal_unsupported);
+    Result = Context.IntTy;
+    declarator.setInvalidType(true);
+    break;
+  case DeclSpec::TST_class:
+  case DeclSpec::TST_enum:
+  case DeclSpec::TST_union:
+  case DeclSpec::TST_struct: {
+    TypeDecl *D = dyn_cast_or_null<TypeDecl>(DS.getRepAsDecl());
+    if (!D) {
+      // This can happen in C++ with ambiguous lookups.
+      Result = Context.IntTy;
+      declarator.setInvalidType(true);
+      break;
+    }
+
+    // If the type is deprecated or unavailable, diagnose it.
+    S.DiagnoseUseOfDecl(D, DS.getTypeSpecTypeNameLoc());
+    
+    assert(DS.getTypeSpecWidth() == 0 && DS.getTypeSpecComplex() == 0 &&
+           DS.getTypeSpecSign() == 0 && "No qualifiers on tag names!");
+    
+    // TypeQuals handled by caller.
+    Result = Context.getTypeDeclType(D);
+
+    // In both C and C++, make an ElaboratedType.
+    ElaboratedTypeKeyword Keyword
+      = ElaboratedType::getKeywordForTypeSpec(DS.getTypeSpecType());
+    Result = S.getElaboratedType(Keyword, DS.getTypeSpecScope(), Result);
+    break;
+  }
+  case DeclSpec::TST_typename: {
+    assert(DS.getTypeSpecWidth() == 0 && DS.getTypeSpecComplex() == 0 &&
+           DS.getTypeSpecSign() == 0 &&
+           "Can't handle qualifiers on typedef names yet!");
+    Result = S.GetTypeFromParser(DS.getRepAsType());
+    if (Result.isNull())
+      declarator.setInvalidType(true);
+    else if (DeclSpec::ProtocolQualifierListTy PQ
+               = DS.getProtocolQualifiers()) {
+      if (const ObjCObjectType *ObjT = Result->getAs<ObjCObjectType>()) {
+        // Silently drop any existing protocol qualifiers.
+        // TODO: determine whether that's the right thing to do.
+        if (ObjT->getNumProtocols())
+          Result = ObjT->getBaseType();
+
+        if (DS.getNumProtocolQualifiers())
+          Result = Context.getObjCObjectType(Result,
+                                             (ObjCProtocolDecl**) PQ,
+                                             DS.getNumProtocolQualifiers());
+      } else if (Result->isObjCIdType()) {
+        // id<protocol-list>
+        Result = Context.getObjCObjectType(Context.ObjCBuiltinIdTy,
+                                           (ObjCProtocolDecl**) PQ,
+                                           DS.getNumProtocolQualifiers());
+        Result = Context.getObjCObjectPointerType(Result);
+      } else if (Result->isObjCClassType()) {
+        // Class<protocol-list>
+        Result = Context.getObjCObjectType(Context.ObjCBuiltinClassTy,
+                                           (ObjCProtocolDecl**) PQ,
+                                           DS.getNumProtocolQualifiers());
+        Result = Context.getObjCObjectPointerType(Result);
+      } else {
+        S.Diag(DeclLoc, diag::err_invalid_protocol_qualifiers)
+          << DS.getSourceRange();
+        declarator.setInvalidType(true);
+      }
+    }
+
+    // TypeQuals handled by caller.
+    break;
+  }
+  case DeclSpec::TST_typeofType:
+    // FIXME: Preserve type source info.
+    Result = S.GetTypeFromParser(DS.getRepAsType());
+    assert(!Result.isNull() && "Didn't get a type for typeof?");
+    if (!Result->isDependentType())
+      if (const TagType *TT = Result->getAs<TagType>())
+        S.DiagnoseUseOfDecl(TT->getDecl(), DS.getTypeSpecTypeLoc());
+    // TypeQuals handled by caller.
+    Result = Context.getTypeOfType(Result);
+    break;
+  case DeclSpec::TST_typeofExpr: {
+    Expr *E = DS.getRepAsExpr();
+    assert(E && "Didn't get an expression for typeof?");
+    // TypeQuals handled by caller.
+    Result = S.BuildTypeofExprType(E, DS.getTypeSpecTypeLoc());
+    if (Result.isNull()) {
+      Result = Context.IntTy;
+      declarator.setInvalidType(true);
+    }
+    break;
+  }
+  case DeclSpec::TST_decltype: {
+    Expr *E = DS.getRepAsExpr();
+    assert(E && "Didn't get an expression for decltype?");
+    // TypeQuals handled by caller.
+    Result = S.BuildDecltypeType(E, DS.getTypeSpecTypeLoc());
+    if (Result.isNull()) {
+      Result = Context.IntTy;
+      declarator.setInvalidType(true);
+    }
+    break;
+  }
+  case DeclSpec::TST_underlyingType:
+    Result = S.GetTypeFromParser(DS.getRepAsType());
+    assert(!Result.isNull() && "Didn't get a type for __underlying_type?");
+    Result = S.BuildUnaryTransformType(Result,
+                                       UnaryTransformType::EnumUnderlyingType,
+                                       DS.getTypeSpecTypeLoc());
+    if (Result.isNull()) {
+      Result = Context.IntTy;
+      declarator.setInvalidType(true);
+    }
+    break; 
+
+  case DeclSpec::TST_auto: {
+    // TypeQuals handled by caller.
+    Result = Context.getAutoType(QualType());
+    break;
+  }
+
+  case DeclSpec::TST_unknown_anytype:
+    Result = Context.UnknownAnyTy;
+    break;
+
+  case DeclSpec::TST_atomic:
+    Result = S.GetTypeFromParser(DS.getRepAsType());
+    assert(!Result.isNull() && "Didn't get a type for _Atomic?");
+    Result = S.BuildAtomicType(Result, DS.getTypeSpecTypeLoc());
+    if (Result.isNull()) {
+      Result = Context.IntTy;
+      declarator.setInvalidType(true);
+    }
+    break; 
+
+  case DeclSpec::TST_error:
+    Result = Context.IntTy;
+    declarator.setInvalidType(true);
+    break;
+  }
+
+  // Handle complex types.
+  if (DS.getTypeSpecComplex() == DeclSpec::TSC_complex) {
+    if (S.getLangOpts().Freestanding)
+      S.Diag(DS.getTypeSpecComplexLoc(), diag::ext_freestanding_complex);
+    Result = Context.getComplexType(Result);
+  } else if (DS.isTypeAltiVecVector()) {
+    unsigned typeSize = static_cast<unsigned>(Context.getTypeSize(Result));
+    assert(typeSize > 0 && "type size for vector must be greater than 0 bits");
+    VectorType::VectorKind VecKind = VectorType::AltiVecVector;
+    if (DS.isTypeAltiVecPixel())
+      VecKind = VectorType::AltiVecPixel;
+    else if (DS.isTypeAltiVecBool())
+      VecKind = VectorType::AltiVecBool;
+    Result = Context.getVectorType(Result, 128/typeSize, VecKind);
+  }
+
+  // FIXME: Imaginary.
+  if (DS.getTypeSpecComplex() == DeclSpec::TSC_imaginary)
+    S.Diag(DS.getTypeSpecComplexLoc(), diag::err_imaginary_not_supported);
+
+  // Before we process any type attributes, synthesize a block literal
+  // function declarator if necessary.
+  if (declarator.getContext() == Declarator::BlockLiteralContext)
+    maybeSynthesizeBlockSignature(state, Result);
+
+  // Apply any type attributes from the decl spec.  This may cause the
+  // list of type attributes to be temporarily saved while the type
+  // attributes are pushed around.
+  if (AttributeList *attrs = DS.getAttributes().getList())
+    processTypeAttrs(state, Result, true, attrs);
+
+  // Apply const/volatile/restrict qualifiers to T.
+  if (unsigned TypeQuals = DS.getTypeQualifiers()) {
+
+    // Enforce C99 6.7.3p2: "Types other than pointer types derived from object
+    // or incomplete types shall not be restrict-qualified."  C++ also allows
+    // restrict-qualified references.
+    if (TypeQuals & DeclSpec::TQ_restrict) {
+      if (Result->isAnyPointerType() || Result->isReferenceType()) {
+        QualType EltTy;
+        if (Result->isObjCObjectPointerType())
+          EltTy = Result;
+        else
+          EltTy = Result->isPointerType() ?
+                    Result->getAs<PointerType>()->getPointeeType() :
+                    Result->getAs<ReferenceType>()->getPointeeType();
+
+        // If we have a pointer or reference, the pointee must have an object
+        // incomplete type.
+        if (!EltTy->isIncompleteOrObjectType()) {
+          S.Diag(DS.getRestrictSpecLoc(),
+               diag::err_typecheck_invalid_restrict_invalid_pointee)
+            << EltTy << DS.getSourceRange();
+          TypeQuals &= ~DeclSpec::TQ_restrict; // Remove the restrict qualifier.
+        }
+      } else {
+        S.Diag(DS.getRestrictSpecLoc(),
+               diag::err_typecheck_invalid_restrict_not_pointer)
+          << Result << DS.getSourceRange();
+        TypeQuals &= ~DeclSpec::TQ_restrict; // Remove the restrict qualifier.
+      }
+    }
+
+    // Warn about CV qualifiers on functions: C99 6.7.3p8: "If the specification
+    // of a function type includes any type qualifiers, the behavior is
+    // undefined."
+    if (Result->isFunctionType() && TypeQuals) {
+      // Get some location to point at, either the C or V location.
+      SourceLocation Loc;
+      if (TypeQuals & DeclSpec::TQ_const)
+        Loc = DS.getConstSpecLoc();
+      else if (TypeQuals & DeclSpec::TQ_volatile)
+        Loc = DS.getVolatileSpecLoc();
+      else {
+        assert((TypeQuals & DeclSpec::TQ_restrict) &&
+               "Has CVR quals but not C, V, or R?");
+        Loc = DS.getRestrictSpecLoc();
+      }
+      S.Diag(Loc, diag::warn_typecheck_function_qualifiers)
+        << Result << DS.getSourceRange();
+    }
+
+    // C++ [dcl.ref]p1:
+    //   Cv-qualified references are ill-formed except when the
+    //   cv-qualifiers are introduced through the use of a typedef
+    //   (7.1.3) or of a template type argument (14.3), in which
+    //   case the cv-qualifiers are ignored.
+    // FIXME: Shouldn't we be checking SCS_typedef here?
+    if (DS.getTypeSpecType() == DeclSpec::TST_typename &&
+        TypeQuals && Result->isReferenceType()) {
+      TypeQuals &= ~DeclSpec::TQ_const;
+      TypeQuals &= ~DeclSpec::TQ_volatile;
+    }
+
+    // C90 6.5.3 constraints: "The same type qualifier shall not appear more
+    // than once in the same specifier-list or qualifier-list, either directly
+    // or via one or more typedefs."
+    if (!S.getLangOpts().C99 && !S.getLangOpts().CPlusPlus 
+        && TypeQuals & Result.getCVRQualifiers()) {
+      if (TypeQuals & DeclSpec::TQ_const && Result.isConstQualified()) {
+        S.Diag(DS.getConstSpecLoc(), diag::ext_duplicate_declspec) 
+          << "const";
+      }
+
+      if (TypeQuals & DeclSpec::TQ_volatile && Result.isVolatileQualified()) {
+        S.Diag(DS.getVolatileSpecLoc(), diag::ext_duplicate_declspec) 
+          << "volatile";
+      }
+
+      // C90 doesn't have restrict, so it doesn't force us to produce a warning
+      // in this case.
+    }
+
+    Qualifiers Quals = Qualifiers::fromCVRMask(TypeQuals);
+    Result = Context.getQualifiedType(Result, Quals);
+  }
+
+  return Result;
+}
+
+static std::string getPrintableNameForEntity(DeclarationName Entity) {
+  if (Entity)
+    return Entity.getAsString();
+
+  return "type name";
+}
+
+QualType Sema::BuildQualifiedType(QualType T, SourceLocation Loc,
+                                  Qualifiers Qs) {
+  // Enforce C99 6.7.3p2: "Types other than pointer types derived from
+  // object or incomplete types shall not be restrict-qualified."
+  if (Qs.hasRestrict()) {
+    unsigned DiagID = 0;
+    QualType ProblemTy;
+
+    const Type *Ty = T->getCanonicalTypeInternal().getTypePtr();
+    if (const ReferenceType *RTy = dyn_cast<ReferenceType>(Ty)) {
+      if (!RTy->getPointeeType()->isIncompleteOrObjectType()) {
+        DiagID = diag::err_typecheck_invalid_restrict_invalid_pointee;
+        ProblemTy = T->getAs<ReferenceType>()->getPointeeType();
+      }
+    } else if (const PointerType *PTy = dyn_cast<PointerType>(Ty)) {
+      if (!PTy->getPointeeType()->isIncompleteOrObjectType()) {
+        DiagID = diag::err_typecheck_invalid_restrict_invalid_pointee;
+        ProblemTy = T->getAs<PointerType>()->getPointeeType();
+      }
+    } else if (const MemberPointerType *PTy = dyn_cast<MemberPointerType>(Ty)) {
+      if (!PTy->getPointeeType()->isIncompleteOrObjectType()) {
+        DiagID = diag::err_typecheck_invalid_restrict_invalid_pointee;
+        ProblemTy = T->getAs<PointerType>()->getPointeeType();
+      }      
+    } else if (!Ty->isDependentType()) {
+      // FIXME: this deserves a proper diagnostic
+      DiagID = diag::err_typecheck_invalid_restrict_invalid_pointee;
+      ProblemTy = T;
+    }
+
+    if (DiagID) {
+      Diag(Loc, DiagID) << ProblemTy;
+      Qs.removeRestrict();
+    }
+  }
+
+  return Context.getQualifiedType(T, Qs);
+}
+
+/// \brief Build a paren type including \p T.
+QualType Sema::BuildParenType(QualType T) {
+  return Context.getParenType(T);
+}
+
+/// Given that we're building a pointer or reference to the given
+static QualType inferARCLifetimeForPointee(Sema &S, QualType type,
+                                           SourceLocation loc,
+                                           bool isReference) {
+  // Bail out if retention is unrequired or already specified.
+  if (!type->isObjCLifetimeType() ||
+      type.getObjCLifetime() != Qualifiers::OCL_None)
+    return type;
+
+  Qualifiers::ObjCLifetime implicitLifetime = Qualifiers::OCL_None;
+
+  // If the object type is const-qualified, we can safely use
+  // __unsafe_unretained.  This is safe (because there are no read
+  // barriers), and it'll be safe to coerce anything but __weak* to
+  // the resulting type.
+  if (type.isConstQualified()) {
+    implicitLifetime = Qualifiers::OCL_ExplicitNone;
+
+  // Otherwise, check whether the static type does not require
+  // retaining.  This currently only triggers for Class (possibly
+  // protocol-qualifed, and arrays thereof).
+  } else if (type->isObjCARCImplicitlyUnretainedType()) {
+    implicitLifetime = Qualifiers::OCL_ExplicitNone;
+
+  // If we are in an unevaluated context, like sizeof, skip adding a
+  // qualification.
+  } else if (S.ExprEvalContexts.back().Context == Sema::Unevaluated) {
+    return type;
+
+  // If that failed, give an error and recover using __strong.  __strong
+  // is the option most likely to prevent spurious second-order diagnostics,
+  // like when binding a reference to a field.
+  } else {
+    // These types can show up in private ivars in system headers, so
+    // we need this to not be an error in those cases.  Instead we
+    // want to delay.
+    if (S.DelayedDiagnostics.shouldDelayDiagnostics()) {
+      S.DelayedDiagnostics.add(
+          sema::DelayedDiagnostic::makeForbiddenType(loc,
+              diag::err_arc_indirect_no_ownership, type, isReference));
+    } else {
+      S.Diag(loc, diag::err_arc_indirect_no_ownership) << type << isReference;
+    }
+    implicitLifetime = Qualifiers::OCL_Strong;
+  }
+  assert(implicitLifetime && "didn't infer any lifetime!");
+
+  Qualifiers qs;
+  qs.addObjCLifetime(implicitLifetime);
+  return S.Context.getQualifiedType(type, qs);
+}
+
+/// \brief Build a pointer type.
+///
+/// \param T The type to which we'll be building a pointer.
+///
+/// \param Loc The location of the entity whose type involves this
+/// pointer type or, if there is no such entity, the location of the
+/// type that will have pointer type.
+///
+/// \param Entity The name of the entity that involves the pointer
+/// type, if known.
+///
+/// \returns A suitable pointer type, if there are no
+/// errors. Otherwise, returns a NULL type.
+QualType Sema::BuildPointerType(QualType T,
+                                SourceLocation Loc, DeclarationName Entity) {
+  if (T->isReferenceType()) {
+    // C++ 8.3.2p4: There shall be no ... pointers to references ...
+    Diag(Loc, diag::err_illegal_decl_pointer_to_reference)
+      << getPrintableNameForEntity(Entity) << T;
+    return QualType();
+  }
+
+  assert(!T->isObjCObjectType() && "Should build ObjCObjectPointerType");
+
+  // In ARC, it is forbidden to build pointers to unqualified pointers.
+  if (getLangOpts().ObjCAutoRefCount)
+    T = inferARCLifetimeForPointee(*this, T, Loc, /*reference*/ false);
+
+  // Build the pointer type.
+  return Context.getPointerType(T);
+}
+
+/// \brief Build a reference type.
+///
+/// \param T The type to which we'll be building a reference.
+///
+/// \param Loc The location of the entity whose type involves this
+/// reference type or, if there is no such entity, the location of the
+/// type that will have reference type.
+///
+/// \param Entity The name of the entity that involves the reference
+/// type, if known.
+///
+/// \returns A suitable reference type, if there are no
+/// errors. Otherwise, returns a NULL type.
+QualType Sema::BuildReferenceType(QualType T, bool SpelledAsLValue,
+                                  SourceLocation Loc,
+                                  DeclarationName Entity) {
+  assert(Context.getCanonicalType(T) != Context.OverloadTy && 
+         "Unresolved overloaded function type");
+  
+  // C++0x [dcl.ref]p6:
+  //   If a typedef (7.1.3), a type template-parameter (14.3.1), or a 
+  //   decltype-specifier (7.1.6.2) denotes a type TR that is a reference to a 
+  //   type T, an attempt to create the type "lvalue reference to cv TR" creates 
+  //   the type "lvalue reference to T", while an attempt to create the type 
+  //   "rvalue reference to cv TR" creates the type TR.
+  bool LValueRef = SpelledAsLValue || T->getAs<LValueReferenceType>();
+
+  // C++ [dcl.ref]p4: There shall be no references to references.
+  //
+  // According to C++ DR 106, references to references are only
+  // diagnosed when they are written directly (e.g., "int & &"),
+  // but not when they happen via a typedef:
+  //
+  //   typedef int& intref;
+  //   typedef intref& intref2;
+  //
+  // Parser::ParseDeclaratorInternal diagnoses the case where
+  // references are written directly; here, we handle the
+  // collapsing of references-to-references as described in C++0x.
+  // DR 106 and 540 introduce reference-collapsing into C++98/03.
+
+  // C++ [dcl.ref]p1:
+  //   A declarator that specifies the type "reference to cv void"
+  //   is ill-formed.
+  if (T->isVoidType()) {
+    Diag(Loc, diag::err_reference_to_void);
+    return QualType();
+  }
+
+  // In ARC, it is forbidden to build references to unqualified pointers.
+  if (getLangOpts().ObjCAutoRefCount)
+    T = inferARCLifetimeForPointee(*this, T, Loc, /*reference*/ true);
+
+  // Handle restrict on references.
+  if (LValueRef)
+    return Context.getLValueReferenceType(T, SpelledAsLValue);
+  return Context.getRValueReferenceType(T);
+}
+
+/// Check whether the specified array size makes the array type a VLA.  If so,
+/// return true, if not, return the size of the array in SizeVal.
+static bool isArraySizeVLA(Sema &S, Expr *ArraySize, llvm::APSInt &SizeVal) {
+  // If the size is an ICE, it certainly isn't a VLA. If we're in a GNU mode
+  // (like gnu99, but not c99) accept any evaluatable value as an extension.
+  return S.VerifyIntegerConstantExpression(
+      ArraySize, &SizeVal, S.PDiag(), S.LangOpts.GNUMode,
+      S.PDiag(diag::ext_vla_folded_to_constant)).isInvalid();
+}
+
+
+/// \brief Build an array type.
+///
+/// \param T The type of each element in the array.
+///
+/// \param ASM C99 array size modifier (e.g., '*', 'static').
+///
+/// \param ArraySize Expression describing the size of the array.
+///
+/// \param Loc The location of the entity whose type involves this
+/// array type or, if there is no such entity, the location of the
+/// type that will have array type.
+///
+/// \param Entity The name of the entity that involves the array
+/// type, if known.
+///
+/// \returns A suitable array type, if there are no errors. Otherwise,
+/// returns a NULL type.
+QualType Sema::BuildArrayType(QualType T, ArrayType::ArraySizeModifier ASM,
+                              Expr *ArraySize, unsigned Quals,
+                              SourceRange Brackets, DeclarationName Entity) {
+
+  SourceLocation Loc = Brackets.getBegin();
+  if (getLangOpts().CPlusPlus) {
+    // C++ [dcl.array]p1:
+    //   T is called the array element type; this type shall not be a reference
+    //   type, the (possibly cv-qualified) type void, a function type or an 
+    //   abstract class type.
+    //
+    // Note: function types are handled in the common path with C.
+    if (T->isReferenceType()) {
+      Diag(Loc, diag::err_illegal_decl_array_of_references)
+      << getPrintableNameForEntity(Entity) << T;
+      return QualType();
+    }
+    
+    if (T->isVoidType()) {
+      Diag(Loc, diag::err_illegal_decl_array_incomplete_type) << T;
+      return QualType();
+    }
+    
+    if (RequireNonAbstractType(Brackets.getBegin(), T, 
+                               diag::err_array_of_abstract_type))
+      return QualType();
+    
+  } else {
+    // C99 6.7.5.2p1: If the element type is an incomplete or function type,
+    // reject it (e.g. void ary[7], struct foo ary[7], void ary[7]())
+    if (RequireCompleteType(Loc, T,
+                            diag::err_illegal_decl_array_incomplete_type))
+      return QualType();
+  }
+
+  if (T->isFunctionType()) {
+    Diag(Loc, diag::err_illegal_decl_array_of_functions)
+      << getPrintableNameForEntity(Entity) << T;
+    return QualType();
+  }
+
+  if (T->getContainedAutoType()) {
+    Diag(Loc, diag::err_illegal_decl_array_of_auto)
+      << getPrintableNameForEntity(Entity) << T;
+    return QualType();
+  }
+
+  if (const RecordType *EltTy = T->getAs<RecordType>()) {
+    // If the element type is a struct or union that contains a variadic
+    // array, accept it as a GNU extension: C99 6.7.2.1p2.
+    if (EltTy->getDecl()->hasFlexibleArrayMember())
+      Diag(Loc, diag::ext_flexible_array_in_array) << T;
+  } else if (T->isObjCObjectType()) {
+    Diag(Loc, diag::err_objc_array_of_interfaces) << T;
+    return QualType();
+  }
+
+  // Do placeholder conversions on the array size expression.
+  if (ArraySize && ArraySize->hasPlaceholderType()) {
+    ExprResult Result = CheckPlaceholderExpr(ArraySize);
+    if (Result.isInvalid()) return QualType();
+    ArraySize = Result.take();
+  }
+
+  // Do lvalue-to-rvalue conversions on the array size expression.
+  if (ArraySize && !ArraySize->isRValue()) {
+    ExprResult Result = DefaultLvalueConversion(ArraySize);
+    if (Result.isInvalid())
+      return QualType();
+
+    ArraySize = Result.take();
+  }
+
+  // C99 6.7.5.2p1: The size expression shall have integer type.
+  // C++11 allows contextual conversions to such types.
+  if (!getLangOpts().CPlusPlus0x &&
+      ArraySize && !ArraySize->isTypeDependent() &&
+      !ArraySize->getType()->isIntegralOrUnscopedEnumerationType()) {
+    Diag(ArraySize->getLocStart(), diag::err_array_size_non_int)
+      << ArraySize->getType() << ArraySize->getSourceRange();
+    return QualType();
+  }
+
+  llvm::APSInt ConstVal(Context.getTypeSize(Context.getSizeType()));
+  if (!ArraySize) {
+    if (ASM == ArrayType::Star)
+      T = Context.getVariableArrayType(T, 0, ASM, Quals, Brackets);
+    else
+      T = Context.getIncompleteArrayType(T, ASM, Quals);
+  } else if (ArraySize->isTypeDependent() || ArraySize->isValueDependent()) {
+    T = Context.getDependentSizedArrayType(T, ArraySize, ASM, Quals, Brackets);
+  } else if ((!T->isDependentType() && !T->isIncompleteType() &&
+              !T->isConstantSizeType()) ||
+             isArraySizeVLA(*this, ArraySize, ConstVal)) {
+    // Even in C++11, don't allow contextual conversions in the array bound
+    // of a VLA.
+    if (getLangOpts().CPlusPlus0x &&
+        !ArraySize->getType()->isIntegralOrUnscopedEnumerationType()) {
+      Diag(ArraySize->getLocStart(), diag::err_array_size_non_int)
+        << ArraySize->getType() << ArraySize->getSourceRange();
+      return QualType();
+    }
+
+    // C99: an array with an element type that has a non-constant-size is a VLA.
+    // C99: an array with a non-ICE size is a VLA.  We accept any expression
+    // that we can fold to a non-zero positive value as an extension.
+    T = Context.getVariableArrayType(T, ArraySize, ASM, Quals, Brackets);
+  } else {
+    // C99 6.7.5.2p1: If the expression is a constant expression, it shall
+    // have a value greater than zero.
+    if (ConstVal.isSigned() && ConstVal.isNegative()) {
+      if (Entity)
+        Diag(ArraySize->getLocStart(), diag::err_decl_negative_array_size)
+          << getPrintableNameForEntity(Entity) << ArraySize->getSourceRange();
+      else
+        Diag(ArraySize->getLocStart(), diag::err_typecheck_negative_array_size)
+          << ArraySize->getSourceRange();
+      return QualType();
+    }
+    if (ConstVal == 0) {
+      // GCC accepts zero sized static arrays. We allow them when
+      // we're not in a SFINAE context.
+      Diag(ArraySize->getLocStart(), 
+           isSFINAEContext()? diag::err_typecheck_zero_array_size
+                            : diag::ext_typecheck_zero_array_size)
+        << ArraySize->getSourceRange();
+
+      if (ASM == ArrayType::Static) {
+        Diag(ArraySize->getLocStart(),
+             diag::warn_typecheck_zero_static_array_size)
+          << ArraySize->getSourceRange();
+        ASM = ArrayType::Normal;
+      }
+    } else if (!T->isDependentType() && !T->isVariablyModifiedType() && 
+               !T->isIncompleteType()) {
+      // Is the array too large?      
+      unsigned ActiveSizeBits
+        = ConstantArrayType::getNumAddressingBits(Context, T, ConstVal);
+      if (ActiveSizeBits > ConstantArrayType::getMaxSizeBits(Context))
+        Diag(ArraySize->getLocStart(), diag::err_array_too_large)
+          << ConstVal.toString(10)
+          << ArraySize->getSourceRange();
+    }
+    
+    T = Context.getConstantArrayType(T, ConstVal, ASM, Quals);
+  }
+  // If this is not C99, extwarn about VLA's and C99 array size modifiers.
+  if (!getLangOpts().C99) {
+    if (T->isVariableArrayType()) {
+      // Prohibit the use of non-POD types in VLAs.
+      QualType BaseT = Context.getBaseElementType(T);
+      if (!T->isDependentType() && 
+          !BaseT.isPODType(Context) &&
+          !BaseT->isObjCLifetimeType()) {
+        Diag(Loc, diag::err_vla_non_pod)
+          << BaseT;
+        return QualType();
+      } 
+      // Prohibit the use of VLAs during template argument deduction.
+      else if (isSFINAEContext()) {
+        Diag(Loc, diag::err_vla_in_sfinae);
+        return QualType();
+      }
+      // Just extwarn about VLAs.
+      else
+        Diag(Loc, diag::ext_vla);
+    } else if (ASM != ArrayType::Normal || Quals != 0)
+      Diag(Loc,
+           getLangOpts().CPlusPlus? diag::err_c99_array_usage_cxx
+                                     : diag::ext_c99_array_usage) << ASM;
+  }
+
+  return T;
+}
+
+/// \brief Build an ext-vector type.
+///
+/// Run the required checks for the extended vector type.
+QualType Sema::BuildExtVectorType(QualType T, Expr *ArraySize,
+                                  SourceLocation AttrLoc) {
+  // unlike gcc's vector_size attribute, we do not allow vectors to be defined
+  // in conjunction with complex types (pointers, arrays, functions, etc.).
+  if (!T->isDependentType() &&
+      !T->isIntegerType() && !T->isRealFloatingType()) {
+    Diag(AttrLoc, diag::err_attribute_invalid_vector_type) << T;
+    return QualType();
+  }
+
+  if (!ArraySize->isTypeDependent() && !ArraySize->isValueDependent()) {
+    llvm::APSInt vecSize(32);
+    if (!ArraySize->isIntegerConstantExpr(vecSize, Context)) {
+      Diag(AttrLoc, diag::err_attribute_argument_not_int)
+        << "ext_vector_type" << ArraySize->getSourceRange();
+      return QualType();
+    }
+
+    // unlike gcc's vector_size attribute, the size is specified as the
+    // number of elements, not the number of bytes.
+    unsigned vectorSize = static_cast<unsigned>(vecSize.getZExtValue());
+
+    if (vectorSize == 0) {
+      Diag(AttrLoc, diag::err_attribute_zero_size)
+      << ArraySize->getSourceRange();
+      return QualType();
+    }
+
+    return Context.getExtVectorType(T, vectorSize);
+  }
+
+  return Context.getDependentSizedExtVectorType(T, ArraySize, AttrLoc);
+}
+
+/// \brief Build a function type.
+///
+/// This routine checks the function type according to C++ rules and
+/// under the assumption that the result type and parameter types have
+/// just been instantiated from a template. It therefore duplicates
+/// some of the behavior of GetTypeForDeclarator, but in a much
+/// simpler form that is only suitable for this narrow use case.
+///
+/// \param T The return type of the function.
+///
+/// \param ParamTypes The parameter types of the function. This array
+/// will be modified to account for adjustments to the types of the
+/// function parameters.
+///
+/// \param NumParamTypes The number of parameter types in ParamTypes.
+///
+/// \param Variadic Whether this is a variadic function type.
+///
+/// \param HasTrailingReturn Whether this function has a trailing return type.
+///
+/// \param Quals The cvr-qualifiers to be applied to the function type.
+///
+/// \param Loc The location of the entity whose type involves this
+/// function type or, if there is no such entity, the location of the
+/// type that will have function type.
+///
+/// \param Entity The name of the entity that involves the function
+/// type, if known.
+///
+/// \returns A suitable function type, if there are no
+/// errors. Otherwise, returns a NULL type.
+QualType Sema::BuildFunctionType(QualType T,
+                                 QualType *ParamTypes,
+                                 unsigned NumParamTypes,
+                                 bool Variadic, bool HasTrailingReturn,
+                                 unsigned Quals,
+                                 RefQualifierKind RefQualifier,
+                                 SourceLocation Loc, DeclarationName Entity,
+                                 FunctionType::ExtInfo Info) {
+  if (T->isArrayType() || T->isFunctionType()) {
+    Diag(Loc, diag::err_func_returning_array_function) 
+      << T->isFunctionType() << T;
+    return QualType();
+  }
+
+  // Functions cannot return half FP.
+  if (T->isHalfType()) {
+    Diag(Loc, diag::err_parameters_retval_cannot_have_fp16_type) << 1 <<
+      FixItHint::CreateInsertion(Loc, "*");
+    return QualType();
+  }
+
+  bool Invalid = false;
+  for (unsigned Idx = 0; Idx < NumParamTypes; ++Idx) {
+    // FIXME: Loc is too inprecise here, should use proper locations for args.
+    QualType ParamType = Context.getAdjustedParameterType(ParamTypes[Idx]);
+    if (ParamType->isVoidType()) {
+      Diag(Loc, diag::err_param_with_void_type);
+      Invalid = true;
+    } else if (ParamType->isHalfType()) {
+      // Disallow half FP arguments.
+      Diag(Loc, diag::err_parameters_retval_cannot_have_fp16_type) << 0 <<
+        FixItHint::CreateInsertion(Loc, "*");
+      Invalid = true;
+    }
+
+    ParamTypes[Idx] = ParamType;
+  }
+
+  if (Invalid)
+    return QualType();
+
+  FunctionProtoType::ExtProtoInfo EPI;
+  EPI.Variadic = Variadic;
+  EPI.HasTrailingReturn = HasTrailingReturn;
+  EPI.TypeQuals = Quals;
+  EPI.RefQualifier = RefQualifier;
+  EPI.ExtInfo = Info;
+
+  return Context.getFunctionType(T, ParamTypes, NumParamTypes, EPI);
+}
+
+/// \brief Build a member pointer type \c T Class::*.
+///
+/// \param T the type to which the member pointer refers.
+/// \param Class the class type into which the member pointer points.
+/// \param Loc the location where this type begins
+/// \param Entity the name of the entity that will have this member pointer type
+///
+/// \returns a member pointer type, if successful, or a NULL type if there was
+/// an error.
+QualType Sema::BuildMemberPointerType(QualType T, QualType Class,
+                                      SourceLocation Loc,
+                                      DeclarationName Entity) {
+  // Verify that we're not building a pointer to pointer to function with
+  // exception specification.
+  if (CheckDistantExceptionSpec(T)) {
+    Diag(Loc, diag::err_distant_exception_spec);
+
+    // FIXME: If we're doing this as part of template instantiation,
+    // we should return immediately.
+
+    // Build the type anyway, but use the canonical type so that the
+    // exception specifiers are stripped off.
+    T = Context.getCanonicalType(T);
+  }
+
+  // C++ 8.3.3p3: A pointer to member shall not point to ... a member
+  //   with reference type, or "cv void."
+  if (T->isReferenceType()) {
+    Diag(Loc, diag::err_illegal_decl_mempointer_to_reference)
+      << (Entity? Entity.getAsString() : "type name") << T;
+    return QualType();
+  }
+
+  if (T->isVoidType()) {
+    Diag(Loc, diag::err_illegal_decl_mempointer_to_void)
+      << (Entity? Entity.getAsString() : "type name");
+    return QualType();
+  }
+
+  if (!Class->isDependentType() && !Class->isRecordType()) {
+    Diag(Loc, diag::err_mempointer_in_nonclass_type) << Class;
+    return QualType();
+  }
+
+  // In the Microsoft ABI, the class is allowed to be an incomplete
+  // type. In such cases, the compiler makes a worst-case assumption.
+  // We make no such assumption right now, so emit an error if the
+  // class isn't a complete type.
+  if (Context.getTargetInfo().getCXXABI() == CXXABI_Microsoft &&
+      RequireCompleteType(Loc, Class, diag::err_incomplete_type))
+    return QualType();
+
+  return Context.getMemberPointerType(T, Class.getTypePtr());
+}
+
+/// \brief Build a block pointer type.
+///
+/// \param T The type to which we'll be building a block pointer.
+///
+/// \param CVR The cvr-qualifiers to be applied to the block pointer type.
+///
+/// \param Loc The location of the entity whose type involves this
+/// block pointer type or, if there is no such entity, the location of the
+/// type that will have block pointer type.
+///
+/// \param Entity The name of the entity that involves the block pointer
+/// type, if known.
+///
+/// \returns A suitable block pointer type, if there are no
+/// errors. Otherwise, returns a NULL type.
+QualType Sema::BuildBlockPointerType(QualType T, 
+                                     SourceLocation Loc,
+                                     DeclarationName Entity) {
+  if (!T->isFunctionType()) {
+    Diag(Loc, diag::err_nonfunction_block_type);
+    return QualType();
+  }
+
+  return Context.getBlockPointerType(T);
+}
+
+QualType Sema::GetTypeFromParser(ParsedType Ty, TypeSourceInfo **TInfo) {
+  QualType QT = Ty.get();
+  if (QT.isNull()) {
+    if (TInfo) *TInfo = 0;
+    return QualType();
+  }
+
+  TypeSourceInfo *DI = 0;
+  if (const LocInfoType *LIT = dyn_cast<LocInfoType>(QT)) {
+    QT = LIT->getType();
+    DI = LIT->getTypeSourceInfo();
+  }
+
+  if (TInfo) *TInfo = DI;
+  return QT;
+}
+
+static void transferARCOwnershipToDeclaratorChunk(TypeProcessingState &state,
+                                            Qualifiers::ObjCLifetime ownership,
+                                            unsigned chunkIndex);
+
+/// Given that this is the declaration of a parameter under ARC,
+/// attempt to infer attributes and such for pointer-to-whatever
+/// types.
+static void inferARCWriteback(TypeProcessingState &state,
+                              QualType &declSpecType) {
+  Sema &S = state.getSema();
+  Declarator &declarator = state.getDeclarator();
+
+  // TODO: should we care about decl qualifiers?
+
+  // Check whether the declarator has the expected form.  We walk
+  // from the inside out in order to make the block logic work.
+  unsigned outermostPointerIndex = 0;
+  bool isBlockPointer = false;
+  unsigned numPointers = 0;
+  for (unsigned i = 0, e = declarator.getNumTypeObjects(); i != e; ++i) {
+    unsigned chunkIndex = i;
+    DeclaratorChunk &chunk = declarator.getTypeObject(chunkIndex);
+    switch (chunk.Kind) {
+    case DeclaratorChunk::Paren:
+      // Ignore parens.
+      break;
+
+    case DeclaratorChunk::Reference:
+    case DeclaratorChunk::Pointer:
+      // Count the number of pointers.  Treat references
+      // interchangeably as pointers; if they're mis-ordered, normal
+      // type building will discover that.
+      outermostPointerIndex = chunkIndex;
+      numPointers++;
+      break;
+
+    case DeclaratorChunk::BlockPointer:
+      // If we have a pointer to block pointer, that's an acceptable
+      // indirect reference; anything else is not an application of
+      // the rules.
+      if (numPointers != 1) return;
+      numPointers++;
+      outermostPointerIndex = chunkIndex;
+      isBlockPointer = true;
+
+      // We don't care about pointer structure in return values here.
+      goto done;
+
+    case DeclaratorChunk::Array: // suppress if written (id[])?
+    case DeclaratorChunk::Function:
+    case DeclaratorChunk::MemberPointer:
+      return;
+    }
+  }
+ done:
+
+  // If we have *one* pointer, then we want to throw the qualifier on
+  // the declaration-specifiers, which means that it needs to be a
+  // retainable object type.
+  if (numPointers == 1) {
+    // If it's not a retainable object type, the rule doesn't apply.
+    if (!declSpecType->isObjCRetainableType()) return;
+
+    // If it already has lifetime, don't do anything.
+    if (declSpecType.getObjCLifetime()) return;
+
+    // Otherwise, modify the type in-place.
+    Qualifiers qs;
+    
+    if (declSpecType->isObjCARCImplicitlyUnretainedType())
+      qs.addObjCLifetime(Qualifiers::OCL_ExplicitNone);
+    else
+      qs.addObjCLifetime(Qualifiers::OCL_Autoreleasing);
+    declSpecType = S.Context.getQualifiedType(declSpecType, qs);
+
+  // If we have *two* pointers, then we want to throw the qualifier on
+  // the outermost pointer.
+  } else if (numPointers == 2) {
+    // If we don't have a block pointer, we need to check whether the
+    // declaration-specifiers gave us something that will turn into a
+    // retainable object pointer after we slap the first pointer on it.
+    if (!isBlockPointer && !declSpecType->isObjCObjectType())
+      return;
+
+    // Look for an explicit lifetime attribute there.
+    DeclaratorChunk &chunk = declarator.getTypeObject(outermostPointerIndex);
+    if (chunk.Kind != DeclaratorChunk::Pointer &&
+        chunk.Kind != DeclaratorChunk::BlockPointer)
+      return;
+    for (const AttributeList *attr = chunk.getAttrs(); attr;
+           attr = attr->getNext())
+      if (attr->getKind() == AttributeList::AT_objc_ownership)
+        return;
+
+    transferARCOwnershipToDeclaratorChunk(state, Qualifiers::OCL_Autoreleasing,
+                                          outermostPointerIndex);
+
+  // Any other number of pointers/references does not trigger the rule.
+  } else return;
+
+  // TODO: mark whether we did this inference?
+}
+
+static void DiagnoseIgnoredQualifiers(unsigned Quals,
+                                      SourceLocation ConstQualLoc,
+                                      SourceLocation VolatileQualLoc,
+                                      SourceLocation RestrictQualLoc,
+                                      Sema& S) {
+  std::string QualStr;
+  unsigned NumQuals = 0;
+  SourceLocation Loc;
+
+  FixItHint ConstFixIt;
+  FixItHint VolatileFixIt;
+  FixItHint RestrictFixIt;
+
+  const SourceManager &SM = S.getSourceManager();
+
+  // FIXME: The locations here are set kind of arbitrarily. It'd be nicer to
+  // find a range and grow it to encompass all the qualifiers, regardless of
+  // the order in which they textually appear.
+  if (Quals & Qualifiers::Const) {
+    ConstFixIt = FixItHint::CreateRemoval(ConstQualLoc);
+    QualStr = "const";
+    ++NumQuals;
+    if (!Loc.isValid() || SM.isBeforeInTranslationUnit(ConstQualLoc, Loc))
+      Loc = ConstQualLoc;
+  }
+  if (Quals & Qualifiers::Volatile) {
+    VolatileFixIt = FixItHint::CreateRemoval(VolatileQualLoc);
+    QualStr += (NumQuals == 0 ? "volatile" : " volatile");
+    ++NumQuals;
+    if (!Loc.isValid() || SM.isBeforeInTranslationUnit(VolatileQualLoc, Loc))
+      Loc = VolatileQualLoc;
+  }
+  if (Quals & Qualifiers::Restrict) {
+    RestrictFixIt = FixItHint::CreateRemoval(RestrictQualLoc);
+    QualStr += (NumQuals == 0 ? "restrict" : " restrict");
+    ++NumQuals;
+    if (!Loc.isValid() || SM.isBeforeInTranslationUnit(RestrictQualLoc, Loc))
+      Loc = RestrictQualLoc;
+  }
+
+  assert(NumQuals > 0 && "No known qualifiers?");
+
+  S.Diag(Loc, diag::warn_qual_return_type)
+    << QualStr << NumQuals << ConstFixIt << VolatileFixIt << RestrictFixIt;
+}
+
+static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state,
+                                             TypeSourceInfo *&ReturnTypeInfo) {
+  Sema &SemaRef = state.getSema();
+  Declarator &D = state.getDeclarator();
+  QualType T;
+  ReturnTypeInfo = 0;
+
+  // The TagDecl owned by the DeclSpec.
+  TagDecl *OwnedTagDecl = 0;
+
+  switch (D.getName().getKind()) {
+  case UnqualifiedId::IK_ImplicitSelfParam:
+  case UnqualifiedId::IK_OperatorFunctionId:
+  case UnqualifiedId::IK_Identifier:
+  case UnqualifiedId::IK_LiteralOperatorId:
+  case UnqualifiedId::IK_TemplateId:
+    T = ConvertDeclSpecToType(state);
+    
+    if (!D.isInvalidType() && D.getDeclSpec().isTypeSpecOwned()) {
+      OwnedTagDecl = cast<TagDecl>(D.getDeclSpec().getRepAsDecl());
+      // Owned declaration is embedded in declarator.
+      OwnedTagDecl->setEmbeddedInDeclarator(true);
+    }
+    break;
+
+  case UnqualifiedId::IK_ConstructorName:
+  case UnqualifiedId::IK_ConstructorTemplateId:
+  case UnqualifiedId::IK_DestructorName:
+    // Constructors and destructors don't have return types. Use
+    // "void" instead. 
+    T = SemaRef.Context.VoidTy;
+    break;
+
+  case UnqualifiedId::IK_ConversionFunctionId:
+    // The result type of a conversion function is the type that it
+    // converts to.
+    T = SemaRef.GetTypeFromParser(D.getName().ConversionFunctionId, 
+                                  &ReturnTypeInfo);
+    break;
+  }
+
+  if (D.getAttributes())
+    distributeTypeAttrsFromDeclarator(state, T);
+
+  // C++11 [dcl.spec.auto]p5: reject 'auto' if it is not in an allowed context.
+  // In C++11, a function declarator using 'auto' must have a trailing return
+  // type (this is checked later) and we can skip this. In other languages
+  // using auto, we need to check regardless.
+  if (D.getDeclSpec().getTypeSpecType() == DeclSpec::TST_auto &&
+      (!SemaRef.getLangOpts().CPlusPlus0x || !D.isFunctionDeclarator())) {
+    int Error = -1;
+
+    switch (D.getContext()) {
+    case Declarator::KNRTypeListContext:
+      llvm_unreachable("K&R type lists aren't allowed in C++");
+    case Declarator::LambdaExprContext:
+      llvm_unreachable("Can't specify a type specifier in lambda grammar");
+    case Declarator::ObjCParameterContext:
+    case Declarator::ObjCResultContext:
+    case Declarator::PrototypeContext:
+      Error = 0; // Function prototype
+      break;
+    case Declarator::MemberContext:
+      if (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_static)
+        break;
+      switch (cast<TagDecl>(SemaRef.CurContext)->getTagKind()) {
+      case TTK_Enum: llvm_unreachable("unhandled tag kind");
+      case TTK_Struct: Error = 1; /* Struct member */ break;
+      case TTK_Union:  Error = 2; /* Union member */ break;
+      case TTK_Class:  Error = 3; /* Class member */ break;
+      }
+      break;
+    case Declarator::CXXCatchContext:
+    case Declarator::ObjCCatchContext:
+      Error = 4; // Exception declaration
+      break;
+    case Declarator::TemplateParamContext:
+      Error = 5; // Template parameter
+      break;
+    case Declarator::BlockLiteralContext:
+      Error = 6; // Block literal
+      break;
+    case Declarator::TemplateTypeArgContext:
+      Error = 7; // Template type argument
+      break;
+    case Declarator::AliasDeclContext:
+    case Declarator::AliasTemplateContext:
+      Error = 9; // Type alias
+      break;
+    case Declarator::TrailingReturnContext:
+      Error = 10; // Function return type
+      break;
+    case Declarator::TypeNameContext:
+      Error = 11; // Generic
+      break;
+    case Declarator::FileContext:
+    case Declarator::BlockContext:
+    case Declarator::ForContext:
+    case Declarator::ConditionContext:
+    case Declarator::CXXNewContext:
+      break;
+    }
+
+    if (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_typedef)
+      Error = 8;
+
+    // In Objective-C it is an error to use 'auto' on a function declarator.
+    if (D.isFunctionDeclarator())
+      Error = 10;
+
+    // C++11 [dcl.spec.auto]p2: 'auto' is always fine if the declarator
+    // contains a trailing return type. That is only legal at the outermost
+    // level. Check all declarator chunks (outermost first) anyway, to give
+    // better diagnostics.
+    if (SemaRef.getLangOpts().CPlusPlus0x && Error != -1) {
+      for (unsigned i = 0, e = D.getNumTypeObjects(); i != e; ++i) {
+        unsigned chunkIndex = e - i - 1;
+        state.setCurrentChunkIndex(chunkIndex);
+        DeclaratorChunk &DeclType = D.getTypeObject(chunkIndex);
+        if (DeclType.Kind == DeclaratorChunk::Function) {
+          const DeclaratorChunk::FunctionTypeInfo &FTI = DeclType.Fun;
+          if (FTI.TrailingReturnType) {
+            Error = -1;
+            break;
+          }
+        }
+      }
+    }
+
+    if (Error != -1) {
+      SemaRef.Diag(D.getDeclSpec().getTypeSpecTypeLoc(),
+                   diag::err_auto_not_allowed)
+        << Error;
+      T = SemaRef.Context.IntTy;
+      D.setInvalidType(true);
+    } else
+      SemaRef.Diag(D.getDeclSpec().getTypeSpecTypeLoc(),
+                   diag::warn_cxx98_compat_auto_type_specifier);
+  }
+
+  if (SemaRef.getLangOpts().CPlusPlus &&
+      OwnedTagDecl && OwnedTagDecl->isCompleteDefinition()) {
+    // Check the contexts where C++ forbids the declaration of a new class
+    // or enumeration in a type-specifier-seq.
+    switch (D.getContext()) {
+    case Declarator::TrailingReturnContext:
+      // Class and enumeration definitions are syntactically not allowed in
+      // trailing return types.
+      llvm_unreachable("parser should not have allowed this");
+      break;
+    case Declarator::FileContext:
+    case Declarator::MemberContext:
+    case Declarator::BlockContext:
+    case Declarator::ForContext:
+    case Declarator::BlockLiteralContext:
+    case Declarator::LambdaExprContext:
+      // C++11 [dcl.type]p3:
+      //   A type-specifier-seq shall not define a class or enumeration unless
+      //   it appears in the type-id of an alias-declaration (7.1.3) that is not
+      //   the declaration of a template-declaration.
+    case Declarator::AliasDeclContext:
+      break;
+    case Declarator::AliasTemplateContext:
+      SemaRef.Diag(OwnedTagDecl->getLocation(),
+             diag::err_type_defined_in_alias_template)
+        << SemaRef.Context.getTypeDeclType(OwnedTagDecl);
+      break;
+    case Declarator::TypeNameContext:
+    case Declarator::TemplateParamContext:
+    case Declarator::CXXNewContext:
+    case Declarator::CXXCatchContext:
+    case Declarator::ObjCCatchContext:
+    case Declarator::TemplateTypeArgContext:
+      SemaRef.Diag(OwnedTagDecl->getLocation(),
+             diag::err_type_defined_in_type_specifier)
+        << SemaRef.Context.getTypeDeclType(OwnedTagDecl);
+      break;
+    case Declarator::PrototypeContext:
+    case Declarator::ObjCParameterContext:
+    case Declarator::ObjCResultContext:
+    case Declarator::KNRTypeListContext:
+      // C++ [dcl.fct]p6:
+      //   Types shall not be defined in return or parameter types.
+      SemaRef.Diag(OwnedTagDecl->getLocation(),
+                   diag::err_type_defined_in_param_type)
+        << SemaRef.Context.getTypeDeclType(OwnedTagDecl);
+      break;
+    case Declarator::ConditionContext:
+      // C++ 6.4p2:
+      // The type-specifier-seq shall not contain typedef and shall not declare
+      // a new class or enumeration.
+      SemaRef.Diag(OwnedTagDecl->getLocation(),
+                   diag::err_type_defined_in_condition);
+      break;
+    }
+  }
+
+  return T;
+}
+
+static std::string getFunctionQualifiersAsString(const FunctionProtoType *FnTy){
+  std::string Quals =
+    Qualifiers::fromCVRMask(FnTy->getTypeQuals()).getAsString();
+
+  switch (FnTy->getRefQualifier()) {
+  case RQ_None:
+    break;
+
+  case RQ_LValue:
+    if (!Quals.empty())
+      Quals += ' ';
+    Quals += '&';
+    break;
+
+  case RQ_RValue:
+    if (!Quals.empty())
+      Quals += ' ';
+    Quals += "&&";
+    break;
+  }
+
+  return Quals;
+}
+
+/// Check that the function type T, which has a cv-qualifier or a ref-qualifier,
+/// can be contained within the declarator chunk DeclType, and produce an
+/// appropriate diagnostic if not.
+static void checkQualifiedFunction(Sema &S, QualType T,
+                                   DeclaratorChunk &DeclType) {
+  // C++98 [dcl.fct]p4 / C++11 [dcl.fct]p6: a function type with a
+  // cv-qualifier or a ref-qualifier can only appear at the topmost level
+  // of a type.
+  int DiagKind = -1;
+  switch (DeclType.Kind) {
+  case DeclaratorChunk::Paren:
+  case DeclaratorChunk::MemberPointer:
+    // These cases are permitted.
+    return;
+  case DeclaratorChunk::Array:
+  case DeclaratorChunk::Function:
+    // These cases don't allow function types at all; no need to diagnose the
+    // qualifiers separately.
+    return;
+  case DeclaratorChunk::BlockPointer:
+    DiagKind = 0;
+    break;
+  case DeclaratorChunk::Pointer:
+    DiagKind = 1;
+    break;
+  case DeclaratorChunk::Reference:
+    DiagKind = 2;
+    break;
+  }
+
+  assert(DiagKind != -1);
+  S.Diag(DeclType.Loc, diag::err_compound_qualified_function_type)
+    << DiagKind << isa<FunctionType>(T.IgnoreParens()) << T
+    << getFunctionQualifiersAsString(T->castAs<FunctionProtoType>());
+}
+
+static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
+                                                QualType declSpecType,
+                                                TypeSourceInfo *TInfo) {
+
+  QualType T = declSpecType;
+  Declarator &D = state.getDeclarator();
+  Sema &S = state.getSema();
+  ASTContext &Context = S.Context;
+  const LangOptions &LangOpts = S.getLangOpts();
+
+  bool ImplicitlyNoexcept = false;
+  if (D.getName().getKind() == UnqualifiedId::IK_OperatorFunctionId &&
+      LangOpts.CPlusPlus0x) {
+    OverloadedOperatorKind OO = D.getName().OperatorFunctionId.Operator;
+    /// In C++0x, deallocation functions (normal and array operator delete)
+    /// are implicitly noexcept.
+    if (OO == OO_Delete || OO == OO_Array_Delete)
+      ImplicitlyNoexcept = true;
+  }
+
+  // The name we're declaring, if any.
+  DeclarationName Name;
+  if (D.getIdentifier())
+    Name = D.getIdentifier();
+
+  // Does this declaration declare a typedef-name?
+  bool IsTypedefName =
+    D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_typedef ||
+    D.getContext() == Declarator::AliasDeclContext ||
+    D.getContext() == Declarator::AliasTemplateContext;
+
+  // Does T refer to a function type with a cv-qualifier or a ref-qualifier?
+  bool IsQualifiedFunction = T->isFunctionProtoType() &&
+      (T->castAs<FunctionProtoType>()->getTypeQuals() != 0 ||
+       T->castAs<FunctionProtoType>()->getRefQualifier() != RQ_None);
+
+  // Walk the DeclTypeInfo, building the recursive type as we go.
+  // DeclTypeInfos are ordered from the identifier out, which is
+  // opposite of what we want :).
+  for (unsigned i = 0, e = D.getNumTypeObjects(); i != e; ++i) {
+    unsigned chunkIndex = e - i - 1;
+    state.setCurrentChunkIndex(chunkIndex);
+    DeclaratorChunk &DeclType = D.getTypeObject(chunkIndex);
+    if (IsQualifiedFunction) {
+      checkQualifiedFunction(S, T, DeclType);
+      IsQualifiedFunction = DeclType.Kind == DeclaratorChunk::Paren;
+    }
+    switch (DeclType.Kind) {
+    case DeclaratorChunk::Paren:
+      T = S.BuildParenType(T);
+      break;
+    case DeclaratorChunk::BlockPointer:
+      // If blocks are disabled, emit an error.
+      if (!LangOpts.Blocks)
+        S.Diag(DeclType.Loc, diag::err_blocks_disable);
+
+      T = S.BuildBlockPointerType(T, D.getIdentifierLoc(), Name);
+      if (DeclType.Cls.TypeQuals)
+        T = S.BuildQualifiedType(T, DeclType.Loc, DeclType.Cls.TypeQuals);
+      break;
+    case DeclaratorChunk::Pointer:
+      // Verify that we're not building a pointer to pointer to function with
+      // exception specification.
+      if (LangOpts.CPlusPlus && S.CheckDistantExceptionSpec(T)) {
+        S.Diag(D.getIdentifierLoc(), diag::err_distant_exception_spec);
+        D.setInvalidType(true);
+        // Build the type anyway.
+      }
+      if (LangOpts.ObjC1 && T->getAs<ObjCObjectType>()) {
+        T = Context.getObjCObjectPointerType(T);
+        if (DeclType.Ptr.TypeQuals)
+          T = S.BuildQualifiedType(T, DeclType.Loc, DeclType.Ptr.TypeQuals);
+        break;
+      }
+      T = S.BuildPointerType(T, DeclType.Loc, Name);
+      if (DeclType.Ptr.TypeQuals)
+        T = S.BuildQualifiedType(T, DeclType.Loc, DeclType.Ptr.TypeQuals);
+
+      break;
+    case DeclaratorChunk::Reference: {
+      // Verify that we're not building a reference to pointer to function with
+      // exception specification.
+      if (LangOpts.CPlusPlus && S.CheckDistantExceptionSpec(T)) {
+        S.Diag(D.getIdentifierLoc(), diag::err_distant_exception_spec);
+        D.setInvalidType(true);
+        // Build the type anyway.
+      }
+      T = S.BuildReferenceType(T, DeclType.Ref.LValueRef, DeclType.Loc, Name);
+
+      Qualifiers Quals;
+      if (DeclType.Ref.HasRestrict)
+        T = S.BuildQualifiedType(T, DeclType.Loc, Qualifiers::Restrict);
+      break;
+    }
+    case DeclaratorChunk::Array: {
+      // Verify that we're not building an array of pointers to function with
+      // exception specification.
+      if (LangOpts.CPlusPlus && S.CheckDistantExceptionSpec(T)) {
+        S.Diag(D.getIdentifierLoc(), diag::err_distant_exception_spec);
+        D.setInvalidType(true);
+        // Build the type anyway.
+      }
+      DeclaratorChunk::ArrayTypeInfo &ATI = DeclType.Arr;
+      Expr *ArraySize = static_cast<Expr*>(ATI.NumElts);
+      ArrayType::ArraySizeModifier ASM;
+      if (ATI.isStar)
+        ASM = ArrayType::Star;
+      else if (ATI.hasStatic)
+        ASM = ArrayType::Static;
+      else
+        ASM = ArrayType::Normal;
+      if (ASM == ArrayType::Star && !D.isPrototypeContext()) {
+        // FIXME: This check isn't quite right: it allows star in prototypes
+        // for function definitions, and disallows some edge cases detailed
+        // in http://gcc.gnu.org/ml/gcc-patches/2009-02/msg00133.html
+        S.Diag(DeclType.Loc, diag::err_array_star_outside_prototype);
+        ASM = ArrayType::Normal;
+        D.setInvalidType(true);
+      }
+      T = S.BuildArrayType(T, ASM, ArraySize, ATI.TypeQuals,
+                           SourceRange(DeclType.Loc, DeclType.EndLoc), Name);
+      break;
+    }
+    case DeclaratorChunk::Function: {
+      // If the function declarator has a prototype (i.e. it is not () and
+      // does not have a K&R-style identifier list), then the arguments are part
+      // of the type, otherwise the argument list is ().
+      const DeclaratorChunk::FunctionTypeInfo &FTI = DeclType.Fun;
+      IsQualifiedFunction = FTI.TypeQuals || FTI.hasRefQualifier();
+
+      // Check for auto functions and trailing return type and adjust the
+      // return type accordingly.
+      if (!D.isInvalidType()) {
+        // trailing-return-type is only required if we're declaring a function,
+        // and not, for instance, a pointer to a function.
+        if (D.getDeclSpec().getTypeSpecType() == DeclSpec::TST_auto &&
+            !FTI.TrailingReturnType && chunkIndex == 0) {
+          S.Diag(D.getDeclSpec().getTypeSpecTypeLoc(),
+               diag::err_auto_missing_trailing_return);
+          T = Context.IntTy;
+          D.setInvalidType(true);
+        } else if (FTI.TrailingReturnType) {
+          // T must be exactly 'auto' at this point. See CWG issue 681.
+          if (isa<ParenType>(T)) {
+            S.Diag(D.getDeclSpec().getTypeSpecTypeLoc(),
+                 diag::err_trailing_return_in_parens)
+              << T << D.getDeclSpec().getSourceRange();
+            D.setInvalidType(true);
+          } else if (D.getContext() != Declarator::LambdaExprContext &&
+                     (T.hasQualifiers() || !isa<AutoType>(T))) {
+            S.Diag(D.getDeclSpec().getTypeSpecTypeLoc(),
+                 diag::err_trailing_return_without_auto)
+              << T << D.getDeclSpec().getSourceRange();
+            D.setInvalidType(true);
+          }
+
+          T = S.GetTypeFromParser(
+            ParsedType::getFromOpaquePtr(FTI.TrailingReturnType),
+            &TInfo);
+        }
+      }
+
+      // C99 6.7.5.3p1: The return type may not be a function or array type.
+      // For conversion functions, we'll diagnose this particular error later.
+      if ((T->isArrayType() || T->isFunctionType()) &&
+          (D.getName().getKind() != UnqualifiedId::IK_ConversionFunctionId)) {
+        unsigned diagID = diag::err_func_returning_array_function;
+        // Last processing chunk in block context means this function chunk
+        // represents the block.
+        if (chunkIndex == 0 &&
+            D.getContext() == Declarator::BlockLiteralContext)
+          diagID = diag::err_block_returning_array_function;
+        S.Diag(DeclType.Loc, diagID) << T->isFunctionType() << T;
+        T = Context.IntTy;
+        D.setInvalidType(true);
+      }
+
+      // Do not allow returning half FP value.
+      // FIXME: This really should be in BuildFunctionType.
+      if (T->isHalfType()) {
+        S.Diag(D.getIdentifierLoc(),
+             diag::err_parameters_retval_cannot_have_fp16_type) << 1
+          << FixItHint::CreateInsertion(D.getIdentifierLoc(), "*");
+        D.setInvalidType(true);
+      }
+
+      // cv-qualifiers on return types are pointless except when the type is a
+      // class type in C++.
+      if (isa<PointerType>(T) && T.getLocalCVRQualifiers() &&
+          (D.getName().getKind() != UnqualifiedId::IK_ConversionFunctionId) &&
+          (!LangOpts.CPlusPlus || !T->isDependentType())) {
+        assert(chunkIndex + 1 < e && "No DeclaratorChunk for the return type?");
+        DeclaratorChunk ReturnTypeChunk = D.getTypeObject(chunkIndex + 1);
+        assert(ReturnTypeChunk.Kind == DeclaratorChunk::Pointer);
+
+        DeclaratorChunk::PointerTypeInfo &PTI = ReturnTypeChunk.Ptr;
+
+        DiagnoseIgnoredQualifiers(PTI.TypeQuals,
+            SourceLocation::getFromRawEncoding(PTI.ConstQualLoc),
+            SourceLocation::getFromRawEncoding(PTI.VolatileQualLoc),
+            SourceLocation::getFromRawEncoding(PTI.RestrictQualLoc),
+            S);
+
+      } else if (T.getCVRQualifiers() && D.getDeclSpec().getTypeQualifiers() &&
+          (!LangOpts.CPlusPlus ||
+           (!T->isDependentType() && !T->isRecordType()))) {
+
+        DiagnoseIgnoredQualifiers(D.getDeclSpec().getTypeQualifiers(),
+                                  D.getDeclSpec().getConstSpecLoc(),
+                                  D.getDeclSpec().getVolatileSpecLoc(),
+                                  D.getDeclSpec().getRestrictSpecLoc(),
+                                  S);
+      }
+
+      if (LangOpts.CPlusPlus && D.getDeclSpec().isTypeSpecOwned()) {
+        // C++ [dcl.fct]p6:
+        //   Types shall not be defined in return or parameter types.
+        TagDecl *Tag = cast<TagDecl>(D.getDeclSpec().getRepAsDecl());
+        if (Tag->isCompleteDefinition())
+          S.Diag(Tag->getLocation(), diag::err_type_defined_in_result_type)
+            << Context.getTypeDeclType(Tag);
+      }
+
+      // Exception specs are not allowed in typedefs. Complain, but add it
+      // anyway.
+      if (IsTypedefName && FTI.getExceptionSpecType())
+        S.Diag(FTI.getExceptionSpecLoc(), diag::err_exception_spec_in_typedef)
+          << (D.getContext() == Declarator::AliasDeclContext ||
+              D.getContext() == Declarator::AliasTemplateContext);
+
+      if (!FTI.NumArgs && !FTI.isVariadic && !LangOpts.CPlusPlus) {
+        // Simple void foo(), where the incoming T is the result type.
+        T = Context.getFunctionNoProtoType(T);
+      } else {
+        // We allow a zero-parameter variadic function in C if the
+        // function is marked with the "overloadable" attribute. Scan
+        // for this attribute now.
+        if (!FTI.NumArgs && FTI.isVariadic && !LangOpts.CPlusPlus) {
+          bool Overloadable = false;
+          for (const AttributeList *Attrs = D.getAttributes();
+               Attrs; Attrs = Attrs->getNext()) {
+            if (Attrs->getKind() == AttributeList::AT_overloadable) {
+              Overloadable = true;
+              break;
+            }
+          }
+
+          if (!Overloadable)
+            S.Diag(FTI.getEllipsisLoc(), diag::err_ellipsis_first_arg);
+        }
+
+        if (FTI.NumArgs && FTI.ArgInfo[0].Param == 0) {
+          // C99 6.7.5.3p3: Reject int(x,y,z) when it's not a function
+          // definition.
+          S.Diag(FTI.ArgInfo[0].IdentLoc, diag::err_ident_list_in_fn_declaration);
+          D.setInvalidType(true);
+          break;
+        }
+
+        FunctionProtoType::ExtProtoInfo EPI;
+        EPI.Variadic = FTI.isVariadic;
+        EPI.HasTrailingReturn = FTI.TrailingReturnType;
+        EPI.TypeQuals = FTI.TypeQuals;
+        EPI.RefQualifier = !FTI.hasRefQualifier()? RQ_None
+                    : FTI.RefQualifierIsLValueRef? RQ_LValue
+                    : RQ_RValue;
+        
+        // Otherwise, we have a function with an argument list that is
+        // potentially variadic.
+        SmallVector<QualType, 16> ArgTys;
+        ArgTys.reserve(FTI.NumArgs);
+
+        SmallVector<bool, 16> ConsumedArguments;
+        ConsumedArguments.reserve(FTI.NumArgs);
+        bool HasAnyConsumedArguments = false;
+
+        for (unsigned i = 0, e = FTI.NumArgs; i != e; ++i) {
+          ParmVarDecl *Param = cast<ParmVarDecl>(FTI.ArgInfo[i].Param);
+          QualType ArgTy = Param->getType();
+          assert(!ArgTy.isNull() && "Couldn't parse type?");
+
+          // Adjust the parameter type.
+          assert((ArgTy == Context.getAdjustedParameterType(ArgTy)) && 
+                 "Unadjusted type?");
+
+          // Look for 'void'.  void is allowed only as a single argument to a
+          // function with no other parameters (C99 6.7.5.3p10).  We record
+          // int(void) as a FunctionProtoType with an empty argument list.
+          if (ArgTy->isVoidType()) {
+            // If this is something like 'float(int, void)', reject it.  'void'
+            // is an incomplete type (C99 6.2.5p19) and function decls cannot
+            // have arguments of incomplete type.
+            if (FTI.NumArgs != 1 || FTI.isVariadic) {
+              S.Diag(DeclType.Loc, diag::err_void_only_param);
+              ArgTy = Context.IntTy;
+              Param->setType(ArgTy);
+            } else if (FTI.ArgInfo[i].Ident) {
+              // Reject, but continue to parse 'int(void abc)'.
+              S.Diag(FTI.ArgInfo[i].IdentLoc,
+                   diag::err_param_with_void_type);
+              ArgTy = Context.IntTy;
+              Param->setType(ArgTy);
+            } else {
+              // Reject, but continue to parse 'float(const void)'.
+              if (ArgTy.hasQualifiers())
+                S.Diag(DeclType.Loc, diag::err_void_param_qualified);
+
+              // Do not add 'void' to the ArgTys list.
+              break;
+            }
+          } else if (ArgTy->isHalfType()) {
+            // Disallow half FP arguments.
+            // FIXME: This really should be in BuildFunctionType.
+            S.Diag(Param->getLocation(),
+               diag::err_parameters_retval_cannot_have_fp16_type) << 0
+            << FixItHint::CreateInsertion(Param->getLocation(), "*");
+            D.setInvalidType();
+          } else if (!FTI.hasPrototype) {
+            if (ArgTy->isPromotableIntegerType()) {
+              ArgTy = Context.getPromotedIntegerType(ArgTy);
+              Param->setKNRPromoted(true);
+            } else if (const BuiltinType* BTy = ArgTy->getAs<BuiltinType>()) {
+              if (BTy->getKind() == BuiltinType::Float) {
+                ArgTy = Context.DoubleTy;
+                Param->setKNRPromoted(true);
+              }
+            }
+          }
+
+          if (LangOpts.ObjCAutoRefCount) {
+            bool Consumed = Param->hasAttr<NSConsumedAttr>();
+            ConsumedArguments.push_back(Consumed);
+            HasAnyConsumedArguments |= Consumed;
+          }
+
+          ArgTys.push_back(ArgTy);
+        }
+
+        if (HasAnyConsumedArguments)
+          EPI.ConsumedArguments = ConsumedArguments.data();
+
+        SmallVector<QualType, 4> Exceptions;
+        SmallVector<ParsedType, 2> DynamicExceptions;
+        SmallVector<SourceRange, 2> DynamicExceptionRanges;
+        Expr *NoexceptExpr = 0;
+        
+        if (FTI.getExceptionSpecType() == EST_Dynamic) {
+          // FIXME: It's rather inefficient to have to split into two vectors
+          // here.
+          unsigned N = FTI.NumExceptions;
+          DynamicExceptions.reserve(N);
+          DynamicExceptionRanges.reserve(N);
+          for (unsigned I = 0; I != N; ++I) {
+            DynamicExceptions.push_back(FTI.Exceptions[I].Ty);
+            DynamicExceptionRanges.push_back(FTI.Exceptions[I].Range);
+          }
+        } else if (FTI.getExceptionSpecType() == EST_ComputedNoexcept) {
+          NoexceptExpr = FTI.NoexceptExpr;
+        }
+              
+        S.checkExceptionSpecification(FTI.getExceptionSpecType(),
+                                      DynamicExceptions,
+                                      DynamicExceptionRanges,
+                                      NoexceptExpr,
+                                      Exceptions,
+                                      EPI);
+        
+        if (FTI.getExceptionSpecType() == EST_None &&
+            ImplicitlyNoexcept && chunkIndex == 0) {
+          // Only the outermost chunk is marked noexcept, of course.
+          EPI.ExceptionSpecType = EST_BasicNoexcept;
+        }
+
+        T = Context.getFunctionType(T, ArgTys.data(), ArgTys.size(), EPI);
+      }
+
+      break;
+    }
+    case DeclaratorChunk::MemberPointer:
+      // The scope spec must refer to a class, or be dependent.
+      CXXScopeSpec &SS = DeclType.Mem.Scope();
+      QualType ClsType;
+      if (SS.isInvalid()) {
+        // Avoid emitting extra errors if we already errored on the scope.
+        D.setInvalidType(true);
+      } else if (S.isDependentScopeSpecifier(SS) ||
+                 dyn_cast_or_null<CXXRecordDecl>(S.computeDeclContext(SS))) {
+        NestedNameSpecifier *NNS
+          = static_cast<NestedNameSpecifier*>(SS.getScopeRep());
+        NestedNameSpecifier *NNSPrefix = NNS->getPrefix();
+        switch (NNS->getKind()) {
+        case NestedNameSpecifier::Identifier:
+          ClsType = Context.getDependentNameType(ETK_None, NNSPrefix,
+                                                 NNS->getAsIdentifier());
+          break;
+
+        case NestedNameSpecifier::Namespace:
+        case NestedNameSpecifier::NamespaceAlias:
+        case NestedNameSpecifier::Global:
+          llvm_unreachable("Nested-name-specifier must name a type");
+
+        case NestedNameSpecifier::TypeSpec:
+        case NestedNameSpecifier::TypeSpecWithTemplate:
+          ClsType = QualType(NNS->getAsType(), 0);
+          // Note: if the NNS has a prefix and ClsType is a nondependent
+          // TemplateSpecializationType, then the NNS prefix is NOT included
+          // in ClsType; hence we wrap ClsType into an ElaboratedType.
+          // NOTE: in particular, no wrap occurs if ClsType already is an
+          // Elaborated, DependentName, or DependentTemplateSpecialization.
+          if (NNSPrefix && isa<TemplateSpecializationType>(NNS->getAsType()))
+            ClsType = Context.getElaboratedType(ETK_None, NNSPrefix, ClsType);
+          break;
+        }
+      } else {
+        S.Diag(DeclType.Mem.Scope().getBeginLoc(),
+             diag::err_illegal_decl_mempointer_in_nonclass)
+          << (D.getIdentifier() ? D.getIdentifier()->getName() : "type name")
+          << DeclType.Mem.Scope().getRange();
+        D.setInvalidType(true);
+      }
+
+      if (!ClsType.isNull())
+        T = S.BuildMemberPointerType(T, ClsType, DeclType.Loc, D.getIdentifier());
+      if (T.isNull()) {
+        T = Context.IntTy;
+        D.setInvalidType(true);
+      } else if (DeclType.Mem.TypeQuals) {
+        T = S.BuildQualifiedType(T, DeclType.Loc, DeclType.Mem.TypeQuals);
+      }
+      break;
+    }
+
+    if (T.isNull()) {
+      D.setInvalidType(true);
+      T = Context.IntTy;
+    }
+
+    // See if there are any attributes on this declarator chunk.
+    if (AttributeList *attrs = const_cast<AttributeList*>(DeclType.getAttrs()))
+      processTypeAttrs(state, T, false, attrs);
+  }
+
+  if (LangOpts.CPlusPlus && T->isFunctionType()) {
+    const FunctionProtoType *FnTy = T->getAs<FunctionProtoType>();
+    assert(FnTy && "Why oh why is there not a FunctionProtoType here?");
+
+    // C++ 8.3.5p4: 
+    //   A cv-qualifier-seq shall only be part of the function type
+    //   for a nonstatic member function, the function type to which a pointer
+    //   to member refers, or the top-level function type of a function typedef
+    //   declaration.
+    //
+    // Core issue 547 also allows cv-qualifiers on function types that are
+    // top-level template type arguments.
+    bool FreeFunction;
+    if (!D.getCXXScopeSpec().isSet()) {
+      FreeFunction = ((D.getContext() != Declarator::MemberContext &&
+                       D.getContext() != Declarator::LambdaExprContext) ||
+                      D.getDeclSpec().isFriendSpecified());
+    } else {
+      DeclContext *DC = S.computeDeclContext(D.getCXXScopeSpec());
+      FreeFunction = (DC && !DC->isRecord());
+    }
+
+    // C++0x [dcl.constexpr]p8: A constexpr specifier for a non-static member
+    // function that is not a constructor declares that function to be const.
+    if (D.getDeclSpec().isConstexprSpecified() && !FreeFunction &&
+        D.getDeclSpec().getStorageClassSpec() != DeclSpec::SCS_static &&
+        D.getName().getKind() != UnqualifiedId::IK_ConstructorName &&
+        D.getName().getKind() != UnqualifiedId::IK_ConstructorTemplateId &&
+        !(FnTy->getTypeQuals() & DeclSpec::TQ_const)) {
+      // Rebuild function type adding a 'const' qualifier.
+      FunctionProtoType::ExtProtoInfo EPI = FnTy->getExtProtoInfo();
+      EPI.TypeQuals |= DeclSpec::TQ_const;
+      T = Context.getFunctionType(FnTy->getResultType(), 
+                                  FnTy->arg_type_begin(),
+                                  FnTy->getNumArgs(), EPI);
+    }
+
+    // C++11 [dcl.fct]p6 (w/DR1417):
+    // An attempt to specify a function type with a cv-qualifier-seq or a
+    // ref-qualifier (including by typedef-name) is ill-formed unless it is:
+    //  - the function type for a non-static member function,
+    //  - the function type to which a pointer to member refers,
+    //  - the top-level function type of a function typedef declaration or
+    //    alias-declaration,
+    //  - the type-id in the default argument of a type-parameter, or
+    //  - the type-id of a template-argument for a type-parameter
+    if (IsQualifiedFunction &&
+        !(!FreeFunction &&
+          D.getDeclSpec().getStorageClassSpec() != DeclSpec::SCS_static) &&
+        !IsTypedefName &&
+        D.getContext() != Declarator::TemplateTypeArgContext) {
+      SourceLocation Loc = D.getLocStart();
+      SourceRange RemovalRange;
+      unsigned I;
+      if (D.isFunctionDeclarator(I)) {
+        SmallVector<SourceLocation, 4> RemovalLocs;
+        const DeclaratorChunk &Chunk = D.getTypeObject(I);
+        assert(Chunk.Kind == DeclaratorChunk::Function);
+        if (Chunk.Fun.hasRefQualifier())
+          RemovalLocs.push_back(Chunk.Fun.getRefQualifierLoc());
+        if (Chunk.Fun.TypeQuals & Qualifiers::Const)
+          RemovalLocs.push_back(Chunk.Fun.getConstQualifierLoc());
+        if (Chunk.Fun.TypeQuals & Qualifiers::Volatile)
+          RemovalLocs.push_back(Chunk.Fun.getVolatileQualifierLoc());
+        // FIXME: We do not track the location of the __restrict qualifier.
+        //if (Chunk.Fun.TypeQuals & Qualifiers::Restrict)
+        //  RemovalLocs.push_back(Chunk.Fun.getRestrictQualifierLoc());
+        if (!RemovalLocs.empty()) {
+          std::sort(RemovalLocs.begin(), RemovalLocs.end(),
+                    SourceManager::LocBeforeThanCompare(S.getSourceManager()));
+          RemovalRange = SourceRange(RemovalLocs.front(), RemovalLocs.back());
+          Loc = RemovalLocs.front();
+        }
+      }
+
+      S.Diag(Loc, diag::err_invalid_qualified_function_type)
+        << FreeFunction << D.isFunctionDeclarator() << T
+        << getFunctionQualifiersAsString(FnTy)
+        << FixItHint::CreateRemoval(RemovalRange);
+
+      // Strip the cv-qualifiers and ref-qualifiers from the type.
+      FunctionProtoType::ExtProtoInfo EPI = FnTy->getExtProtoInfo();
+      EPI.TypeQuals = 0;
+      EPI.RefQualifier = RQ_None;
+
+      T = Context.getFunctionType(FnTy->getResultType(), 
+                                  FnTy->arg_type_begin(),
+                                  FnTy->getNumArgs(), EPI);
+    }
+  }
+
+  // Apply any undistributed attributes from the declarator.
+  if (!T.isNull())
+    if (AttributeList *attrs = D.getAttributes())
+      processTypeAttrs(state, T, false, attrs);
+
+  // Diagnose any ignored type attributes.
+  if (!T.isNull()) state.diagnoseIgnoredTypeAttrs(T);
+
+  // C++0x [dcl.constexpr]p9:
+  //  A constexpr specifier used in an object declaration declares the object
+  //  as const. 
+  if (D.getDeclSpec().isConstexprSpecified() && T->isObjectType()) {
+    T.addConst();
+  }
+
+  // If there was an ellipsis in the declarator, the declaration declares a 
+  // parameter pack whose type may be a pack expansion type.
+  if (D.hasEllipsis() && !T.isNull()) {
+    // C++0x [dcl.fct]p13:
+    //   A declarator-id or abstract-declarator containing an ellipsis shall 
+    //   only be used in a parameter-declaration. Such a parameter-declaration
+    //   is a parameter pack (14.5.3). [...]
+    switch (D.getContext()) {
+    case Declarator::PrototypeContext:
+      // C++0x [dcl.fct]p13:
+      //   [...] When it is part of a parameter-declaration-clause, the 
+      //   parameter pack is a function parameter pack (14.5.3). The type T 
+      //   of the declarator-id of the function parameter pack shall contain
+      //   a template parameter pack; each template parameter pack in T is 
+      //   expanded by the function parameter pack.
+      //
+      // We represent function parameter packs as function parameters whose
+      // type is a pack expansion.
+      if (!T->containsUnexpandedParameterPack()) {
+        S.Diag(D.getEllipsisLoc(), 
+             diag::err_function_parameter_pack_without_parameter_packs)
+          << T <<  D.getSourceRange();
+        D.setEllipsisLoc(SourceLocation());
+      } else {
+        T = Context.getPackExpansionType(T, llvm::Optional<unsigned>());
+      }
+      break;
+        
+    case Declarator::TemplateParamContext:
+      // C++0x [temp.param]p15:
+      //   If a template-parameter is a [...] is a parameter-declaration that 
+      //   declares a parameter pack (8.3.5), then the template-parameter is a
+      //   template parameter pack (14.5.3).
+      //
+      // Note: core issue 778 clarifies that, if there are any unexpanded
+      // parameter packs in the type of the non-type template parameter, then
+      // it expands those parameter packs.
+      if (T->containsUnexpandedParameterPack())
+        T = Context.getPackExpansionType(T, llvm::Optional<unsigned>());
+      else
+        S.Diag(D.getEllipsisLoc(),
+               LangOpts.CPlusPlus0x
+                 ? diag::warn_cxx98_compat_variadic_templates
+                 : diag::ext_variadic_templates);
+      break;
+    
+    case Declarator::FileContext:
+    case Declarator::KNRTypeListContext:
+    case Declarator::ObjCParameterContext:  // FIXME: special diagnostic here?
+    case Declarator::ObjCResultContext:     // FIXME: special diagnostic here?
+    case Declarator::TypeNameContext:
+    case Declarator::CXXNewContext:
+    case Declarator::AliasDeclContext:
+    case Declarator::AliasTemplateContext:
+    case Declarator::MemberContext:
+    case Declarator::BlockContext:
+    case Declarator::ForContext:
+    case Declarator::ConditionContext:
+    case Declarator::CXXCatchContext:
+    case Declarator::ObjCCatchContext:
+    case Declarator::BlockLiteralContext:
+    case Declarator::LambdaExprContext:
+    case Declarator::TrailingReturnContext:
+    case Declarator::TemplateTypeArgContext:
+      // FIXME: We may want to allow parameter packs in block-literal contexts
+      // in the future.
+      S.Diag(D.getEllipsisLoc(), diag::err_ellipsis_in_declarator_not_parameter);
+      D.setEllipsisLoc(SourceLocation());
+      break;
+    }
+  }
+
+  if (T.isNull())
+    return Context.getNullTypeSourceInfo();
+  else if (D.isInvalidType())
+    return Context.getTrivialTypeSourceInfo(T);
+
+  return S.GetTypeSourceInfoForDeclarator(D, T, TInfo);
+}
+
+/// GetTypeForDeclarator - Convert the type for the specified
+/// declarator to Type instances.
+///
+/// The result of this call will never be null, but the associated
+/// type may be a null type if there's an unrecoverable error.
+TypeSourceInfo *Sema::GetTypeForDeclarator(Declarator &D, Scope *S) {
+  // Determine the type of the declarator. Not all forms of declarator
+  // have a type.
+
+  TypeProcessingState state(*this, D);
+
+  TypeSourceInfo *ReturnTypeInfo = 0;
+  QualType T = GetDeclSpecTypeForDeclarator(state, ReturnTypeInfo);
+  if (T.isNull())
+    return Context.getNullTypeSourceInfo();
+
+  if (D.isPrototypeContext() && getLangOpts().ObjCAutoRefCount)
+    inferARCWriteback(state, T);
+  
+  return GetFullTypeForDeclarator(state, T, ReturnTypeInfo);
+}
+
+static void transferARCOwnershipToDeclSpec(Sema &S,
+                                           QualType &declSpecTy,
+                                           Qualifiers::ObjCLifetime ownership) {
+  if (declSpecTy->isObjCRetainableType() &&
+      declSpecTy.getObjCLifetime() == Qualifiers::OCL_None) {
+    Qualifiers qs;
+    qs.addObjCLifetime(ownership);
+    declSpecTy = S.Context.getQualifiedType(declSpecTy, qs);
+  }
+}
+
+static void transferARCOwnershipToDeclaratorChunk(TypeProcessingState &state,
+                                            Qualifiers::ObjCLifetime ownership,
+                                            unsigned chunkIndex) {
+  Sema &S = state.getSema();
+  Declarator &D = state.getDeclarator();
+
+  // Look for an explicit lifetime attribute.
+  DeclaratorChunk &chunk = D.getTypeObject(chunkIndex);
+  for (const AttributeList *attr = chunk.getAttrs(); attr;
+         attr = attr->getNext())
+    if (attr->getKind() == AttributeList::AT_objc_ownership)
+      return;
+
+  const char *attrStr = 0;
+  switch (ownership) {
+  case Qualifiers::OCL_None: llvm_unreachable("no ownership!");
+  case Qualifiers::OCL_ExplicitNone: attrStr = "none"; break;
+  case Qualifiers::OCL_Strong: attrStr = "strong"; break;
+  case Qualifiers::OCL_Weak: attrStr = "weak"; break;
+  case Qualifiers::OCL_Autoreleasing: attrStr = "autoreleasing"; break;
+  }
+
+  // If there wasn't one, add one (with an invalid source location
+  // so that we don't make an AttributedType for it).
+  AttributeList *attr = D.getAttributePool()
+    .create(&S.Context.Idents.get("objc_ownership"), SourceLocation(),
+            /*scope*/ 0, SourceLocation(),
+            &S.Context.Idents.get(attrStr), SourceLocation(),
+            /*args*/ 0, 0,
+            /*declspec*/ false, /*C++0x*/ false);
+  spliceAttrIntoList(*attr, chunk.getAttrListRef());
+
+  // TODO: mark whether we did this inference?
+}
+
+/// \brief Used for transfering ownership in casts resulting in l-values.
+static void transferARCOwnership(TypeProcessingState &state,
+                                 QualType &declSpecTy,
+                                 Qualifiers::ObjCLifetime ownership) {
+  Sema &S = state.getSema();
+  Declarator &D = state.getDeclarator();
+
+  int inner = -1;
+  bool hasIndirection = false;
+  for (unsigned i = 0, e = D.getNumTypeObjects(); i != e; ++i) {
+    DeclaratorChunk &chunk = D.getTypeObject(i);
+    switch (chunk.Kind) {
+    case DeclaratorChunk::Paren:
+      // Ignore parens.
+      break;
+
+    case DeclaratorChunk::Array:
+    case DeclaratorChunk::Reference:
+    case DeclaratorChunk::Pointer:
+      if (inner != -1)
+        hasIndirection = true;
+      inner = i;
+      break;
+
+    case DeclaratorChunk::BlockPointer:
+      if (inner != -1)
+        transferARCOwnershipToDeclaratorChunk(state, ownership, i);
+      return;
+
+    case DeclaratorChunk::Function:
+    case DeclaratorChunk::MemberPointer:
+      return;
+    }
+  }
+
+  if (inner == -1)
+    return;
+
+  DeclaratorChunk &chunk = D.getTypeObject(inner); 
+  if (chunk.Kind == DeclaratorChunk::Pointer) {
+    if (declSpecTy->isObjCRetainableType())
+      return transferARCOwnershipToDeclSpec(S, declSpecTy, ownership);
+    if (declSpecTy->isObjCObjectType() && hasIndirection)
+      return transferARCOwnershipToDeclaratorChunk(state, ownership, inner);
+  } else {
+    assert(chunk.Kind == DeclaratorChunk::Array ||
+           chunk.Kind == DeclaratorChunk::Reference);
+    return transferARCOwnershipToDeclSpec(S, declSpecTy, ownership);
+  }
+}
+
+TypeSourceInfo *Sema::GetTypeForDeclaratorCast(Declarator &D, QualType FromTy) {
+  TypeProcessingState state(*this, D);
+
+  TypeSourceInfo *ReturnTypeInfo = 0;
+  QualType declSpecTy = GetDeclSpecTypeForDeclarator(state, ReturnTypeInfo);
+  if (declSpecTy.isNull())
+    return Context.getNullTypeSourceInfo();
+
+  if (getLangOpts().ObjCAutoRefCount) {
+    Qualifiers::ObjCLifetime ownership = Context.getInnerObjCOwnership(FromTy);
+    if (ownership != Qualifiers::OCL_None)
+      transferARCOwnership(state, declSpecTy, ownership);
+  }
+
+  return GetFullTypeForDeclarator(state, declSpecTy, ReturnTypeInfo);
+}
+
+/// Map an AttributedType::Kind to an AttributeList::Kind.
+static AttributeList::Kind getAttrListKind(AttributedType::Kind kind) {
+  switch (kind) {
+  case AttributedType::attr_address_space:
+    return AttributeList::AT_address_space;
+  case AttributedType::attr_regparm:
+    return AttributeList::AT_regparm;
+  case AttributedType::attr_vector_size:
+    return AttributeList::AT_vector_size;
+  case AttributedType::attr_neon_vector_type:
+    return AttributeList::AT_neon_vector_type;
+  case AttributedType::attr_neon_polyvector_type:
+    return AttributeList::AT_neon_polyvector_type;
+  case AttributedType::attr_objc_gc:
+    return AttributeList::AT_objc_gc;
+  case AttributedType::attr_objc_ownership:
+    return AttributeList::AT_objc_ownership;
+  case AttributedType::attr_noreturn:
+    return AttributeList::AT_noreturn;
+  case AttributedType::attr_cdecl:
+    return AttributeList::AT_cdecl;
+  case AttributedType::attr_fastcall:
+    return AttributeList::AT_fastcall;
+  case AttributedType::attr_stdcall:
+    return AttributeList::AT_stdcall;
+  case AttributedType::attr_thiscall:
+    return AttributeList::AT_thiscall;
+  case AttributedType::attr_pascal:
+    return AttributeList::AT_pascal;
+  case AttributedType::attr_pcs:
+    return AttributeList::AT_pcs;
+  }
+  llvm_unreachable("unexpected attribute kind!");
+}
+
+static void fillAttributedTypeLoc(AttributedTypeLoc TL,
+                                  const AttributeList *attrs) {
+  AttributedType::Kind kind = TL.getAttrKind();
+
+  assert(attrs && "no type attributes in the expected location!");
+  AttributeList::Kind parsedKind = getAttrListKind(kind);
+  while (attrs->getKind() != parsedKind) {
+    attrs = attrs->getNext();
+    assert(attrs && "no matching attribute in expected location!");
+  }
+
+  TL.setAttrNameLoc(attrs->getLoc());
+  if (TL.hasAttrExprOperand())
+    TL.setAttrExprOperand(attrs->getArg(0));
+  else if (TL.hasAttrEnumOperand())
+    TL.setAttrEnumOperandLoc(attrs->getParameterLoc());
+
+  // FIXME: preserve this information to here.
+  if (TL.hasAttrOperand())
+    TL.setAttrOperandParensRange(SourceRange());
+}
+
+namespace {
+  class TypeSpecLocFiller : public TypeLocVisitor<TypeSpecLocFiller> {
+    ASTContext &Context;
+    const DeclSpec &DS;
+
+  public:
+    TypeSpecLocFiller(ASTContext &Context, const DeclSpec &DS) 
+      : Context(Context), DS(DS) {}
+
+    void VisitAttributedTypeLoc(AttributedTypeLoc TL) {
+      fillAttributedTypeLoc(TL, DS.getAttributes().getList());
+      Visit(TL.getModifiedLoc());
+    }
+    void VisitQualifiedTypeLoc(QualifiedTypeLoc TL) {
+      Visit(TL.getUnqualifiedLoc());
+    }
+    void VisitTypedefTypeLoc(TypedefTypeLoc TL) {
+      TL.setNameLoc(DS.getTypeSpecTypeLoc());
+    }
+    void VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc TL) {
+      TL.setNameLoc(DS.getTypeSpecTypeLoc());
+    }
+    void VisitObjCObjectTypeLoc(ObjCObjectTypeLoc TL) {
+      // Handle the base type, which might not have been written explicitly.
+      if (DS.getTypeSpecType() == DeclSpec::TST_unspecified) {
+        TL.setHasBaseTypeAsWritten(false);
+        TL.getBaseLoc().initialize(Context, SourceLocation());
+      } else {
+        TL.setHasBaseTypeAsWritten(true);
+        Visit(TL.getBaseLoc());
+      }
+
+      // Protocol qualifiers.
+      if (DS.getProtocolQualifiers()) {
+        assert(TL.getNumProtocols() > 0);
+        assert(TL.getNumProtocols() == DS.getNumProtocolQualifiers());
+        TL.setLAngleLoc(DS.getProtocolLAngleLoc());
+        TL.setRAngleLoc(DS.getSourceRange().getEnd());
+        for (unsigned i = 0, e = DS.getNumProtocolQualifiers(); i != e; ++i)
+          TL.setProtocolLoc(i, DS.getProtocolLocs()[i]);
+      } else {
+        assert(TL.getNumProtocols() == 0);
+        TL.setLAngleLoc(SourceLocation());
+        TL.setRAngleLoc(SourceLocation());
+      }
+    }
+    void VisitObjCObjectPointerTypeLoc(ObjCObjectPointerTypeLoc TL) {
+      TL.setStarLoc(SourceLocation());
+      Visit(TL.getPointeeLoc());
+    }
+    void VisitTemplateSpecializationTypeLoc(TemplateSpecializationTypeLoc TL) {
+      TypeSourceInfo *TInfo = 0;
+      Sema::GetTypeFromParser(DS.getRepAsType(), &TInfo);
+
+      // If we got no declarator info from previous Sema routines,
+      // just fill with the typespec loc.
+      if (!TInfo) {
+        TL.initialize(Context, DS.getTypeSpecTypeNameLoc());
+        return;
+      }
+
+      TypeLoc OldTL = TInfo->getTypeLoc();
+      if (TInfo->getType()->getAs<ElaboratedType>()) {
+        ElaboratedTypeLoc ElabTL = cast<ElaboratedTypeLoc>(OldTL);
+        TemplateSpecializationTypeLoc NamedTL =
+          cast<TemplateSpecializationTypeLoc>(ElabTL.getNamedTypeLoc());
+        TL.copy(NamedTL);
+      }
+      else
+        TL.copy(cast<TemplateSpecializationTypeLoc>(OldTL));
+    }
+    void VisitTypeOfExprTypeLoc(TypeOfExprTypeLoc TL) {
+      assert(DS.getTypeSpecType() == DeclSpec::TST_typeofExpr);
+      TL.setTypeofLoc(DS.getTypeSpecTypeLoc());
+      TL.setParensRange(DS.getTypeofParensRange());
+    }
+    void VisitTypeOfTypeLoc(TypeOfTypeLoc TL) {
+      assert(DS.getTypeSpecType() == DeclSpec::TST_typeofType);
+      TL.setTypeofLoc(DS.getTypeSpecTypeLoc());
+      TL.setParensRange(DS.getTypeofParensRange());
+      assert(DS.getRepAsType());
+      TypeSourceInfo *TInfo = 0;
+      Sema::GetTypeFromParser(DS.getRepAsType(), &TInfo);
+      TL.setUnderlyingTInfo(TInfo);
+    }
+    void VisitUnaryTransformTypeLoc(UnaryTransformTypeLoc TL) {
+      // FIXME: This holds only because we only have one unary transform.
+      assert(DS.getTypeSpecType() == DeclSpec::TST_underlyingType);
+      TL.setKWLoc(DS.getTypeSpecTypeLoc());
+      TL.setParensRange(DS.getTypeofParensRange());
+      assert(DS.getRepAsType());
+      TypeSourceInfo *TInfo = 0;
+      Sema::GetTypeFromParser(DS.getRepAsType(), &TInfo);
+      TL.setUnderlyingTInfo(TInfo);
+    }
+    void VisitBuiltinTypeLoc(BuiltinTypeLoc TL) {
+      // By default, use the source location of the type specifier.
+      TL.setBuiltinLoc(DS.getTypeSpecTypeLoc());
+      if (TL.needsExtraLocalData()) {
+        // Set info for the written builtin specifiers.
+        TL.getWrittenBuiltinSpecs() = DS.getWrittenBuiltinSpecs();
+        // Try to have a meaningful source location.
+        if (TL.getWrittenSignSpec() != TSS_unspecified)
+          // Sign spec loc overrides the others (e.g., 'unsigned long').
+          TL.setBuiltinLoc(DS.getTypeSpecSignLoc());
+        else if (TL.getWrittenWidthSpec() != TSW_unspecified)
+          // Width spec loc overrides type spec loc (e.g., 'short int').
+          TL.setBuiltinLoc(DS.getTypeSpecWidthLoc());
+      }
+    }
+    void VisitElaboratedTypeLoc(ElaboratedTypeLoc TL) {
+      ElaboratedTypeKeyword Keyword
+        = TypeWithKeyword::getKeywordForTypeSpec(DS.getTypeSpecType());
+      if (DS.getTypeSpecType() == TST_typename) {
+        TypeSourceInfo *TInfo = 0;
+        Sema::GetTypeFromParser(DS.getRepAsType(), &TInfo);
+        if (TInfo) {
+          TL.copy(cast<ElaboratedTypeLoc>(TInfo->getTypeLoc()));
+          return;
+        }
+      }
+      TL.setElaboratedKeywordLoc(Keyword != ETK_None
+                                 ? DS.getTypeSpecTypeLoc()
+                                 : SourceLocation());
+      const CXXScopeSpec& SS = DS.getTypeSpecScope();
+      TL.setQualifierLoc(SS.getWithLocInContext(Context));
+      Visit(TL.getNextTypeLoc().getUnqualifiedLoc());
+    }
+    void VisitDependentNameTypeLoc(DependentNameTypeLoc TL) {
+      assert(DS.getTypeSpecType() == TST_typename);
+      TypeSourceInfo *TInfo = 0;
+      Sema::GetTypeFromParser(DS.getRepAsType(), &TInfo);
+      assert(TInfo);
+      TL.copy(cast<DependentNameTypeLoc>(TInfo->getTypeLoc()));
+    }
+    void VisitDependentTemplateSpecializationTypeLoc(
+                                 DependentTemplateSpecializationTypeLoc TL) {
+      assert(DS.getTypeSpecType() == TST_typename);
+      TypeSourceInfo *TInfo = 0;
+      Sema::GetTypeFromParser(DS.getRepAsType(), &TInfo);
+      assert(TInfo);
+      TL.copy(cast<DependentTemplateSpecializationTypeLoc>(
+                TInfo->getTypeLoc()));
+    }
+    void VisitTagTypeLoc(TagTypeLoc TL) {
+      TL.setNameLoc(DS.getTypeSpecTypeNameLoc());
+    }
+    void VisitAtomicTypeLoc(AtomicTypeLoc TL) {
+      TL.setKWLoc(DS.getTypeSpecTypeLoc());
+      TL.setParensRange(DS.getTypeofParensRange());
+      
+      TypeSourceInfo *TInfo = 0;
+      Sema::GetTypeFromParser(DS.getRepAsType(), &TInfo);
+      TL.getValueLoc().initializeFullCopy(TInfo->getTypeLoc());
+    }
+
+    void VisitTypeLoc(TypeLoc TL) {
+      // FIXME: add other typespec types and change this to an assert.
+      TL.initialize(Context, DS.getTypeSpecTypeLoc());
+    }
+  };
+
+  class DeclaratorLocFiller : public TypeLocVisitor<DeclaratorLocFiller> {
+    ASTContext &Context;
+    const DeclaratorChunk &Chunk;
+
+  public:
+    DeclaratorLocFiller(ASTContext &Context, const DeclaratorChunk &Chunk)
+      : Context(Context), Chunk(Chunk) {}
+
+    void VisitQualifiedTypeLoc(QualifiedTypeLoc TL) {
+      llvm_unreachable("qualified type locs not expected here!");
+    }
+
+    void VisitAttributedTypeLoc(AttributedTypeLoc TL) {
+      fillAttributedTypeLoc(TL, Chunk.getAttrs());
+    }
+    void VisitBlockPointerTypeLoc(BlockPointerTypeLoc TL) {
+      assert(Chunk.Kind == DeclaratorChunk::BlockPointer);
+      TL.setCaretLoc(Chunk.Loc);
+    }
+    void VisitPointerTypeLoc(PointerTypeLoc TL) {
+      assert(Chunk.Kind == DeclaratorChunk::Pointer);
+      TL.setStarLoc(Chunk.Loc);
+    }
+    void VisitObjCObjectPointerTypeLoc(ObjCObjectPointerTypeLoc TL) {
+      assert(Chunk.Kind == DeclaratorChunk::Pointer);
+      TL.setStarLoc(Chunk.Loc);
+    }
+    void VisitMemberPointerTypeLoc(MemberPointerTypeLoc TL) {
+      assert(Chunk.Kind == DeclaratorChunk::MemberPointer);
+      const CXXScopeSpec& SS = Chunk.Mem.Scope();
+      NestedNameSpecifierLoc NNSLoc = SS.getWithLocInContext(Context);
+
+      const Type* ClsTy = TL.getClass();
+      QualType ClsQT = QualType(ClsTy, 0);
+      TypeSourceInfo *ClsTInfo = Context.CreateTypeSourceInfo(ClsQT, 0);
+      // Now copy source location info into the type loc component.
+      TypeLoc ClsTL = ClsTInfo->getTypeLoc();
+      switch (NNSLoc.getNestedNameSpecifier()->getKind()) {
+      case NestedNameSpecifier::Identifier:
+        assert(isa<DependentNameType>(ClsTy) && "Unexpected TypeLoc");
+        {
+          DependentNameTypeLoc DNTLoc = cast<DependentNameTypeLoc>(ClsTL);
+          DNTLoc.setElaboratedKeywordLoc(SourceLocation());
+          DNTLoc.setQualifierLoc(NNSLoc.getPrefix());
+          DNTLoc.setNameLoc(NNSLoc.getLocalBeginLoc());
+        }
+        break;
+
+      case NestedNameSpecifier::TypeSpec:
+      case NestedNameSpecifier::TypeSpecWithTemplate:
+        if (isa<ElaboratedType>(ClsTy)) {
+          ElaboratedTypeLoc ETLoc = *cast<ElaboratedTypeLoc>(&ClsTL);
+          ETLoc.setElaboratedKeywordLoc(SourceLocation());
+          ETLoc.setQualifierLoc(NNSLoc.getPrefix());
+          TypeLoc NamedTL = ETLoc.getNamedTypeLoc();
+          NamedTL.initializeFullCopy(NNSLoc.getTypeLoc());
+        } else {
+          ClsTL.initializeFullCopy(NNSLoc.getTypeLoc());
+        }
+        break;
+
+      case NestedNameSpecifier::Namespace:
+      case NestedNameSpecifier::NamespaceAlias:
+      case NestedNameSpecifier::Global:
+        llvm_unreachable("Nested-name-specifier must name a type");
+      }
+
+      // Finally fill in MemberPointerLocInfo fields.
+      TL.setStarLoc(Chunk.Loc);
+      TL.setClassTInfo(ClsTInfo);
+    }
+    void VisitLValueReferenceTypeLoc(LValueReferenceTypeLoc TL) {
+      assert(Chunk.Kind == DeclaratorChunk::Reference);
+      // 'Amp' is misleading: this might have been originally
+      /// spelled with AmpAmp.
+      TL.setAmpLoc(Chunk.Loc);
+    }
+    void VisitRValueReferenceTypeLoc(RValueReferenceTypeLoc TL) {
+      assert(Chunk.Kind == DeclaratorChunk::Reference);
+      assert(!Chunk.Ref.LValueRef);
+      TL.setAmpAmpLoc(Chunk.Loc);
+    }
+    void VisitArrayTypeLoc(ArrayTypeLoc TL) {
+      assert(Chunk.Kind == DeclaratorChunk::Array);
+      TL.setLBracketLoc(Chunk.Loc);
+      TL.setRBracketLoc(Chunk.EndLoc);
+      TL.setSizeExpr(static_cast<Expr*>(Chunk.Arr.NumElts));
+    }
+    void VisitFunctionTypeLoc(FunctionTypeLoc TL) {
+      assert(Chunk.Kind == DeclaratorChunk::Function);
+      TL.setLocalRangeBegin(Chunk.Loc);
+      TL.setLocalRangeEnd(Chunk.EndLoc);
+      TL.setTrailingReturn(!!Chunk.Fun.TrailingReturnType);
+
+      const DeclaratorChunk::FunctionTypeInfo &FTI = Chunk.Fun;
+      for (unsigned i = 0, e = TL.getNumArgs(), tpi = 0; i != e; ++i) {
+        ParmVarDecl *Param = cast<ParmVarDecl>(FTI.ArgInfo[i].Param);
+        TL.setArg(tpi++, Param);
+      }
+      // FIXME: exception specs
+    }
+    void VisitParenTypeLoc(ParenTypeLoc TL) {
+      assert(Chunk.Kind == DeclaratorChunk::Paren);
+      TL.setLParenLoc(Chunk.Loc);
+      TL.setRParenLoc(Chunk.EndLoc);
+    }
+
+    void VisitTypeLoc(TypeLoc TL) {
+      llvm_unreachable("unsupported TypeLoc kind in declarator!");
+    }
+  };
+}
+
+/// \brief Create and instantiate a TypeSourceInfo with type source information.
+///
+/// \param T QualType referring to the type as written in source code.
+///
+/// \param ReturnTypeInfo For declarators whose return type does not show
+/// up in the normal place in the declaration specifiers (such as a C++
+/// conversion function), this pointer will refer to a type source information
+/// for that return type.
+TypeSourceInfo *
+Sema::GetTypeSourceInfoForDeclarator(Declarator &D, QualType T,
+                                     TypeSourceInfo *ReturnTypeInfo) {
+  TypeSourceInfo *TInfo = Context.CreateTypeSourceInfo(T);
+  UnqualTypeLoc CurrTL = TInfo->getTypeLoc().getUnqualifiedLoc();
+
+  // Handle parameter packs whose type is a pack expansion.
+  if (isa<PackExpansionType>(T)) {
+    cast<PackExpansionTypeLoc>(CurrTL).setEllipsisLoc(D.getEllipsisLoc());
+    CurrTL = CurrTL.getNextTypeLoc().getUnqualifiedLoc();    
+  }
+  
+  for (unsigned i = 0, e = D.getNumTypeObjects(); i != e; ++i) {
+    while (isa<AttributedTypeLoc>(CurrTL)) {
+      AttributedTypeLoc TL = cast<AttributedTypeLoc>(CurrTL);
+      fillAttributedTypeLoc(TL, D.getTypeObject(i).getAttrs());
+      CurrTL = TL.getNextTypeLoc().getUnqualifiedLoc();
+    }
+
+    DeclaratorLocFiller(Context, D.getTypeObject(i)).Visit(CurrTL);
+    CurrTL = CurrTL.getNextTypeLoc().getUnqualifiedLoc();
+  }
+  
+  // If we have different source information for the return type, use
+  // that.  This really only applies to C++ conversion functions.
+  if (ReturnTypeInfo) {
+    TypeLoc TL = ReturnTypeInfo->getTypeLoc();
+    assert(TL.getFullDataSize() == CurrTL.getFullDataSize());
+    memcpy(CurrTL.getOpaqueData(), TL.getOpaqueData(), TL.getFullDataSize());
+  } else {
+    TypeSpecLocFiller(Context, D.getDeclSpec()).Visit(CurrTL);
+  }
+      
+  return TInfo;
+}
+
+/// \brief Create a LocInfoType to hold the given QualType and TypeSourceInfo.
+ParsedType Sema::CreateParsedType(QualType T, TypeSourceInfo *TInfo) {
+  // FIXME: LocInfoTypes are "transient", only needed for passing to/from Parser
+  // and Sema during declaration parsing. Try deallocating/caching them when
+  // it's appropriate, instead of allocating them and keeping them around.
+  LocInfoType *LocT = (LocInfoType*)BumpAlloc.Allocate(sizeof(LocInfoType), 
+                                                       TypeAlignment);
+  new (LocT) LocInfoType(T, TInfo);
+  assert(LocT->getTypeClass() != T->getTypeClass() &&
+         "LocInfoType's TypeClass conflicts with an existing Type class");
+  return ParsedType::make(QualType(LocT, 0));
+}
+
+void LocInfoType::getAsStringInternal(std::string &Str,
+                                      const PrintingPolicy &Policy) const {
+  llvm_unreachable("LocInfoType leaked into the type system; an opaque TypeTy*"
+         " was used directly instead of getting the QualType through"
+         " GetTypeFromParser");
+}
+
+TypeResult Sema::ActOnTypeName(Scope *S, Declarator &D) {
+  // C99 6.7.6: Type names have no identifier.  This is already validated by
+  // the parser.
+  assert(D.getIdentifier() == 0 && "Type name should have no identifier!");
+
+  TypeSourceInfo *TInfo = GetTypeForDeclarator(D, S);
+  QualType T = TInfo->getType();
+  if (D.isInvalidType())
+    return true;
+
+  // Make sure there are no unused decl attributes on the declarator.
+  // We don't want to do this for ObjC parameters because we're going
+  // to apply them to the actual parameter declaration.
+  if (D.getContext() != Declarator::ObjCParameterContext)
+    checkUnusedDeclAttributes(D);
+
+  if (getLangOpts().CPlusPlus) {
+    // Check that there are no default arguments (C++ only).
+    CheckExtraCXXDefaultArguments(D);
+  }
+
+  return CreateParsedType(T, TInfo);
+}
+
+ParsedType Sema::ActOnObjCInstanceType(SourceLocation Loc) {
+  QualType T = Context.getObjCInstanceType();
+  TypeSourceInfo *TInfo = Context.getTrivialTypeSourceInfo(T, Loc);
+  return CreateParsedType(T, TInfo);
+}
+
+
+//===----------------------------------------------------------------------===//
+// Type Attribute Processing
+//===----------------------------------------------------------------------===//
+
+/// HandleAddressSpaceTypeAttribute - Process an address_space attribute on the
+/// specified type.  The attribute contains 1 argument, the id of the address
+/// space for the type.
+static void HandleAddressSpaceTypeAttribute(QualType &Type,
+                                            const AttributeList &Attr, Sema &S){
+
+  // If this type is already address space qualified, reject it.
+  // ISO/IEC TR 18037 S5.3 (amending C99 6.7.3): "No type shall be qualified by
+  // qualifiers for two or more different address spaces."
+  if (Type.getAddressSpace()) {
+    S.Diag(Attr.getLoc(), diag::err_attribute_address_multiple_qualifiers);
+    Attr.setInvalid();
+    return;
+  }
+
+  // ISO/IEC TR 18037 S5.3 (amending C99 6.7.3): "A function type shall not be
+  // qualified by an address-space qualifier."
+  if (Type->isFunctionType()) {
+    S.Diag(Attr.getLoc(), diag::err_attribute_address_function_type);
+    Attr.setInvalid();
+    return;
+  }
+
+  // Check the attribute arguments.
+  if (Attr.getNumArgs() != 1) {
+    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
+    Attr.setInvalid();
+    return;
+  }
+  Expr *ASArgExpr = static_cast<Expr *>(Attr.getArg(0));
+  llvm::APSInt addrSpace(32);
+  if (ASArgExpr->isTypeDependent() || ASArgExpr->isValueDependent() ||
+      !ASArgExpr->isIntegerConstantExpr(addrSpace, S.Context)) {
+    S.Diag(Attr.getLoc(), diag::err_attribute_address_space_not_int)
+      << ASArgExpr->getSourceRange();
+    Attr.setInvalid();
+    return;
+  }
+
+  // Bounds checking.
+  if (addrSpace.isSigned()) {
+    if (addrSpace.isNegative()) {
+      S.Diag(Attr.getLoc(), diag::err_attribute_address_space_negative)
+        << ASArgExpr->getSourceRange();
+      Attr.setInvalid();
+      return;
+    }
+    addrSpace.setIsSigned(false);
+  }
+  llvm::APSInt max(addrSpace.getBitWidth());
+  max = Qualifiers::MaxAddressSpace;
+  if (addrSpace > max) {
+    S.Diag(Attr.getLoc(), diag::err_attribute_address_space_too_high)
+      << Qualifiers::MaxAddressSpace << ASArgExpr->getSourceRange();
+    Attr.setInvalid();
+    return;
+  }
+
+  unsigned ASIdx = static_cast<unsigned>(addrSpace.getZExtValue());
+  Type = S.Context.getAddrSpaceQualType(Type, ASIdx);
+}
+
+/// Does this type have a "direct" ownership qualifier?  That is,
+/// is it written like "__strong id", as opposed to something like
+/// "typeof(foo)", where that happens to be strong?
+static bool hasDirectOwnershipQualifier(QualType type) {
+  // Fast path: no qualifier at all.
+  assert(type.getQualifiers().hasObjCLifetime());
+
+  while (true) {
+    // __strong id
+    if (const AttributedType *attr = dyn_cast<AttributedType>(type)) {
+      if (attr->getAttrKind() == AttributedType::attr_objc_ownership)
+        return true;
+
+      type = attr->getModifiedType();
+
+    // X *__strong (...)
+    } else if (const ParenType *paren = dyn_cast<ParenType>(type)) {
+      type = paren->getInnerType();
+   
+    // That's it for things we want to complain about.  In particular,
+    // we do not want to look through typedefs, typeof(expr),
+    // typeof(type), or any other way that the type is somehow
+    // abstracted.
+    } else {
+      
+      return false;
+    }
+  }
+}
+
+/// handleObjCOwnershipTypeAttr - Process an objc_ownership
+/// attribute on the specified type.
+///
+/// Returns 'true' if the attribute was handled.
+static bool handleObjCOwnershipTypeAttr(TypeProcessingState &state,
+                                       AttributeList &attr,
+                                       QualType &type) {
+  bool NonObjCPointer = false;
+
+  if (!type->isDependentType()) {
+    if (const PointerType *ptr = type->getAs<PointerType>()) {
+      QualType pointee = ptr->getPointeeType();
+      if (pointee->isObjCRetainableType() || pointee->isPointerType())
+        return false;
+      // It is important not to lose the source info that there was an attribute
+      // applied to non-objc pointer. We will create an attributed type but
+      // its type will be the same as the original type.
+      NonObjCPointer = true;
+    } else if (!type->isObjCRetainableType()) {
+      return false;
+    }
+  }
+
+  Sema &S = state.getSema();
+  SourceLocation AttrLoc = attr.getLoc();
+  if (AttrLoc.isMacroID())
+    AttrLoc = S.getSourceManager().getImmediateExpansionRange(AttrLoc).first;
+
+  if (!attr.getParameterName()) {
+    S.Diag(AttrLoc, diag::err_attribute_argument_n_not_string)
+      << "objc_ownership" << 1;
+    attr.setInvalid();
+    return true;
+  }
+
+  // Consume lifetime attributes without further comment outside of
+  // ARC mode.
+  if (!S.getLangOpts().ObjCAutoRefCount)
+    return true;
+
+  Qualifiers::ObjCLifetime lifetime;
+  if (attr.getParameterName()->isStr("none"))
+    lifetime = Qualifiers::OCL_ExplicitNone;
+  else if (attr.getParameterName()->isStr("strong"))
+    lifetime = Qualifiers::OCL_Strong;
+  else if (attr.getParameterName()->isStr("weak"))
+    lifetime = Qualifiers::OCL_Weak;
+  else if (attr.getParameterName()->isStr("autoreleasing"))
+    lifetime = Qualifiers::OCL_Autoreleasing;
+  else {
+    S.Diag(AttrLoc, diag::warn_attribute_type_not_supported)
+      << "objc_ownership" << attr.getParameterName();
+    attr.setInvalid();
+    return true;
+  }
+
+  SplitQualType underlyingType = type.split();
+
+  // Check for redundant/conflicting ownership qualifiers.
+  if (Qualifiers::ObjCLifetime previousLifetime
+        = type.getQualifiers().getObjCLifetime()) {
+    // If it's written directly, that's an error.
+    if (hasDirectOwnershipQualifier(type)) {
+      S.Diag(AttrLoc, diag::err_attr_objc_ownership_redundant)
+        << type;
+      return true;
+    }
+
+    // Otherwise, if the qualifiers actually conflict, pull sugar off
+    // until we reach a type that is directly qualified.
+    if (previousLifetime != lifetime) {
+      // This should always terminate: the canonical type is
+      // qualified, so some bit of sugar must be hiding it.
+      while (!underlyingType.Quals.hasObjCLifetime()) {
+        underlyingType = underlyingType.getSingleStepDesugaredType();
+      }
+      underlyingType.Quals.removeObjCLifetime();
+    }
+  }
+
+  underlyingType.Quals.addObjCLifetime(lifetime);
+
+  if (NonObjCPointer) {
+    StringRef name = attr.getName()->getName();
+    switch (lifetime) {
+    case Qualifiers::OCL_None:
+    case Qualifiers::OCL_ExplicitNone:
+      break;
+    case Qualifiers::OCL_Strong: name = "__strong"; break;
+    case Qualifiers::OCL_Weak: name = "__weak"; break;
+    case Qualifiers::OCL_Autoreleasing: name = "__autoreleasing"; break;
+    }
+    S.Diag(AttrLoc, diag::warn_objc_object_attribute_wrong_type)
+      << name << type;
+  }
+
+  QualType origType = type;
+  if (!NonObjCPointer)
+    type = S.Context.getQualifiedType(underlyingType);
+
+  // If we have a valid source location for the attribute, use an
+  // AttributedType instead.
+  if (AttrLoc.isValid())
+    type = S.Context.getAttributedType(AttributedType::attr_objc_ownership,
+                                       origType, type);
+
+  // Forbid __weak if the runtime doesn't support it.
+  if (lifetime == Qualifiers::OCL_Weak &&
+      !S.getLangOpts().ObjCRuntimeHasWeak && !NonObjCPointer) {
+
+    // Actually, delay this until we know what we're parsing.
+    if (S.DelayedDiagnostics.shouldDelayDiagnostics()) {
+      S.DelayedDiagnostics.add(
+          sema::DelayedDiagnostic::makeForbiddenType(
+              S.getSourceManager().getExpansionLoc(AttrLoc),
+              diag::err_arc_weak_no_runtime, type, /*ignored*/ 0));
+    } else {
+      S.Diag(AttrLoc, diag::err_arc_weak_no_runtime);
+    }
+
+    attr.setInvalid();
+    return true;
+  }
+    
+  // Forbid __weak for class objects marked as 
+  // objc_arc_weak_reference_unavailable
+  if (lifetime == Qualifiers::OCL_Weak) {
+    QualType T = type;
+    while (const PointerType *ptr = T->getAs<PointerType>())
+      T = ptr->getPointeeType();
+    if (const ObjCObjectPointerType *ObjT = T->getAs<ObjCObjectPointerType>()) {
+      ObjCInterfaceDecl *Class = ObjT->getInterfaceDecl();
+      if (Class->isArcWeakrefUnavailable()) {
+          S.Diag(AttrLoc, diag::err_arc_unsupported_weak_class);
+          S.Diag(ObjT->getInterfaceDecl()->getLocation(), 
+                 diag::note_class_declared);
+      }
+    }
+  }
+  
+  return true;
+}
+
+/// handleObjCGCTypeAttr - Process the __attribute__((objc_gc)) type
+/// attribute on the specified type.  Returns true to indicate that
+/// the attribute was handled, false to indicate that the type does
+/// not permit the attribute.
+static bool handleObjCGCTypeAttr(TypeProcessingState &state,
+                                 AttributeList &attr,
+                                 QualType &type) {
+  Sema &S = state.getSema();
+
+  // Delay if this isn't some kind of pointer.
+  if (!type->isPointerType() &&
+      !type->isObjCObjectPointerType() &&
+      !type->isBlockPointerType())
+    return false;
+
+  if (type.getObjCGCAttr() != Qualifiers::GCNone) {
+    S.Diag(attr.getLoc(), diag::err_attribute_multiple_objc_gc);
+    attr.setInvalid();
+    return true;
+  }
+
+  // Check the attribute arguments.
+  if (!attr.getParameterName()) {
+    S.Diag(attr.getLoc(), diag::err_attribute_argument_n_not_string)
+      << "objc_gc" << 1;
+    attr.setInvalid();
+    return true;
+  }
+  Qualifiers::GC GCAttr;
+  if (attr.getNumArgs() != 0) {
+    S.Diag(attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
+    attr.setInvalid();
+    return true;
+  }
+  if (attr.getParameterName()->isStr("weak"))
+    GCAttr = Qualifiers::Weak;
+  else if (attr.getParameterName()->isStr("strong"))
+    GCAttr = Qualifiers::Strong;
+  else {
+    S.Diag(attr.getLoc(), diag::warn_attribute_type_not_supported)
+      << "objc_gc" << attr.getParameterName();
+    attr.setInvalid();
+    return true;
+  }
+
+  QualType origType = type;
+  type = S.Context.getObjCGCQualType(origType, GCAttr);
+
+  // Make an attributed type to preserve the source information.
+  if (attr.getLoc().isValid())
+    type = S.Context.getAttributedType(AttributedType::attr_objc_gc,
+                                       origType, type);
+
+  return true;
+}
+
+namespace {
+  /// A helper class to unwrap a type down to a function for the
+  /// purposes of applying attributes there.
+  ///
+  /// Use:
+  ///   FunctionTypeUnwrapper unwrapped(SemaRef, T);
+  ///   if (unwrapped.isFunctionType()) {
+  ///     const FunctionType *fn = unwrapped.get();
+  ///     // change fn somehow
+  ///     T = unwrapped.wrap(fn);
+  ///   }
+  struct FunctionTypeUnwrapper {
+    enum WrapKind {
+      Desugar,
+      Parens,
+      Pointer,
+      BlockPointer,
+      Reference,
+      MemberPointer
+    };
+
+    QualType Original;
+    const FunctionType *Fn;
+    SmallVector<unsigned char /*WrapKind*/, 8> Stack;
+
+    FunctionTypeUnwrapper(Sema &S, QualType T) : Original(T) {
+      while (true) {
+        const Type *Ty = T.getTypePtr();
+        if (isa<FunctionType>(Ty)) {
+          Fn = cast<FunctionType>(Ty);
+          return;
+        } else if (isa<ParenType>(Ty)) {
+          T = cast<ParenType>(Ty)->getInnerType();
+          Stack.push_back(Parens);
+        } else if (isa<PointerType>(Ty)) {
+          T = cast<PointerType>(Ty)->getPointeeType();
+          Stack.push_back(Pointer);
+        } else if (isa<BlockPointerType>(Ty)) {
+          T = cast<BlockPointerType>(Ty)->getPointeeType();
+          Stack.push_back(BlockPointer);
+        } else if (isa<MemberPointerType>(Ty)) {
+          T = cast<MemberPointerType>(Ty)->getPointeeType();
+          Stack.push_back(MemberPointer);
+        } else if (isa<ReferenceType>(Ty)) {
+          T = cast<ReferenceType>(Ty)->getPointeeType();
+          Stack.push_back(Reference);
+        } else {
+          const Type *DTy = Ty->getUnqualifiedDesugaredType();
+          if (Ty == DTy) {
+            Fn = 0;
+            return;
+          }
+
+          T = QualType(DTy, 0);
+          Stack.push_back(Desugar);
+        }
+      }
+    }
+
+    bool isFunctionType() const { return (Fn != 0); }
+    const FunctionType *get() const { return Fn; }
+
+    QualType wrap(Sema &S, const FunctionType *New) {
+      // If T wasn't modified from the unwrapped type, do nothing.
+      if (New == get()) return Original;
+
+      Fn = New;
+      return wrap(S.Context, Original, 0);
+    }
+
+  private:
+    QualType wrap(ASTContext &C, QualType Old, unsigned I) {
+      if (I == Stack.size())
+        return C.getQualifiedType(Fn, Old.getQualifiers());
+
+      // Build up the inner type, applying the qualifiers from the old
+      // type to the new type.
+      SplitQualType SplitOld = Old.split();
+
+      // As a special case, tail-recurse if there are no qualifiers.
+      if (SplitOld.Quals.empty())
+        return wrap(C, SplitOld.Ty, I);
+      return C.getQualifiedType(wrap(C, SplitOld.Ty, I), SplitOld.Quals);
+    }
+
+    QualType wrap(ASTContext &C, const Type *Old, unsigned I) {
+      if (I == Stack.size()) return QualType(Fn, 0);
+
+      switch (static_cast<WrapKind>(Stack[I++])) {
+      case Desugar:
+        // This is the point at which we potentially lose source
+        // information.
+        return wrap(C, Old->getUnqualifiedDesugaredType(), I);
+
+      case Parens: {
+        QualType New = wrap(C, cast<ParenType>(Old)->getInnerType(), I);
+        return C.getParenType(New);
+      }
+
+      case Pointer: {
+        QualType New = wrap(C, cast<PointerType>(Old)->getPointeeType(), I);
+        return C.getPointerType(New);
+      }
+
+      case BlockPointer: {
+        QualType New = wrap(C, cast<BlockPointerType>(Old)->getPointeeType(),I);
+        return C.getBlockPointerType(New);
+      }
+
+      case MemberPointer: {
+        const MemberPointerType *OldMPT = cast<MemberPointerType>(Old);
+        QualType New = wrap(C, OldMPT->getPointeeType(), I);
+        return C.getMemberPointerType(New, OldMPT->getClass());
+      }
+
+      case Reference: {
+        const ReferenceType *OldRef = cast<ReferenceType>(Old);
+        QualType New = wrap(C, OldRef->getPointeeType(), I);
+        if (isa<LValueReferenceType>(OldRef))
+          return C.getLValueReferenceType(New, OldRef->isSpelledAsLValue());
+        else
+          return C.getRValueReferenceType(New);
+      }
+      }
+
+      llvm_unreachable("unknown wrapping kind");
+    }
+  };
+}
+
+/// Process an individual function attribute.  Returns true to
+/// indicate that the attribute was handled, false if it wasn't.
+static bool handleFunctionTypeAttr(TypeProcessingState &state,
+                                   AttributeList &attr,
+                                   QualType &type) {
+  Sema &S = state.getSema();
+
+  FunctionTypeUnwrapper unwrapped(S, type);
+
+  if (attr.getKind() == AttributeList::AT_noreturn) {
+    if (S.CheckNoReturnAttr(attr))
+      return true;
+
+    // Delay if this is not a function type.
+    if (!unwrapped.isFunctionType())
+      return false;
+
+    // Otherwise we can process right away.
+    FunctionType::ExtInfo EI = unwrapped.get()->getExtInfo().withNoReturn(true);
+    type = unwrapped.wrap(S, S.Context.adjustFunctionType(unwrapped.get(), EI));
+    return true;
+  }
+
+  // ns_returns_retained is not always a type attribute, but if we got
+  // here, we're treating it as one right now.
+  if (attr.getKind() == AttributeList::AT_ns_returns_retained) {
+    assert(S.getLangOpts().ObjCAutoRefCount &&
+           "ns_returns_retained treated as type attribute in non-ARC");
+    if (attr.getNumArgs()) return true;
+
+    // Delay if this is not a function type.
+    if (!unwrapped.isFunctionType())
+      return false;
+
+    FunctionType::ExtInfo EI
+      = unwrapped.get()->getExtInfo().withProducesResult(true);
+    type = unwrapped.wrap(S, S.Context.adjustFunctionType(unwrapped.get(), EI));
+    return true;
+  }
+
+  if (attr.getKind() == AttributeList::AT_regparm) {
+    unsigned value;
+    if (S.CheckRegparmAttr(attr, value))
+      return true;
+
+    // Delay if this is not a function type.
+    if (!unwrapped.isFunctionType())
+      return false;
+
+    // Diagnose regparm with fastcall.
+    const FunctionType *fn = unwrapped.get();
+    CallingConv CC = fn->getCallConv();
+    if (CC == CC_X86FastCall) {
+      S.Diag(attr.getLoc(), diag::err_attributes_are_not_compatible)
+        << FunctionType::getNameForCallConv(CC)
+        << "regparm";
+      attr.setInvalid();
+      return true;
+    }
+
+    FunctionType::ExtInfo EI = 
+      unwrapped.get()->getExtInfo().withRegParm(value);
+    type = unwrapped.wrap(S, S.Context.adjustFunctionType(unwrapped.get(), EI));
+    return true;
+  }
+
+  // Otherwise, a calling convention.
+  CallingConv CC;
+  if (S.CheckCallingConvAttr(attr, CC))
+    return true;
+
+  // Delay if the type didn't work out to a function.
+  if (!unwrapped.isFunctionType()) return false;
+
+  const FunctionType *fn = unwrapped.get();
+  CallingConv CCOld = fn->getCallConv();
+  if (S.Context.getCanonicalCallConv(CC) ==
+      S.Context.getCanonicalCallConv(CCOld)) {
+    FunctionType::ExtInfo EI= unwrapped.get()->getExtInfo().withCallingConv(CC);
+    type = unwrapped.wrap(S, S.Context.adjustFunctionType(unwrapped.get(), EI));
+    return true;
+  }
+
+  if (CCOld != (S.LangOpts.MRTD ? CC_X86StdCall : CC_Default)) {
+    // Should we diagnose reapplications of the same convention?
+    S.Diag(attr.getLoc(), diag::err_attributes_are_not_compatible)
+      << FunctionType::getNameForCallConv(CC)
+      << FunctionType::getNameForCallConv(CCOld);
+    attr.setInvalid();
+    return true;
+  }
+
+  // Diagnose the use of X86 fastcall on varargs or unprototyped functions.
+  if (CC == CC_X86FastCall) {
+    if (isa<FunctionNoProtoType>(fn)) {
+      S.Diag(attr.getLoc(), diag::err_cconv_knr)
+        << FunctionType::getNameForCallConv(CC);
+      attr.setInvalid();
+      return true;
+    }
+
+    const FunctionProtoType *FnP = cast<FunctionProtoType>(fn);
+    if (FnP->isVariadic()) {
+      S.Diag(attr.getLoc(), diag::err_cconv_varargs)
+        << FunctionType::getNameForCallConv(CC);
+      attr.setInvalid();
+      return true;
+    }
+
+    // Also diagnose fastcall with regparm.
+    if (fn->getHasRegParm()) {
+      S.Diag(attr.getLoc(), diag::err_attributes_are_not_compatible)
+        << "regparm"
+        << FunctionType::getNameForCallConv(CC);
+      attr.setInvalid();
+      return true;
+    }
+  }
+
+  FunctionType::ExtInfo EI = unwrapped.get()->getExtInfo().withCallingConv(CC);
+  type = unwrapped.wrap(S, S.Context.adjustFunctionType(unwrapped.get(), EI));
+  return true;
+}
+
+/// Handle OpenCL image access qualifiers: read_only, write_only, read_write
+static void HandleOpenCLImageAccessAttribute(QualType& CurType,
+                                             const AttributeList &Attr,
+                                             Sema &S) {
+  // Check the attribute arguments.
+  if (Attr.getNumArgs() != 1) {
+    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
+    Attr.setInvalid();
+    return;
+  }
+  Expr *sizeExpr = static_cast<Expr *>(Attr.getArg(0));
+  llvm::APSInt arg(32);
+  if (sizeExpr->isTypeDependent() || sizeExpr->isValueDependent() ||
+      !sizeExpr->isIntegerConstantExpr(arg, S.Context)) {
+    S.Diag(Attr.getLoc(), diag::err_attribute_argument_not_int)
+      << "opencl_image_access" << sizeExpr->getSourceRange();
+    Attr.setInvalid();
+    return;
+  }
+  unsigned iarg = static_cast<unsigned>(arg.getZExtValue());
+  switch (iarg) {
+  case CLIA_read_only:
+  case CLIA_write_only:
+  case CLIA_read_write:
+    // Implemented in a separate patch
+    break;
+  default:
+    // Implemented in a separate patch
+    S.Diag(Attr.getLoc(), diag::err_attribute_invalid_size)
+      << sizeExpr->getSourceRange();
+    Attr.setInvalid();
+    break;
+  }
+}
+
+/// HandleVectorSizeAttribute - this attribute is only applicable to integral
+/// and float scalars, although arrays, pointers, and function return values are
+/// allowed in conjunction with this construct. Aggregates with this attribute
+/// are invalid, even if they are of the same size as a corresponding scalar.
+/// The raw attribute should contain precisely 1 argument, the vector size for
+/// the variable, measured in bytes. If curType and rawAttr are well formed,
+/// this routine will return a new vector type.
+static void HandleVectorSizeAttr(QualType& CurType, const AttributeList &Attr,
+                                 Sema &S) {
+  // Check the attribute arguments.
+  if (Attr.getNumArgs() != 1) {
+    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
+    Attr.setInvalid();
+    return;
+  }
+  Expr *sizeExpr = static_cast<Expr *>(Attr.getArg(0));
+  llvm::APSInt vecSize(32);
+  if (sizeExpr->isTypeDependent() || sizeExpr->isValueDependent() ||
+      !sizeExpr->isIntegerConstantExpr(vecSize, S.Context)) {
+    S.Diag(Attr.getLoc(), diag::err_attribute_argument_not_int)
+      << "vector_size" << sizeExpr->getSourceRange();
+    Attr.setInvalid();
+    return;
+  }
+  // the base type must be integer or float, and can't already be a vector.
+  if (!CurType->isIntegerType() && !CurType->isRealFloatingType()) {
+    S.Diag(Attr.getLoc(), diag::err_attribute_invalid_vector_type) << CurType;
+    Attr.setInvalid();
+    return;
+  }
+  unsigned typeSize = static_cast<unsigned>(S.Context.getTypeSize(CurType));
+  // vecSize is specified in bytes - convert to bits.
+  unsigned vectorSize = static_cast<unsigned>(vecSize.getZExtValue() * 8);
+
+  // the vector size needs to be an integral multiple of the type size.
+  if (vectorSize % typeSize) {
+    S.Diag(Attr.getLoc(), diag::err_attribute_invalid_size)
+      << sizeExpr->getSourceRange();
+    Attr.setInvalid();
+    return;
+  }
+  if (vectorSize == 0) {
+    S.Diag(Attr.getLoc(), diag::err_attribute_zero_size)
+      << sizeExpr->getSourceRange();
+    Attr.setInvalid();
+    return;
+  }
+
+  // Success! Instantiate the vector type, the number of elements is > 0, and
+  // not required to be a power of 2, unlike GCC.
+  CurType = S.Context.getVectorType(CurType, vectorSize/typeSize,
+                                    VectorType::GenericVector);
+}
+
+/// \brief Process the OpenCL-like ext_vector_type attribute when it occurs on
+/// a type.
+static void HandleExtVectorTypeAttr(QualType &CurType, 
+                                    const AttributeList &Attr, 
+                                    Sema &S) {
+  Expr *sizeExpr;
+  
+  // Special case where the argument is a template id.
+  if (Attr.getParameterName()) {
+    CXXScopeSpec SS;
+    SourceLocation TemplateKWLoc;
+    UnqualifiedId id;
+    id.setIdentifier(Attr.getParameterName(), Attr.getLoc());
+
+    ExprResult Size = S.ActOnIdExpression(S.getCurScope(), SS, TemplateKWLoc,
+                                          id, false, false);
+    if (Size.isInvalid())
+      return;
+    
+    sizeExpr = Size.get();
+  } else {
+    // check the attribute arguments.
+    if (Attr.getNumArgs() != 1) {
+      S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
+      return;
+    }
+    sizeExpr = Attr.getArg(0);
+  }
+  
+  // Create the vector type.
+  QualType T = S.BuildExtVectorType(CurType, sizeExpr, Attr.getLoc());
+  if (!T.isNull())
+    CurType = T;
+}
+
+/// HandleNeonVectorTypeAttr - The "neon_vector_type" and
+/// "neon_polyvector_type" attributes are used to create vector types that
+/// are mangled according to ARM's ABI.  Otherwise, these types are identical
+/// to those created with the "vector_size" attribute.  Unlike "vector_size"
+/// the argument to these Neon attributes is the number of vector elements,
+/// not the vector size in bytes.  The vector width and element type must
+/// match one of the standard Neon vector types.
+static void HandleNeonVectorTypeAttr(QualType& CurType,
+                                     const AttributeList &Attr, Sema &S,
+                                     VectorType::VectorKind VecKind,
+                                     const char *AttrName) {
+  // Check the attribute arguments.
+  if (Attr.getNumArgs() != 1) {
+    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
+    Attr.setInvalid();
+    return;
+  }
+  // The number of elements must be an ICE.
+  Expr *numEltsExpr = static_cast<Expr *>(Attr.getArg(0));
+  llvm::APSInt numEltsInt(32);
+  if (numEltsExpr->isTypeDependent() || numEltsExpr->isValueDependent() ||
+      !numEltsExpr->isIntegerConstantExpr(numEltsInt, S.Context)) {
+    S.Diag(Attr.getLoc(), diag::err_attribute_argument_not_int)
+      << AttrName << numEltsExpr->getSourceRange();
+    Attr.setInvalid();
+    return;
+  }
+  // Only certain element types are supported for Neon vectors.
+  const BuiltinType* BTy = CurType->getAs<BuiltinType>();
+  if (!BTy ||
+      (VecKind == VectorType::NeonPolyVector &&
+       BTy->getKind() != BuiltinType::SChar &&
+       BTy->getKind() != BuiltinType::Short) ||
+      (BTy->getKind() != BuiltinType::SChar &&
+       BTy->getKind() != BuiltinType::UChar &&
+       BTy->getKind() != BuiltinType::Short &&
+       BTy->getKind() != BuiltinType::UShort &&
+       BTy->getKind() != BuiltinType::Int &&
+       BTy->getKind() != BuiltinType::UInt &&
+       BTy->getKind() != BuiltinType::LongLong &&
+       BTy->getKind() != BuiltinType::ULongLong &&
+       BTy->getKind() != BuiltinType::Float)) {
+    S.Diag(Attr.getLoc(), diag::err_attribute_invalid_vector_type) <<CurType;
+    Attr.setInvalid();
+    return;
+  }
+  // The total size of the vector must be 64 or 128 bits.
+  unsigned typeSize = static_cast<unsigned>(S.Context.getTypeSize(CurType));
+  unsigned numElts = static_cast<unsigned>(numEltsInt.getZExtValue());
+  unsigned vecSize = typeSize * numElts;
+  if (vecSize != 64 && vecSize != 128) {
+    S.Diag(Attr.getLoc(), diag::err_attribute_bad_neon_vector_size) << CurType;
+    Attr.setInvalid();
+    return;
+  }
+
+  CurType = S.Context.getVectorType(CurType, numElts, VecKind);
+}
+
+static void processTypeAttrs(TypeProcessingState &state, QualType &type,
+                             bool isDeclSpec, AttributeList *attrs) {
+  // Scan through and apply attributes to this type where it makes sense.  Some
+  // attributes (such as __address_space__, __vector_size__, etc) apply to the
+  // type, but others can be present in the type specifiers even though they
+  // apply to the decl.  Here we apply type attributes and ignore the rest.
+
+  AttributeList *next;
+  do {
+    AttributeList &attr = *attrs;
+    next = attr.getNext();
+
+    // Skip attributes that were marked to be invalid.
+    if (attr.isInvalid())
+      continue;
+
+    // If this is an attribute we can handle, do so now,
+    // otherwise, add it to the FnAttrs list for rechaining.
+    switch (attr.getKind()) {
+    default: break;
+
+    case AttributeList::AT_may_alias:
+      // FIXME: This attribute needs to actually be handled, but if we ignore
+      // it it breaks large amounts of Linux software.
+      attr.setUsedAsTypeAttr();
+      break;
+    case AttributeList::AT_address_space:
+      HandleAddressSpaceTypeAttribute(type, attr, state.getSema());
+      attr.setUsedAsTypeAttr();
+      break;
+    OBJC_POINTER_TYPE_ATTRS_CASELIST:
+      if (!handleObjCPointerTypeAttr(state, attr, type))
+        distributeObjCPointerTypeAttr(state, attr, type);
+      attr.setUsedAsTypeAttr();
+      break;
+    case AttributeList::AT_vector_size:
+      HandleVectorSizeAttr(type, attr, state.getSema());
+      attr.setUsedAsTypeAttr();
+      break;
+    case AttributeList::AT_ext_vector_type:
+      if (state.getDeclarator().getDeclSpec().getStorageClassSpec()
+            != DeclSpec::SCS_typedef)
+        HandleExtVectorTypeAttr(type, attr, state.getSema());
+      attr.setUsedAsTypeAttr();
+      break;
+    case AttributeList::AT_neon_vector_type:
+      HandleNeonVectorTypeAttr(type, attr, state.getSema(),
+                               VectorType::NeonVector, "neon_vector_type");
+      attr.setUsedAsTypeAttr();
+      break;
+    case AttributeList::AT_neon_polyvector_type:
+      HandleNeonVectorTypeAttr(type, attr, state.getSema(),
+                               VectorType::NeonPolyVector,
+                               "neon_polyvector_type");
+      attr.setUsedAsTypeAttr();
+      break;
+    case AttributeList::AT_opencl_image_access:
+      HandleOpenCLImageAccessAttribute(type, attr, state.getSema());
+      attr.setUsedAsTypeAttr();
+      break;
+
+    case AttributeList::AT_ns_returns_retained:
+      if (!state.getSema().getLangOpts().ObjCAutoRefCount)
+	break;
+      // fallthrough into the function attrs
+
+    FUNCTION_TYPE_ATTRS_CASELIST:
+      attr.setUsedAsTypeAttr();
+
+      // Never process function type attributes as part of the
+      // declaration-specifiers.
+      if (isDeclSpec)
+        distributeFunctionTypeAttrFromDeclSpec(state, attr, type);
+
+      // Otherwise, handle the possible delays.
+      else if (!handleFunctionTypeAttr(state, attr, type))
+        distributeFunctionTypeAttr(state, attr, type);
+      break;
+    }
+  } while ((attrs = next));
+}
+
+/// \brief Ensure that the type of the given expression is complete.
+///
+/// This routine checks whether the expression \p E has a complete type. If the
+/// expression refers to an instantiable construct, that instantiation is
+/// performed as needed to complete its type. Furthermore
+/// Sema::RequireCompleteType is called for the expression's type (or in the
+/// case of a reference type, the referred-to type).
+///
+/// \param E The expression whose type is required to be complete.
+/// \param PD The partial diagnostic that will be printed out if the type cannot
+/// be completed.
+///
+/// \returns \c true if the type of \p E is incomplete and diagnosed, \c false
+/// otherwise.
+bool Sema::RequireCompleteExprType(Expr *E, const PartialDiagnostic &PD,
+                                   std::pair<SourceLocation,
+                                             PartialDiagnostic> Note) {
+  QualType T = E->getType();
+
+  // Fast path the case where the type is already complete.
+  if (!T->isIncompleteType())
+    return false;
+
+  // Incomplete array types may be completed by the initializer attached to
+  // their definitions. For static data members of class templates we need to
+  // instantiate the definition to get this initializer and complete the type.
+  if (T->isIncompleteArrayType()) {
+    if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E->IgnoreParens())) {
+      if (VarDecl *Var = dyn_cast<VarDecl>(DRE->getDecl())) {
+        if (Var->isStaticDataMember() &&
+            Var->getInstantiatedFromStaticDataMember()) {
+          
+          MemberSpecializationInfo *MSInfo = Var->getMemberSpecializationInfo();
+          assert(MSInfo && "Missing member specialization information?");
+          if (MSInfo->getTemplateSpecializationKind()
+                != TSK_ExplicitSpecialization) {
+            // If we don't already have a point of instantiation, this is it.
+            if (MSInfo->getPointOfInstantiation().isInvalid()) {
+              MSInfo->setPointOfInstantiation(E->getLocStart());
+              
+              // This is a modification of an existing AST node. Notify 
+              // listeners.
+              if (ASTMutationListener *L = getASTMutationListener())
+                L->StaticDataMemberInstantiated(Var);
+            }
+            
+            InstantiateStaticDataMemberDefinition(E->getExprLoc(), Var);
+            
+            // Update the type to the newly instantiated definition's type both
+            // here and within the expression.
+            if (VarDecl *Def = Var->getDefinition()) {
+              DRE->setDecl(Def);
+              T = Def->getType();
+              DRE->setType(T);
+              E->setType(T);
+            }
+          }
+          
+          // We still go on to try to complete the type independently, as it
+          // may also require instantiations or diagnostics if it remains
+          // incomplete.
+        }
+      }
+    }
+  }
+
+  // FIXME: Are there other cases which require instantiating something other
+  // than the type to complete the type of an expression?
+
+  // Look through reference types and complete the referred type.
+  if (const ReferenceType *Ref = T->getAs<ReferenceType>())
+    T = Ref->getPointeeType();
+
+  return RequireCompleteType(E->getExprLoc(), T, PD, Note);
+}
+
+/// @brief Ensure that the type T is a complete type.
+///
+/// This routine checks whether the type @p T is complete in any
+/// context where a complete type is required. If @p T is a complete
+/// type, returns false. If @p T is a class template specialization,
+/// this routine then attempts to perform class template
+/// instantiation. If instantiation fails, or if @p T is incomplete
+/// and cannot be completed, issues the diagnostic @p diag (giving it
+/// the type @p T) and returns true.
+///
+/// @param Loc  The location in the source that the incomplete type
+/// diagnostic should refer to.
+///
+/// @param T  The type that this routine is examining for completeness.
+///
+/// @param PD The partial diagnostic that will be printed out if T is not a
+/// complete type.
+///
+/// @returns @c true if @p T is incomplete and a diagnostic was emitted,
+/// @c false otherwise.
+bool Sema::RequireCompleteType(SourceLocation Loc, QualType T,
+                               const PartialDiagnostic &PD,
+                               std::pair<SourceLocation, 
+                                         PartialDiagnostic> Note) {
+  unsigned diag = PD.getDiagID();
+
+  // FIXME: Add this assertion to make sure we always get instantiation points.
+  //  assert(!Loc.isInvalid() && "Invalid location in RequireCompleteType");
+  // FIXME: Add this assertion to help us flush out problems with
+  // checking for dependent types and type-dependent expressions.
+  //
+  //  assert(!T->isDependentType() &&
+  //         "Can't ask whether a dependent type is complete");
+
+  // If we have a complete type, we're done.
+  NamedDecl *Def = 0;
+  if (!T->isIncompleteType(&Def)) {
+    // If we know about the definition but it is not visible, complain.
+    if (diag != 0 && Def && !LookupResult::isVisible(Def)) {
+      // Suppress this error outside of a SFINAE context if we've already
+      // emitted the error once for this type. There's no usefulness in 
+      // repeating the diagnostic.
+      // FIXME: Add a Fix-It that imports the corresponding module or includes
+      // the header.
+      if (isSFINAEContext() || HiddenDefinitions.insert(Def)) {
+        Diag(Loc, diag::err_module_private_definition) << T;
+        Diag(Def->getLocation(), diag::note_previous_definition);
+      }
+    }
+    
+    return false;
+  }
+
+  const TagType *Tag = T->getAs<TagType>();
+  const ObjCInterfaceType *IFace = 0;
+  
+  if (Tag) {
+    // Avoid diagnosing invalid decls as incomplete.
+    if (Tag->getDecl()->isInvalidDecl())
+      return true;
+
+    // Give the external AST source a chance to complete the type.
+    if (Tag->getDecl()->hasExternalLexicalStorage()) {
+      Context.getExternalSource()->CompleteType(Tag->getDecl());
+      if (!Tag->isIncompleteType())
+        return false;
+    }
+  }
+  else if ((IFace = T->getAs<ObjCInterfaceType>())) {
+    // Avoid diagnosing invalid decls as incomplete.
+    if (IFace->getDecl()->isInvalidDecl())
+      return true;
+    
+    // Give the external AST source a chance to complete the type.
+    if (IFace->getDecl()->hasExternalLexicalStorage()) {
+      Context.getExternalSource()->CompleteType(IFace->getDecl());
+      if (!IFace->isIncompleteType())
+        return false;
+    }
+  }
+    
+  // If we have a class template specialization or a class member of a
+  // class template specialization, or an array with known size of such,
+  // try to instantiate it.
+  QualType MaybeTemplate = T;
+  while (const ConstantArrayType *Array
+           = Context.getAsConstantArrayType(MaybeTemplate))
+    MaybeTemplate = Array->getElementType();
+  if (const RecordType *Record = MaybeTemplate->getAs<RecordType>()) {
+    if (ClassTemplateSpecializationDecl *ClassTemplateSpec
+          = dyn_cast<ClassTemplateSpecializationDecl>(Record->getDecl())) {
+      if (ClassTemplateSpec->getSpecializationKind() == TSK_Undeclared)
+        return InstantiateClassTemplateSpecialization(Loc, ClassTemplateSpec,
+                                                      TSK_ImplicitInstantiation,
+                                                      /*Complain=*/diag != 0);
+    } else if (CXXRecordDecl *Rec
+                 = dyn_cast<CXXRecordDecl>(Record->getDecl())) {
+      CXXRecordDecl *Pattern = Rec->getInstantiatedFromMemberClass();
+      if (!Rec->isBeingDefined() && Pattern) {
+        MemberSpecializationInfo *MSI = Rec->getMemberSpecializationInfo();
+        assert(MSI && "Missing member specialization information?");
+        // This record was instantiated from a class within a template.
+        if (MSI->getTemplateSpecializationKind() != TSK_ExplicitSpecialization)
+          return InstantiateClass(Loc, Rec, Pattern,
+                                  getTemplateInstantiationArgs(Rec),
+                                  TSK_ImplicitInstantiation,
+                                  /*Complain=*/diag != 0);
+      }
+    }
+  }
+
+  if (diag == 0)
+    return true;
+    
+  // We have an incomplete type. Produce a diagnostic.
+  Diag(Loc, PD) << T;
+    
+  // If we have a note, produce it.
+  if (!Note.first.isInvalid())
+    Diag(Note.first, Note.second);
+    
+  // If the type was a forward declaration of a class/struct/union
+  // type, produce a note.
+  if (Tag && !Tag->getDecl()->isInvalidDecl())
+    Diag(Tag->getDecl()->getLocation(),
+         Tag->isBeingDefined() ? diag::note_type_being_defined
+                               : diag::note_forward_declaration)
+      << QualType(Tag, 0);
+  
+  // If the Objective-C class was a forward declaration, produce a note.
+  if (IFace && !IFace->getDecl()->isInvalidDecl())
+    Diag(IFace->getDecl()->getLocation(), diag::note_forward_class);
+
+  return true;
+}
+
+bool Sema::RequireCompleteType(SourceLocation Loc, QualType T,
+                               const PartialDiagnostic &PD) {
+  return RequireCompleteType(Loc, T, PD, 
+                             std::make_pair(SourceLocation(), PDiag(0)));
+}
+  
+bool Sema::RequireCompleteType(SourceLocation Loc, QualType T,
+                               unsigned DiagID) {
+  return RequireCompleteType(Loc, T, PDiag(DiagID),
+                             std::make_pair(SourceLocation(), PDiag(0)));
+}
+
+/// @brief Ensure that the type T is a literal type.
+///
+/// This routine checks whether the type @p T is a literal type. If @p T is an
+/// incomplete type, an attempt is made to complete it. If @p T is a literal
+/// type, or @p AllowIncompleteType is true and @p T is an incomplete type,
+/// returns false. Otherwise, this routine issues the diagnostic @p PD (giving
+/// it the type @p T), along with notes explaining why the type is not a
+/// literal type, and returns true.
+///
+/// @param Loc  The location in the source that the non-literal type
+/// diagnostic should refer to.
+///
+/// @param T  The type that this routine is examining for literalness.
+///
+/// @param PD The partial diagnostic that will be printed out if T is not a
+/// literal type.
+///
+/// @returns @c true if @p T is not a literal type and a diagnostic was emitted,
+/// @c false otherwise.
+bool Sema::RequireLiteralType(SourceLocation Loc, QualType T,
+                              const PartialDiagnostic &PD) {
+  assert(!T->isDependentType() && "type should not be dependent");
+
+  QualType ElemType = Context.getBaseElementType(T);
+  RequireCompleteType(Loc, ElemType, 0);
+
+  if (T->isLiteralType())
+    return false;
+
+  if (PD.getDiagID() == 0)
+    return true;
+
+  Diag(Loc, PD) << T;
+
+  if (T->isVariableArrayType())
+    return true;
+
+  const RecordType *RT = ElemType->getAs<RecordType>();
+  if (!RT)
+    return true;
+
+  const CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
+
+  // FIXME: Better diagnostic for incomplete class?
+  if (!RD->isCompleteDefinition())
+    return true;
+
+  // If the class has virtual base classes, then it's not an aggregate, and
+  // cannot have any constexpr constructors or a trivial default constructor,
+  // so is non-literal. This is better to diagnose than the resulting absence
+  // of constexpr constructors.
+  if (RD->getNumVBases()) {
+    Diag(RD->getLocation(), diag::note_non_literal_virtual_base)
+      << RD->isStruct() << RD->getNumVBases();
+    for (CXXRecordDecl::base_class_const_iterator I = RD->vbases_begin(),
+           E = RD->vbases_end(); I != E; ++I)
+      Diag(I->getLocStart(),
+           diag::note_constexpr_virtual_base_here) << I->getSourceRange();
+  } else if (!RD->isAggregate() && !RD->hasConstexprNonCopyMoveConstructor() &&
+             !RD->hasTrivialDefaultConstructor()) {
+    Diag(RD->getLocation(), diag::note_non_literal_no_constexpr_ctors) << RD;
+  } else if (RD->hasNonLiteralTypeFieldsOrBases()) {
+    for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(),
+         E = RD->bases_end(); I != E; ++I) {
+      if (!I->getType()->isLiteralType()) {
+        Diag(I->getLocStart(),
+             diag::note_non_literal_base_class)
+          << RD << I->getType() << I->getSourceRange();
+        return true;
+      }
+    }
+    for (CXXRecordDecl::field_iterator I = RD->field_begin(),
+         E = RD->field_end(); I != E; ++I) {
+      if (!(*I)->getType()->isLiteralType() ||
+          (*I)->getType().isVolatileQualified()) {
+        Diag((*I)->getLocation(), diag::note_non_literal_field)
+          << RD << (*I) << (*I)->getType()
+          << (*I)->getType().isVolatileQualified();
+        return true;
+      }
+    }
+  } else if (!RD->hasTrivialDestructor()) {
+    // All fields and bases are of literal types, so have trivial destructors.
+    // If this class's destructor is non-trivial it must be user-declared.
+    CXXDestructorDecl *Dtor = RD->getDestructor();
+    assert(Dtor && "class has literal fields and bases but no dtor?");
+    if (!Dtor)
+      return true;
+
+    Diag(Dtor->getLocation(), Dtor->isUserProvided() ?
+         diag::note_non_literal_user_provided_dtor :
+         diag::note_non_literal_nontrivial_dtor) << RD;
+  }
+
+  return true;
+}
+
+/// \brief Retrieve a version of the type 'T' that is elaborated by Keyword
+/// and qualified by the nested-name-specifier contained in SS.
+QualType Sema::getElaboratedType(ElaboratedTypeKeyword Keyword,
+                                 const CXXScopeSpec &SS, QualType T) {
+  if (T.isNull())
+    return T;
+  NestedNameSpecifier *NNS;
+  if (SS.isValid())
+    NNS = static_cast<NestedNameSpecifier *>(SS.getScopeRep());
+  else {
+    if (Keyword == ETK_None)
+      return T;
+    NNS = 0;
+  }
+  return Context.getElaboratedType(Keyword, NNS, T);
+}
+
+QualType Sema::BuildTypeofExprType(Expr *E, SourceLocation Loc) {
+  ExprResult ER = CheckPlaceholderExpr(E);
+  if (ER.isInvalid()) return QualType();
+  E = ER.take();
+
+  if (!E->isTypeDependent()) {
+    QualType T = E->getType();
+    if (const TagType *TT = T->getAs<TagType>())
+      DiagnoseUseOfDecl(TT->getDecl(), E->getExprLoc());
+  }
+  return Context.getTypeOfExprType(E);
+}
+
+/// getDecltypeForExpr - Given an expr, will return the decltype for
+/// that expression, according to the rules in C++11
+/// [dcl.type.simple]p4 and C++11 [expr.lambda.prim]p18.
+static QualType getDecltypeForExpr(Sema &S, Expr *E) {
+  if (E->isTypeDependent())
+    return S.Context.DependentTy;
+
+  // C++11 [dcl.type.simple]p4:
+  //   The type denoted by decltype(e) is defined as follows:
+  //
+  //     - if e is an unparenthesized id-expression or an unparenthesized class
+  //       member access (5.2.5), decltype(e) is the type of the entity named 
+  //       by e. If there is no such entity, or if e names a set of overloaded 
+  //       functions, the program is ill-formed;
+  if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) {
+    if (const ValueDecl *VD = dyn_cast<ValueDecl>(DRE->getDecl()))
+      return VD->getType();
+  }
+  if (const MemberExpr *ME = dyn_cast<MemberExpr>(E)) {
+    if (const FieldDecl *FD = dyn_cast<FieldDecl>(ME->getMemberDecl()))
+      return FD->getType();
+  }
+  
+  // C++11 [expr.lambda.prim]p18:
+  //   Every occurrence of decltype((x)) where x is a possibly
+  //   parenthesized id-expression that names an entity of automatic
+  //   storage duration is treated as if x were transformed into an
+  //   access to a corresponding data member of the closure type that
+  //   would have been declared if x were an odr-use of the denoted
+  //   entity.
+  using namespace sema;
+  if (S.getCurLambda()) {
+    if (isa<ParenExpr>(E)) {
+      if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E->IgnoreParens())) {
+        if (VarDecl *Var = dyn_cast<VarDecl>(DRE->getDecl())) {
+          QualType T = S.getCapturedDeclRefType(Var, DRE->getLocation());
+          if (!T.isNull())
+            return S.Context.getLValueReferenceType(T);
+        }
+      }
+    }
+  }
+
+
+  // C++11 [dcl.type.simple]p4:
+  //   [...]
+  QualType T = E->getType();
+  switch (E->getValueKind()) {
+  //     - otherwise, if e is an xvalue, decltype(e) is T&&, where T is the 
+  //       type of e;
+  case VK_XValue: T = S.Context.getRValueReferenceType(T); break;
+  //     - otherwise, if e is an lvalue, decltype(e) is T&, where T is the 
+  //       type of e;
+  case VK_LValue: T = S.Context.getLValueReferenceType(T); break;
+  //  - otherwise, decltype(e) is the type of e.
+  case VK_RValue: break;
+  }
+  
+  return T;
+}
+
+QualType Sema::BuildDecltypeType(Expr *E, SourceLocation Loc) {
+  ExprResult ER = CheckPlaceholderExpr(E);
+  if (ER.isInvalid()) return QualType();
+  E = ER.take();
+  
+  return Context.getDecltypeType(E, getDecltypeForExpr(*this, E));
+}
+
+QualType Sema::BuildUnaryTransformType(QualType BaseType,
+                                       UnaryTransformType::UTTKind UKind,
+                                       SourceLocation Loc) {
+  switch (UKind) {
+  case UnaryTransformType::EnumUnderlyingType:
+    if (!BaseType->isDependentType() && !BaseType->isEnumeralType()) {
+      Diag(Loc, diag::err_only_enums_have_underlying_types);
+      return QualType();
+    } else {
+      QualType Underlying = BaseType;
+      if (!BaseType->isDependentType()) {
+        EnumDecl *ED = BaseType->getAs<EnumType>()->getDecl();
+        assert(ED && "EnumType has no EnumDecl");
+        DiagnoseUseOfDecl(ED, Loc);
+        Underlying = ED->getIntegerType();
+      }
+      assert(!Underlying.isNull());
+      return Context.getUnaryTransformType(BaseType, Underlying,
+                                        UnaryTransformType::EnumUnderlyingType);
+    }
+  }
+  llvm_unreachable("unknown unary transform type");
+}
+
+QualType Sema::BuildAtomicType(QualType T, SourceLocation Loc) {
+  if (!T->isDependentType()) {
+    // FIXME: It isn't entirely clear whether incomplete atomic types
+    // are allowed or not; for simplicity, ban them for the moment.
+    if (RequireCompleteType(Loc, T,
+                            PDiag(diag::err_atomic_specifier_bad_type) << 0))
+      return QualType();
+
+    int DisallowedKind = -1;
+    if (T->isArrayType())
+      DisallowedKind = 1;
+    else if (T->isFunctionType())
+      DisallowedKind = 2;
+    else if (T->isReferenceType())
+      DisallowedKind = 3;
+    else if (T->isAtomicType())
+      DisallowedKind = 4;
+    else if (T.hasQualifiers())
+      DisallowedKind = 5;
+    else if (!T.isTriviallyCopyableType(Context))
+      // Some other non-trivially-copyable type (probably a C++ class)
+      DisallowedKind = 6;
+
+    if (DisallowedKind != -1) {
+      Diag(Loc, diag::err_atomic_specifier_bad_type) << DisallowedKind << T;
+      return QualType();
+    }
+
+    // FIXME: Do we need any handling for ARC here?
+  }
+
+  // Build the pointer type.
+  return Context.getAtomicType(T);
+}
diff --git a/clang/lib/Sema/TargetAttributesSema.cpp b/clang/lib/Sema/TargetAttributesSema.cpp
new file mode 100644
index 0000000..8b19be7
--- /dev/null
+++ b/clang/lib/Sema/TargetAttributesSema.cpp
@@ -0,0 +1,278 @@
+//===-- TargetAttributesSema.cpp - Encapsulate target attributes-*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains semantic analysis implementation for target-specific
+// attributes.
+//
+//===----------------------------------------------------------------------===//
+
+#include "TargetAttributesSema.h"
+#include "clang/Sema/SemaInternal.h"
+#include "clang/Basic/TargetInfo.h"
+#include "clang/AST/DeclCXX.h"
+#include "llvm/ADT/Triple.h"
+
+using namespace clang;
+
+TargetAttributesSema::~TargetAttributesSema() {}
+bool TargetAttributesSema::ProcessDeclAttribute(Scope *scope, Decl *D,
+                                    const AttributeList &Attr, Sema &S) const {
+  return false;
+}
+
+static void HandleMSP430InterruptAttr(Decl *d,
+                                      const AttributeList &Attr, Sema &S) {
+    // Check the attribute arguments.
+    if (Attr.getNumArgs() != 1) {
+      S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
+      return;
+    }
+
+    // FIXME: Check for decl - it should be void ()(void).
+
+    Expr *NumParamsExpr = static_cast<Expr *>(Attr.getArg(0));
+    llvm::APSInt NumParams(32);
+    if (!NumParamsExpr->isIntegerConstantExpr(NumParams, S.Context)) {
+      S.Diag(Attr.getLoc(), diag::err_attribute_argument_not_int)
+        << "interrupt" << NumParamsExpr->getSourceRange();
+      return;
+    }
+
+    unsigned Num = NumParams.getLimitedValue(255);
+    if ((Num & 1) || Num > 30) {
+      S.Diag(Attr.getLoc(), diag::err_attribute_argument_out_of_bounds)
+        << "interrupt" << (int)NumParams.getSExtValue()
+        << NumParamsExpr->getSourceRange();
+      return;
+    }
+
+    d->addAttr(::new (S.Context) MSP430InterruptAttr(Attr.getLoc(), S.Context, Num));
+    d->addAttr(::new (S.Context) UsedAttr(Attr.getLoc(), S.Context));
+  }
+
+namespace {
+  class MSP430AttributesSema : public TargetAttributesSema {
+  public:
+    MSP430AttributesSema() { }
+    bool ProcessDeclAttribute(Scope *scope, Decl *D,
+                              const AttributeList &Attr, Sema &S) const {
+      if (Attr.getName()->getName() == "interrupt") {
+        HandleMSP430InterruptAttr(D, Attr, S);
+        return true;
+      }
+      return false;
+    }
+  };
+}
+
+static void HandleMBlazeInterruptHandlerAttr(Decl *d, const AttributeList &Attr,
+                                             Sema &S) {
+  // Check the attribute arguments.
+  if (Attr.getNumArgs() != 0) {
+    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
+    return;
+  }
+
+  // FIXME: Check for decl - it should be void ()(void).
+
+  d->addAttr(::new (S.Context) MBlazeInterruptHandlerAttr(Attr.getLoc(),
+                                                          S.Context));
+  d->addAttr(::new (S.Context) UsedAttr(Attr.getLoc(), S.Context));
+}
+
+static void HandleMBlazeSaveVolatilesAttr(Decl *d, const AttributeList &Attr,
+                                          Sema &S) {
+  // Check the attribute arguments.
+  if (Attr.getNumArgs() != 0) {
+    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
+    return;
+  }
+
+  // FIXME: Check for decl - it should be void ()(void).
+
+  d->addAttr(::new (S.Context) MBlazeSaveVolatilesAttr(Attr.getLoc(),
+                                                       S.Context));
+  d->addAttr(::new (S.Context) UsedAttr(Attr.getLoc(), S.Context));
+}
+
+
+namespace {
+  class MBlazeAttributesSema : public TargetAttributesSema {
+  public:
+    MBlazeAttributesSema() { }
+    bool ProcessDeclAttribute(Scope *scope, Decl *D, const AttributeList &Attr,
+                              Sema &S) const {
+      if (Attr.getName()->getName() == "interrupt_handler") {
+        HandleMBlazeInterruptHandlerAttr(D, Attr, S);
+        return true;
+      } else if (Attr.getName()->getName() == "save_volatiles") {
+        HandleMBlazeSaveVolatilesAttr(D, Attr, S);
+        return true;
+      }
+      return false;
+    }
+  };
+}
+
+static void HandleX86ForceAlignArgPointerAttr(Decl *D,
+                                              const AttributeList& Attr,
+                                              Sema &S) {
+  // Check the attribute arguments.
+  if (Attr.getNumArgs() != 0) {
+    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
+    return;
+  }
+
+  // If we try to apply it to a function pointer, don't warn, but don't
+  // do anything, either. It doesn't matter anyway, because there's nothing
+  // special about calling a force_align_arg_pointer function.
+  ValueDecl *VD = dyn_cast<ValueDecl>(D);
+  if (VD && VD->getType()->isFunctionPointerType())
+    return;
+  // Also don't warn on function pointer typedefs.
+  TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(D);
+  if (TD && (TD->getUnderlyingType()->isFunctionPointerType() ||
+             TD->getUnderlyingType()->isFunctionType()))
+    return;
+  // Attribute can only be applied to function types.
+  if (!isa<FunctionDecl>(D)) {
+    S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
+      << Attr.getName() << /* function */0;
+    return;
+  }
+
+  D->addAttr(::new (S.Context) X86ForceAlignArgPointerAttr(Attr.getRange(),
+                                                           S.Context));
+}
+
+static void HandleDLLImportAttr(Decl *D, const AttributeList &Attr, Sema &S) {
+  // check the attribute arguments.
+  if (Attr.getNumArgs() != 0) {
+    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
+    return;
+  }
+
+  // Attribute can be applied only to functions or variables.
+  if (isa<VarDecl>(D)) {
+    D->addAttr(::new (S.Context) DLLImportAttr(Attr.getLoc(), S.Context));
+    return;
+  }
+
+  FunctionDecl *FD = dyn_cast<FunctionDecl>(D);
+  if (!FD) {
+    // Apparently Visual C++ thinks it is okay to not emit a warning
+    // in this case, so only emit a warning when -fms-extensions is not
+    // specified.
+    if (!S.getLangOpts().MicrosoftExt)
+      S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
+        << Attr.getName() << 2 /*variable and function*/;
+    return;
+  }
+
+  // Currently, the dllimport attribute is ignored for inlined functions.
+  // Warning is emitted.
+  if (FD->isInlineSpecified()) {
+    S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "dllimport";
+    return;
+  }
+
+  // The attribute is also overridden by a subsequent declaration as dllexport.
+  // Warning is emitted.
+  for (AttributeList *nextAttr = Attr.getNext(); nextAttr;
+       nextAttr = nextAttr->getNext()) {
+    if (nextAttr->getKind() == AttributeList::AT_dllexport) {
+      S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "dllimport";
+      return;
+    }
+  }
+
+  if (D->getAttr<DLLExportAttr>()) {
+    S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "dllimport";
+    return;
+  }
+
+  D->addAttr(::new (S.Context) DLLImportAttr(Attr.getLoc(), S.Context));
+}
+
+static void HandleDLLExportAttr(Decl *D, const AttributeList &Attr, Sema &S) {
+  // check the attribute arguments.
+  if (Attr.getNumArgs() != 0) {
+    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
+    return;
+  }
+
+  // Attribute can be applied only to functions or variables.
+  if (isa<VarDecl>(D)) {
+    D->addAttr(::new (S.Context) DLLExportAttr(Attr.getLoc(), S.Context));
+    return;
+  }
+
+  FunctionDecl *FD = dyn_cast<FunctionDecl>(D);
+  if (!FD) {
+    S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
+      << Attr.getName() << 2 /*variable and function*/;
+    return;
+  }
+
+  // Currently, the dllexport attribute is ignored for inlined functions, unless
+  // the -fkeep-inline-functions flag has been used. Warning is emitted;
+  if (FD->isInlineSpecified()) {
+    // FIXME: ... unless the -fkeep-inline-functions flag has been used.
+    S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "dllexport";
+    return;
+  }
+
+  D->addAttr(::new (S.Context) DLLExportAttr(Attr.getLoc(), S.Context));
+}
+
+namespace {
+  class X86AttributesSema : public TargetAttributesSema {
+  public:
+    X86AttributesSema() { }
+    bool ProcessDeclAttribute(Scope *scope, Decl *D,
+                              const AttributeList &Attr, Sema &S) const {
+      const llvm::Triple &Triple(S.Context.getTargetInfo().getTriple());
+      if (Triple.getOS() == llvm::Triple::Win32 ||
+          Triple.getOS() == llvm::Triple::MinGW32) {
+        switch (Attr.getKind()) {
+        case AttributeList::AT_dllimport: HandleDLLImportAttr(D, Attr, S);
+                                          return true;
+        case AttributeList::AT_dllexport: HandleDLLExportAttr(D, Attr, S);
+                                          return true;
+        default:                          break;
+        }
+      }
+      if (Triple.getArch() != llvm::Triple::x86_64 &&
+          (Attr.getName()->getName() == "force_align_arg_pointer" ||
+           Attr.getName()->getName() == "__force_align_arg_pointer__")) {
+        HandleX86ForceAlignArgPointerAttr(D, Attr, S);
+        return true;
+      }
+      return false;
+    }
+  };
+}
+
+const TargetAttributesSema &Sema::getTargetAttributesSema() const {
+  if (TheTargetAttributesSema)
+    return *TheTargetAttributesSema;
+
+  const llvm::Triple &Triple(Context.getTargetInfo().getTriple());
+  switch (Triple.getArch()) {
+  case llvm::Triple::msp430:
+    return *(TheTargetAttributesSema = new MSP430AttributesSema);
+  case llvm::Triple::mblaze:
+    return *(TheTargetAttributesSema = new MBlazeAttributesSema);
+  case llvm::Triple::x86:
+  case llvm::Triple::x86_64:
+    return *(TheTargetAttributesSema = new X86AttributesSema);
+  default:
+    return *(TheTargetAttributesSema = new TargetAttributesSema);
+  }
+}
diff --git a/clang/lib/Sema/TargetAttributesSema.h b/clang/lib/Sema/TargetAttributesSema.h
new file mode 100644
index 0000000..410c900
--- /dev/null
+++ b/clang/lib/Sema/TargetAttributesSema.h
@@ -0,0 +1,27 @@
+//===--- TargetAttributesSema.h - Semantic Analysis For Target Attributes -===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef CLANG_SEMA_TARGETSEMA_H
+#define CLANG_SEMA_TARGETSEMA_H
+
+namespace clang {
+  class Scope;
+  class Decl;
+  class AttributeList;
+  class Sema;
+
+  class TargetAttributesSema {
+  public:
+    virtual ~TargetAttributesSema();
+    virtual bool ProcessDeclAttribute(Scope *scope, Decl *D,
+                                      const AttributeList &Attr, Sema &S) const;
+  };
+}
+
+#endif
diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h
new file mode 100644
index 0000000..a66378e
--- /dev/null
+++ b/clang/lib/Sema/TreeTransform.h
@@ -0,0 +1,9268 @@
+//===------- TreeTransform.h - Semantic Tree Transformation -----*- 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 a semantic tree transformation that takes a given
+//  AST and rebuilds it, possibly transforming some nodes in the process.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_SEMA_TREETRANSFORM_H
+#define LLVM_CLANG_SEMA_TREETRANSFORM_H
+
+#include "clang/Sema/SemaInternal.h"
+#include "clang/Sema/Lookup.h"
+#include "clang/Sema/ParsedTemplate.h"
+#include "clang/Sema/SemaDiagnostic.h"
+#include "clang/Sema/ScopeInfo.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/AST/DeclTemplate.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/ExprCXX.h"
+#include "clang/AST/ExprObjC.h"
+#include "clang/AST/Stmt.h"
+#include "clang/AST/StmtCXX.h"
+#include "clang/AST/StmtObjC.h"
+#include "clang/Sema/Ownership.h"
+#include "clang/Sema/Designator.h"
+#include "clang/Lex/Preprocessor.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "TypeLocBuilder.h"
+#include <algorithm>
+
+namespace clang {
+using namespace sema;
+
+/// \brief A semantic tree transformation that allows one to transform one
+/// abstract syntax tree into another.
+///
+/// A new tree transformation is defined by creating a new subclass \c X of
+/// \c TreeTransform<X> and then overriding certain operations to provide
+/// behavior specific to that transformation. For example, template
+/// instantiation is implemented as a tree transformation where the
+/// transformation of TemplateTypeParmType nodes involves substituting the
+/// template arguments for their corresponding template parameters; a similar
+/// transformation is performed for non-type template parameters and
+/// template template parameters.
+///
+/// This tree-transformation template uses static polymorphism to allow
+/// subclasses to customize any of its operations. Thus, a subclass can
+/// override any of the transformation or rebuild operators by providing an
+/// operation with the same signature as the default implementation. The
+/// overridding function should not be virtual.
+///
+/// Semantic tree transformations are split into two stages, either of which
+/// can be replaced by a subclass. The "transform" step transforms an AST node
+/// or the parts of an AST node using the various transformation functions,
+/// then passes the pieces on to the "rebuild" step, which constructs a new AST
+/// node of the appropriate kind from the pieces. The default transformation
+/// routines recursively transform the operands to composite AST nodes (e.g.,
+/// the pointee type of a PointerType node) and, if any of those operand nodes
+/// were changed by the transformation, invokes the rebuild operation to create
+/// a new AST node.
+///
+/// Subclasses can customize the transformation at various levels. The
+/// most coarse-grained transformations involve replacing TransformType(),
+/// TransformExpr(), TransformDecl(), TransformNestedNameSpecifierLoc(),
+/// TransformTemplateName(), or TransformTemplateArgument() with entirely
+/// new implementations.
+///
+/// For more fine-grained transformations, subclasses can replace any of the
+/// \c TransformXXX functions (where XXX is the name of an AST node, e.g.,
+/// PointerType, StmtExpr) to alter the transformation. As mentioned previously,
+/// replacing TransformTemplateTypeParmType() allows template instantiation
+/// to substitute template arguments for their corresponding template
+/// parameters. Additionally, subclasses can override the \c RebuildXXX
+/// functions to control how AST nodes are rebuilt when their operands change.
+/// By default, \c TreeTransform will invoke semantic analysis to rebuild
+/// AST nodes. However, certain other tree transformations (e.g, cloning) may
+/// be able to use more efficient rebuild steps.
+///
+/// There are a handful of other functions that can be overridden, allowing one
+/// to avoid traversing nodes that don't need any transformation
+/// (\c AlreadyTransformed()), force rebuilding AST nodes even when their
+/// operands have not changed (\c AlwaysRebuild()), and customize the
+/// default locations and entity names used for type-checking
+/// (\c getBaseLocation(), \c getBaseEntity()).
+template<typename Derived>
+class TreeTransform {
+  /// \brief Private RAII object that helps us forget and then re-remember
+  /// the template argument corresponding to a partially-substituted parameter
+  /// pack.
+  class ForgetPartiallySubstitutedPackRAII {
+    Derived &Self;
+    TemplateArgument Old;
+    
+  public:
+    ForgetPartiallySubstitutedPackRAII(Derived &Self) : Self(Self) {
+      Old = Self.ForgetPartiallySubstitutedPack();
+    }
+    
+    ~ForgetPartiallySubstitutedPackRAII() {
+      Self.RememberPartiallySubstitutedPack(Old);
+    }
+  };
+  
+protected:
+  Sema &SemaRef;
+  
+  /// \brief The set of local declarations that have been transformed, for
+  /// cases where we are forced to build new declarations within the transformer
+  /// rather than in the subclass (e.g., lambda closure types).
+  llvm::DenseMap<Decl *, Decl *> TransformedLocalDecls;
+  
+public:
+  /// \brief Initializes a new tree transformer.
+  TreeTransform(Sema &SemaRef) : SemaRef(SemaRef) { }
+
+  /// \brief Retrieves a reference to the derived class.
+  Derived &getDerived() { return static_cast<Derived&>(*this); }
+
+  /// \brief Retrieves a reference to the derived class.
+  const Derived &getDerived() const {
+    return static_cast<const Derived&>(*this);
+  }
+
+  static inline ExprResult Owned(Expr *E) { return E; }
+  static inline StmtResult Owned(Stmt *S) { return S; }
+
+  /// \brief Retrieves a reference to the semantic analysis object used for
+  /// this tree transform.
+  Sema &getSema() const { return SemaRef; }
+
+  /// \brief Whether the transformation should always rebuild AST nodes, even
+  /// if none of the children have changed.
+  ///
+  /// Subclasses may override this function to specify when the transformation
+  /// should rebuild all AST nodes.
+  bool AlwaysRebuild() { return false; }
+
+  /// \brief Returns the location of the entity being transformed, if that
+  /// information was not available elsewhere in the AST.
+  ///
+  /// By default, returns no source-location information. Subclasses can
+  /// provide an alternative implementation that provides better location
+  /// information.
+  SourceLocation getBaseLocation() { return SourceLocation(); }
+
+  /// \brief Returns the name of the entity being transformed, if that
+  /// information was not available elsewhere in the AST.
+  ///
+  /// By default, returns an empty name. Subclasses can provide an alternative
+  /// implementation with a more precise name.
+  DeclarationName getBaseEntity() { return DeclarationName(); }
+
+  /// \brief Sets the "base" location and entity when that
+  /// information is known based on another transformation.
+  ///
+  /// By default, the source location and entity are ignored. Subclasses can
+  /// override this function to provide a customized implementation.
+  void setBase(SourceLocation Loc, DeclarationName Entity) { }
+
+  /// \brief RAII object that temporarily sets the base location and entity
+  /// used for reporting diagnostics in types.
+  class TemporaryBase {
+    TreeTransform &Self;
+    SourceLocation OldLocation;
+    DeclarationName OldEntity;
+
+  public:
+    TemporaryBase(TreeTransform &Self, SourceLocation Location,
+                  DeclarationName Entity) : Self(Self) {
+      OldLocation = Self.getDerived().getBaseLocation();
+      OldEntity = Self.getDerived().getBaseEntity();
+      
+      if (Location.isValid())
+        Self.getDerived().setBase(Location, Entity);
+    }
+
+    ~TemporaryBase() {
+      Self.getDerived().setBase(OldLocation, OldEntity);
+    }
+  };
+
+  /// \brief Determine whether the given type \p T has already been
+  /// transformed.
+  ///
+  /// Subclasses can provide an alternative implementation of this routine
+  /// to short-circuit evaluation when it is known that a given type will
+  /// not change. For example, template instantiation need not traverse
+  /// non-dependent types.
+  bool AlreadyTransformed(QualType T) {
+    return T.isNull();
+  }
+
+  /// \brief Determine whether the given call argument should be dropped, e.g.,
+  /// because it is a default argument.
+  ///
+  /// Subclasses can provide an alternative implementation of this routine to
+  /// determine which kinds of call arguments get dropped. By default,
+  /// CXXDefaultArgument nodes are dropped (prior to transformation).
+  bool DropCallArgument(Expr *E) {
+    return E->isDefaultArgument();
+  }
+  
+  /// \brief Determine whether we should expand a pack expansion with the
+  /// given set of parameter packs into separate arguments by repeatedly
+  /// transforming the pattern.
+  ///
+  /// By default, the transformer never tries to expand pack expansions.
+  /// Subclasses can override this routine to provide different behavior.
+  ///
+  /// \param EllipsisLoc The location of the ellipsis that identifies the
+  /// pack expansion.
+  ///
+  /// \param PatternRange The source range that covers the entire pattern of
+  /// the pack expansion.
+  ///
+  /// \param Unexpanded The set of unexpanded parameter packs within the 
+  /// pattern.
+  ///
+  /// \param NumUnexpanded The number of unexpanded parameter packs in
+  /// \p Unexpanded.
+  ///
+  /// \param ShouldExpand Will be set to \c true if the transformer should
+  /// expand the corresponding pack expansions into separate arguments. When
+  /// set, \c NumExpansions must also be set.
+  ///
+  /// \param RetainExpansion Whether the caller should add an unexpanded
+  /// pack expansion after all of the expanded arguments. This is used
+  /// when extending explicitly-specified template argument packs per
+  /// C++0x [temp.arg.explicit]p9.
+  ///
+  /// \param NumExpansions The number of separate arguments that will be in
+  /// the expanded form of the corresponding pack expansion. This is both an
+  /// input and an output parameter, which can be set by the caller if the
+  /// number of expansions is known a priori (e.g., due to a prior substitution)
+  /// and will be set by the callee when the number of expansions is known.
+  /// The callee must set this value when \c ShouldExpand is \c true; it may
+  /// set this value in other cases.
+  ///
+  /// \returns true if an error occurred (e.g., because the parameter packs 
+  /// are to be instantiated with arguments of different lengths), false 
+  /// otherwise. If false, \c ShouldExpand (and possibly \c NumExpansions) 
+  /// must be set.
+  bool TryExpandParameterPacks(SourceLocation EllipsisLoc,
+                               SourceRange PatternRange,
+                             llvm::ArrayRef<UnexpandedParameterPack> Unexpanded,
+                               bool &ShouldExpand,
+                               bool &RetainExpansion,
+                               llvm::Optional<unsigned> &NumExpansions) {
+    ShouldExpand = false;
+    return false;
+  }
+  
+  /// \brief "Forget" about the partially-substituted pack template argument,
+  /// when performing an instantiation that must preserve the parameter pack
+  /// use.
+  ///
+  /// This routine is meant to be overridden by the template instantiator.
+  TemplateArgument ForgetPartiallySubstitutedPack() {
+    return TemplateArgument();
+  }
+  
+  /// \brief "Remember" the partially-substituted pack template argument
+  /// after performing an instantiation that must preserve the parameter pack
+  /// use.
+  ///
+  /// This routine is meant to be overridden by the template instantiator.
+  void RememberPartiallySubstitutedPack(TemplateArgument Arg) { }
+  
+  /// \brief Note to the derived class when a function parameter pack is
+  /// being expanded.
+  void ExpandingFunctionParameterPack(ParmVarDecl *Pack) { }
+                                      
+  /// \brief Transforms the given type into another type.
+  ///
+  /// By default, this routine transforms a type by creating a
+  /// TypeSourceInfo for it and delegating to the appropriate
+  /// function.  This is expensive, but we don't mind, because
+  /// this method is deprecated anyway;  all users should be
+  /// switched to storing TypeSourceInfos.
+  ///
+  /// \returns the transformed type.
+  QualType TransformType(QualType T);
+
+  /// \brief Transforms the given type-with-location into a new
+  /// type-with-location.
+  ///
+  /// By default, this routine transforms a type by delegating to the
+  /// appropriate TransformXXXType to build a new type.  Subclasses
+  /// may override this function (to take over all type
+  /// transformations) or some set of the TransformXXXType functions
+  /// to alter the transformation.
+  TypeSourceInfo *TransformType(TypeSourceInfo *DI);
+
+  /// \brief Transform the given type-with-location into a new
+  /// type, collecting location information in the given builder
+  /// as necessary.
+  ///
+  QualType TransformType(TypeLocBuilder &TLB, TypeLoc TL);
+
+  /// \brief Transform the given statement.
+  ///
+  /// By default, this routine transforms a statement by delegating to the
+  /// appropriate TransformXXXStmt function to transform a specific kind of
+  /// statement or the TransformExpr() function to transform an expression.
+  /// Subclasses may override this function to transform statements using some
+  /// other mechanism.
+  ///
+  /// \returns the transformed statement.
+  StmtResult TransformStmt(Stmt *S);
+
+  /// \brief Transform the given expression.
+  ///
+  /// By default, this routine transforms an expression by delegating to the
+  /// appropriate TransformXXXExpr function to build a new expression.
+  /// Subclasses may override this function to transform expressions using some
+  /// other mechanism.
+  ///
+  /// \returns the transformed expression.
+  ExprResult TransformExpr(Expr *E);
+
+  /// \brief Transform the given list of expressions.
+  ///
+  /// This routine transforms a list of expressions by invoking 
+  /// \c TransformExpr() for each subexpression. However, it also provides 
+  /// support for variadic templates by expanding any pack expansions (if the
+  /// derived class permits such expansion) along the way. When pack expansions
+  /// are present, the number of outputs may not equal the number of inputs.
+  ///
+  /// \param Inputs The set of expressions to be transformed.
+  ///
+  /// \param NumInputs The number of expressions in \c Inputs.
+  ///
+  /// \param IsCall If \c true, then this transform is being performed on
+  /// function-call arguments, and any arguments that should be dropped, will 
+  /// be.
+  ///
+  /// \param Outputs The transformed input expressions will be added to this
+  /// vector.
+  ///
+  /// \param ArgChanged If non-NULL, will be set \c true if any argument changed
+  /// due to transformation.
+  ///
+  /// \returns true if an error occurred, false otherwise.
+  bool TransformExprs(Expr **Inputs, unsigned NumInputs, bool IsCall,
+                      SmallVectorImpl<Expr *> &Outputs,
+                      bool *ArgChanged = 0);
+  
+  /// \brief Transform the given declaration, which is referenced from a type
+  /// or expression.
+  ///
+  /// By default, acts as the identity function on declarations, unless the
+  /// transformer has had to transform the declaration itself. Subclasses
+  /// may override this function to provide alternate behavior.
+  Decl *TransformDecl(SourceLocation Loc, Decl *D) { 
+    llvm::DenseMap<Decl *, Decl *>::iterator Known
+      = TransformedLocalDecls.find(D);
+    if (Known != TransformedLocalDecls.end())
+      return Known->second;
+    
+    return D; 
+  }
+
+  /// \brief Transform the attributes associated with the given declaration and 
+  /// place them on the new declaration.
+  ///
+  /// By default, this operation does nothing. Subclasses may override this
+  /// behavior to transform attributes.
+  void transformAttrs(Decl *Old, Decl *New) { }
+  
+  /// \brief Note that a local declaration has been transformed by this
+  /// transformer.
+  ///
+  /// Local declarations are typically transformed via a call to 
+  /// TransformDefinition. However, in some cases (e.g., lambda expressions),
+  /// the transformer itself has to transform the declarations. This routine
+  /// can be overridden by a subclass that keeps track of such mappings.
+  void transformedLocalDecl(Decl *Old, Decl *New) {
+    TransformedLocalDecls[Old] = New;
+  }
+  
+  /// \brief Transform the definition of the given declaration.
+  ///
+  /// By default, invokes TransformDecl() to transform the declaration.
+  /// Subclasses may override this function to provide alternate behavior.
+  Decl *TransformDefinition(SourceLocation Loc, Decl *D) { 
+    return getDerived().TransformDecl(Loc, D); 
+  }
+
+  /// \brief Transform the given declaration, which was the first part of a
+  /// nested-name-specifier in a member access expression.
+  ///
+  /// This specific declaration transformation only applies to the first 
+  /// identifier in a nested-name-specifier of a member access expression, e.g.,
+  /// the \c T in \c x->T::member
+  ///
+  /// By default, invokes TransformDecl() to transform the declaration.
+  /// Subclasses may override this function to provide alternate behavior.
+  NamedDecl *TransformFirstQualifierInScope(NamedDecl *D, SourceLocation Loc) { 
+    return cast_or_null<NamedDecl>(getDerived().TransformDecl(Loc, D)); 
+  }
+  
+  /// \brief Transform the given nested-name-specifier with source-location
+  /// information.
+  ///
+  /// By default, transforms all of the types and declarations within the
+  /// nested-name-specifier. Subclasses may override this function to provide
+  /// alternate behavior.
+  NestedNameSpecifierLoc TransformNestedNameSpecifierLoc(
+                                                    NestedNameSpecifierLoc NNS,
+                                          QualType ObjectType = QualType(),
+                                          NamedDecl *FirstQualifierInScope = 0);
+
+  /// \brief Transform the given declaration name.
+  ///
+  /// By default, transforms the types of conversion function, constructor,
+  /// and destructor names and then (if needed) rebuilds the declaration name.
+  /// Identifiers and selectors are returned unmodified. Sublcasses may
+  /// override this function to provide alternate behavior.
+  DeclarationNameInfo
+  TransformDeclarationNameInfo(const DeclarationNameInfo &NameInfo);
+
+  /// \brief Transform the given template name.
+  ///
+  /// \param SS The nested-name-specifier that qualifies the template
+  /// name. This nested-name-specifier must already have been transformed.
+  ///
+  /// \param Name The template name to transform.
+  ///
+  /// \param NameLoc The source location of the template name.
+  ///
+  /// \param ObjectType If we're translating a template name within a member 
+  /// access expression, this is the type of the object whose member template
+  /// is being referenced.
+  ///
+  /// \param FirstQualifierInScope If the first part of a nested-name-specifier
+  /// also refers to a name within the current (lexical) scope, this is the
+  /// declaration it refers to.
+  ///
+  /// By default, transforms the template name by transforming the declarations
+  /// and nested-name-specifiers that occur within the template name.
+  /// Subclasses may override this function to provide alternate behavior.
+  TemplateName TransformTemplateName(CXXScopeSpec &SS,
+                                     TemplateName Name,
+                                     SourceLocation NameLoc,
+                                     QualType ObjectType = QualType(),
+                                     NamedDecl *FirstQualifierInScope = 0);
+
+  /// \brief Transform the given template argument.
+  ///
+  /// By default, this operation transforms the type, expression, or
+  /// declaration stored within the template argument and constructs a
+  /// new template argument from the transformed result. Subclasses may
+  /// override this function to provide alternate behavior.
+  ///
+  /// Returns true if there was an error.
+  bool TransformTemplateArgument(const TemplateArgumentLoc &Input,
+                                 TemplateArgumentLoc &Output);
+
+  /// \brief Transform the given set of template arguments.
+  ///
+  /// By default, this operation transforms all of the template arguments 
+  /// in the input set using \c TransformTemplateArgument(), and appends
+  /// the transformed arguments to the output list.
+  ///
+  /// Note that this overload of \c TransformTemplateArguments() is merely
+  /// a convenience function. Subclasses that wish to override this behavior
+  /// should override the iterator-based member template version.
+  ///
+  /// \param Inputs The set of template arguments to be transformed.
+  ///
+  /// \param NumInputs The number of template arguments in \p Inputs.
+  ///
+  /// \param Outputs The set of transformed template arguments output by this
+  /// routine.
+  ///
+  /// Returns true if an error occurred.
+  bool TransformTemplateArguments(const TemplateArgumentLoc *Inputs,
+                                  unsigned NumInputs,
+                                  TemplateArgumentListInfo &Outputs) {
+    return TransformTemplateArguments(Inputs, Inputs + NumInputs, Outputs);
+  }
+
+  /// \brief Transform the given set of template arguments.
+  ///
+  /// By default, this operation transforms all of the template arguments 
+  /// in the input set using \c TransformTemplateArgument(), and appends
+  /// the transformed arguments to the output list. 
+  ///
+  /// \param First An iterator to the first template argument.
+  ///
+  /// \param Last An iterator one step past the last template argument.
+  ///
+  /// \param Outputs The set of transformed template arguments output by this
+  /// routine.
+  ///
+  /// Returns true if an error occurred.
+  template<typename InputIterator>
+  bool TransformTemplateArguments(InputIterator First,
+                                  InputIterator Last,
+                                  TemplateArgumentListInfo &Outputs);
+
+  /// \brief Fakes up a TemplateArgumentLoc for a given TemplateArgument.
+  void InventTemplateArgumentLoc(const TemplateArgument &Arg,
+                                 TemplateArgumentLoc &ArgLoc);
+
+  /// \brief Fakes up a TypeSourceInfo for a type.
+  TypeSourceInfo *InventTypeSourceInfo(QualType T) {
+    return SemaRef.Context.getTrivialTypeSourceInfo(T,
+                       getDerived().getBaseLocation());
+  }
+
+#define ABSTRACT_TYPELOC(CLASS, PARENT)
+#define TYPELOC(CLASS, PARENT)                                   \
+  QualType Transform##CLASS##Type(TypeLocBuilder &TLB, CLASS##TypeLoc T);
+#include "clang/AST/TypeLocNodes.def"
+
+  QualType TransformFunctionProtoType(TypeLocBuilder &TLB,
+                                      FunctionProtoTypeLoc TL,
+                                      CXXRecordDecl *ThisContext,
+                                      unsigned ThisTypeQuals);
+
+  StmtResult
+  TransformSEHHandler(Stmt *Handler);
+
+  QualType 
+  TransformTemplateSpecializationType(TypeLocBuilder &TLB,
+                                      TemplateSpecializationTypeLoc TL,
+                                      TemplateName Template);
+
+  QualType 
+  TransformDependentTemplateSpecializationType(TypeLocBuilder &TLB,
+                                      DependentTemplateSpecializationTypeLoc TL,
+                                               TemplateName Template,
+                                               CXXScopeSpec &SS);
+
+  QualType 
+  TransformDependentTemplateSpecializationType(TypeLocBuilder &TLB,
+                                               DependentTemplateSpecializationTypeLoc TL,
+                                         NestedNameSpecifierLoc QualifierLoc);
+
+  /// \brief Transforms the parameters of a function type into the
+  /// given vectors.
+  ///
+  /// The result vectors should be kept in sync; null entries in the
+  /// variables vector are acceptable.
+  ///
+  /// Return true on error.
+  bool TransformFunctionTypeParams(SourceLocation Loc,
+                                   ParmVarDecl **Params, unsigned NumParams,
+                                   const QualType *ParamTypes,
+                                   SmallVectorImpl<QualType> &PTypes,
+                                   SmallVectorImpl<ParmVarDecl*> *PVars);
+
+  /// \brief Transforms a single function-type parameter.  Return null
+  /// on error.
+  ///
+  /// \param indexAdjustment - A number to add to the parameter's
+  ///   scope index;  can be negative
+  ParmVarDecl *TransformFunctionTypeParam(ParmVarDecl *OldParm,
+                                          int indexAdjustment,
+                                        llvm::Optional<unsigned> NumExpansions,
+                                          bool ExpectParameterPack);
+
+  QualType TransformReferenceType(TypeLocBuilder &TLB, ReferenceTypeLoc TL);
+
+  StmtResult TransformCompoundStmt(CompoundStmt *S, bool IsStmtExpr);
+  ExprResult TransformCXXNamedCastExpr(CXXNamedCastExpr *E);
+
+#define STMT(Node, Parent)                        \
+  StmtResult Transform##Node(Node *S);
+#define EXPR(Node, Parent)                        \
+  ExprResult Transform##Node(Node *E);
+#define ABSTRACT_STMT(Stmt)
+#include "clang/AST/StmtNodes.inc"
+
+  /// \brief Build a new pointer type given its pointee type.
+  ///
+  /// By default, performs semantic analysis when building the pointer type.
+  /// Subclasses may override this routine to provide different behavior.
+  QualType RebuildPointerType(QualType PointeeType, SourceLocation Sigil);
+
+  /// \brief Build a new block pointer type given its pointee type.
+  ///
+  /// By default, performs semantic analysis when building the block pointer
+  /// type. Subclasses may override this routine to provide different behavior.
+  QualType RebuildBlockPointerType(QualType PointeeType, SourceLocation Sigil);
+
+  /// \brief Build a new reference type given the type it references.
+  ///
+  /// By default, performs semantic analysis when building the
+  /// reference type. Subclasses may override this routine to provide
+  /// different behavior.
+  ///
+  /// \param LValue whether the type was written with an lvalue sigil
+  /// or an rvalue sigil.
+  QualType RebuildReferenceType(QualType ReferentType,
+                                bool LValue,
+                                SourceLocation Sigil);
+
+  /// \brief Build a new member pointer type given the pointee type and the
+  /// class type it refers into.
+  ///
+  /// By default, performs semantic analysis when building the member pointer
+  /// type. Subclasses may override this routine to provide different behavior.
+  QualType RebuildMemberPointerType(QualType PointeeType, QualType ClassType,
+                                    SourceLocation Sigil);
+
+  /// \brief Build a new array type given the element type, size
+  /// modifier, size of the array (if known), size expression, and index type
+  /// qualifiers.
+  ///
+  /// By default, performs semantic analysis when building the array type.
+  /// Subclasses may override this routine to provide different behavior.
+  /// Also by default, all of the other Rebuild*Array
+  QualType RebuildArrayType(QualType ElementType,
+                            ArrayType::ArraySizeModifier SizeMod,
+                            const llvm::APInt *Size,
+                            Expr *SizeExpr,
+                            unsigned IndexTypeQuals,
+                            SourceRange BracketsRange);
+
+  /// \brief Build a new constant array type given the element type, size
+  /// modifier, (known) size of the array, and index type qualifiers.
+  ///
+  /// By default, performs semantic analysis when building the array type.
+  /// Subclasses may override this routine to provide different behavior.
+  QualType RebuildConstantArrayType(QualType ElementType,
+                                    ArrayType::ArraySizeModifier SizeMod,
+                                    const llvm::APInt &Size,
+                                    unsigned IndexTypeQuals,
+                                    SourceRange BracketsRange);
+
+  /// \brief Build a new incomplete array type given the element type, size
+  /// modifier, and index type qualifiers.
+  ///
+  /// By default, performs semantic analysis when building the array type.
+  /// Subclasses may override this routine to provide different behavior.
+  QualType RebuildIncompleteArrayType(QualType ElementType,
+                                      ArrayType::ArraySizeModifier SizeMod,
+                                      unsigned IndexTypeQuals,
+                                      SourceRange BracketsRange);
+
+  /// \brief Build a new variable-length array type given the element type,
+  /// size modifier, size expression, and index type qualifiers.
+  ///
+  /// By default, performs semantic analysis when building the array type.
+  /// Subclasses may override this routine to provide different behavior.
+  QualType RebuildVariableArrayType(QualType ElementType,
+                                    ArrayType::ArraySizeModifier SizeMod,
+                                    Expr *SizeExpr,
+                                    unsigned IndexTypeQuals,
+                                    SourceRange BracketsRange);
+
+  /// \brief Build a new dependent-sized array type given the element type,
+  /// size modifier, size expression, and index type qualifiers.
+  ///
+  /// By default, performs semantic analysis when building the array type.
+  /// Subclasses may override this routine to provide different behavior.
+  QualType RebuildDependentSizedArrayType(QualType ElementType,
+                                          ArrayType::ArraySizeModifier SizeMod,
+                                          Expr *SizeExpr,
+                                          unsigned IndexTypeQuals,
+                                          SourceRange BracketsRange);
+
+  /// \brief Build a new vector type given the element type and
+  /// number of elements.
+  ///
+  /// By default, performs semantic analysis when building the vector type.
+  /// Subclasses may override this routine to provide different behavior.
+  QualType RebuildVectorType(QualType ElementType, unsigned NumElements,
+                             VectorType::VectorKind VecKind);
+
+  /// \brief Build a new extended vector type given the element type and
+  /// number of elements.
+  ///
+  /// By default, performs semantic analysis when building the vector type.
+  /// Subclasses may override this routine to provide different behavior.
+  QualType RebuildExtVectorType(QualType ElementType, unsigned NumElements,
+                                SourceLocation AttributeLoc);
+
+  /// \brief Build a new potentially dependently-sized extended vector type
+  /// given the element type and number of elements.
+  ///
+  /// By default, performs semantic analysis when building the vector type.
+  /// Subclasses may override this routine to provide different behavior.
+  QualType RebuildDependentSizedExtVectorType(QualType ElementType,
+                                              Expr *SizeExpr,
+                                              SourceLocation AttributeLoc);
+
+  /// \brief Build a new function type.
+  ///
+  /// By default, performs semantic analysis when building the function type.
+  /// Subclasses may override this routine to provide different behavior.
+  QualType RebuildFunctionProtoType(QualType T,
+                                    QualType *ParamTypes,
+                                    unsigned NumParamTypes,
+                                    bool Variadic, bool HasTrailingReturn,
+                                    unsigned Quals,
+                                    RefQualifierKind RefQualifier,
+                                    const FunctionType::ExtInfo &Info);
+
+  /// \brief Build a new unprototyped function type.
+  QualType RebuildFunctionNoProtoType(QualType ResultType);
+
+  /// \brief Rebuild an unresolved typename type, given the decl that
+  /// the UnresolvedUsingTypenameDecl was transformed to.
+  QualType RebuildUnresolvedUsingType(Decl *D);
+
+  /// \brief Build a new typedef type.
+  QualType RebuildTypedefType(TypedefNameDecl *Typedef) {
+    return SemaRef.Context.getTypeDeclType(Typedef);
+  }
+
+  /// \brief Build a new class/struct/union type.
+  QualType RebuildRecordType(RecordDecl *Record) {
+    return SemaRef.Context.getTypeDeclType(Record);
+  }
+
+  /// \brief Build a new Enum type.
+  QualType RebuildEnumType(EnumDecl *Enum) {
+    return SemaRef.Context.getTypeDeclType(Enum);
+  }
+
+  /// \brief Build a new typeof(expr) type.
+  ///
+  /// By default, performs semantic analysis when building the typeof type.
+  /// Subclasses may override this routine to provide different behavior.
+  QualType RebuildTypeOfExprType(Expr *Underlying, SourceLocation Loc);
+
+  /// \brief Build a new typeof(type) type.
+  ///
+  /// By default, builds a new TypeOfType with the given underlying type.
+  QualType RebuildTypeOfType(QualType Underlying);
+
+  /// \brief Build a new unary transform type.
+  QualType RebuildUnaryTransformType(QualType BaseType,
+                                     UnaryTransformType::UTTKind UKind,
+                                     SourceLocation Loc);
+
+  /// \brief Build a new C++0x decltype type.
+  ///
+  /// By default, performs semantic analysis when building the decltype type.
+  /// Subclasses may override this routine to provide different behavior.
+  QualType RebuildDecltypeType(Expr *Underlying, SourceLocation Loc);
+
+  /// \brief Build a new C++0x auto type.
+  ///
+  /// By default, builds a new AutoType with the given deduced type.
+  QualType RebuildAutoType(QualType Deduced) {
+    return SemaRef.Context.getAutoType(Deduced);
+  }
+
+  /// \brief Build a new template specialization type.
+  ///
+  /// By default, performs semantic analysis when building the template
+  /// specialization type. Subclasses may override this routine to provide
+  /// different behavior.
+  QualType RebuildTemplateSpecializationType(TemplateName Template,
+                                             SourceLocation TemplateLoc,
+                                             TemplateArgumentListInfo &Args);
+
+  /// \brief Build a new parenthesized type.
+  ///
+  /// By default, builds a new ParenType type from the inner type.
+  /// Subclasses may override this routine to provide different behavior.
+  QualType RebuildParenType(QualType InnerType) {
+    return SemaRef.Context.getParenType(InnerType);
+  }
+
+  /// \brief Build a new qualified name type.
+  ///
+  /// By default, builds a new ElaboratedType type from the keyword,
+  /// the nested-name-specifier and the named type.
+  /// Subclasses may override this routine to provide different behavior.
+  QualType RebuildElaboratedType(SourceLocation KeywordLoc,
+                                 ElaboratedTypeKeyword Keyword,
+                                 NestedNameSpecifierLoc QualifierLoc,
+                                 QualType Named) {
+    return SemaRef.Context.getElaboratedType(Keyword, 
+                                         QualifierLoc.getNestedNameSpecifier(), 
+                                             Named);
+  }
+
+  /// \brief Build a new typename type that refers to a template-id.
+  ///
+  /// By default, builds a new DependentNameType type from the
+  /// nested-name-specifier and the given type. Subclasses may override
+  /// this routine to provide different behavior.
+  QualType RebuildDependentTemplateSpecializationType(
+                                          ElaboratedTypeKeyword Keyword,
+                                          NestedNameSpecifierLoc QualifierLoc,
+                                          const IdentifierInfo *Name,
+                                          SourceLocation NameLoc,
+                                          TemplateArgumentListInfo &Args) {
+    // Rebuild the template name.
+    // TODO: avoid TemplateName abstraction
+    CXXScopeSpec SS;
+    SS.Adopt(QualifierLoc);
+    TemplateName InstName 
+      = getDerived().RebuildTemplateName(SS, *Name, NameLoc, QualType(), 0);
+    
+    if (InstName.isNull())
+      return QualType();
+    
+    // If it's still dependent, make a dependent specialization.
+    if (InstName.getAsDependentTemplateName())
+      return SemaRef.Context.getDependentTemplateSpecializationType(Keyword, 
+                                          QualifierLoc.getNestedNameSpecifier(), 
+                                                                    Name, 
+                                                                    Args);
+    
+    // Otherwise, make an elaborated type wrapping a non-dependent
+    // specialization.
+    QualType T =
+    getDerived().RebuildTemplateSpecializationType(InstName, NameLoc, Args);
+    if (T.isNull()) return QualType();
+    
+    if (Keyword == ETK_None && QualifierLoc.getNestedNameSpecifier() == 0)
+      return T;
+    
+    return SemaRef.Context.getElaboratedType(Keyword, 
+                                       QualifierLoc.getNestedNameSpecifier(), 
+                                             T);
+  }
+
+  /// \brief Build a new typename type that refers to an identifier.
+  ///
+  /// By default, performs semantic analysis when building the typename type
+  /// (or elaborated type). Subclasses may override this routine to provide
+  /// different behavior.
+  QualType RebuildDependentNameType(ElaboratedTypeKeyword Keyword,
+                                    SourceLocation KeywordLoc,
+                                    NestedNameSpecifierLoc QualifierLoc,
+                                    const IdentifierInfo *Id,
+                                    SourceLocation IdLoc) {
+    CXXScopeSpec SS;
+    SS.Adopt(QualifierLoc);
+
+    if (QualifierLoc.getNestedNameSpecifier()->isDependent()) {
+      // If the name is still dependent, just build a new dependent name type.
+      if (!SemaRef.computeDeclContext(SS))
+        return SemaRef.Context.getDependentNameType(Keyword, 
+                                          QualifierLoc.getNestedNameSpecifier(), 
+                                                    Id);
+    }
+
+    if (Keyword == ETK_None || Keyword == ETK_Typename)
+      return SemaRef.CheckTypenameType(Keyword, KeywordLoc, QualifierLoc,
+                                       *Id, IdLoc);
+
+    TagTypeKind Kind = TypeWithKeyword::getTagTypeKindForKeyword(Keyword);
+
+    // We had a dependent elaborated-type-specifier that has been transformed
+    // into a non-dependent elaborated-type-specifier. Find the tag we're
+    // referring to.
+    LookupResult Result(SemaRef, Id, IdLoc, Sema::LookupTagName);
+    DeclContext *DC = SemaRef.computeDeclContext(SS, false);
+    if (!DC)
+      return QualType();
+
+    if (SemaRef.RequireCompleteDeclContext(SS, DC))
+      return QualType();
+
+    TagDecl *Tag = 0;
+    SemaRef.LookupQualifiedName(Result, DC);
+    switch (Result.getResultKind()) {
+      case LookupResult::NotFound:
+      case LookupResult::NotFoundInCurrentInstantiation:
+        break;
+        
+      case LookupResult::Found:
+        Tag = Result.getAsSingle<TagDecl>();
+        break;
+        
+      case LookupResult::FoundOverloaded:
+      case LookupResult::FoundUnresolvedValue:
+        llvm_unreachable("Tag lookup cannot find non-tags");
+        
+      case LookupResult::Ambiguous:
+        // Let the LookupResult structure handle ambiguities.
+        return QualType();
+    }
+
+    if (!Tag) {
+      // Check where the name exists but isn't a tag type and use that to emit
+      // better diagnostics.
+      LookupResult Result(SemaRef, Id, IdLoc, Sema::LookupTagName);
+      SemaRef.LookupQualifiedName(Result, DC);
+      switch (Result.getResultKind()) {
+        case LookupResult::Found:
+        case LookupResult::FoundOverloaded:
+        case LookupResult::FoundUnresolvedValue: {
+          NamedDecl *SomeDecl = Result.getRepresentativeDecl();
+          unsigned Kind = 0;
+          if (isa<TypedefDecl>(SomeDecl)) Kind = 1;
+          else if (isa<TypeAliasDecl>(SomeDecl)) Kind = 2;
+          else if (isa<ClassTemplateDecl>(SomeDecl)) Kind = 3;
+          SemaRef.Diag(IdLoc, diag::err_tag_reference_non_tag) << Kind;
+          SemaRef.Diag(SomeDecl->getLocation(), diag::note_declared_at);
+          break;
+        }
+        default:
+          // FIXME: Would be nice to highlight just the source range.
+          SemaRef.Diag(IdLoc, diag::err_not_tag_in_scope)
+            << Kind << Id << DC;
+          break;
+      }
+      return QualType();
+    }
+
+    if (!SemaRef.isAcceptableTagRedeclaration(Tag, Kind, /*isDefinition*/false,
+                                              IdLoc, *Id)) {
+      SemaRef.Diag(KeywordLoc, diag::err_use_with_wrong_tag) << Id;
+      SemaRef.Diag(Tag->getLocation(), diag::note_previous_use);
+      return QualType();
+    }
+
+    // Build the elaborated-type-specifier type.
+    QualType T = SemaRef.Context.getTypeDeclType(Tag);
+    return SemaRef.Context.getElaboratedType(Keyword, 
+                                         QualifierLoc.getNestedNameSpecifier(), 
+                                             T);
+  }
+
+  /// \brief Build a new pack expansion type.
+  ///
+  /// By default, builds a new PackExpansionType type from the given pattern.
+  /// Subclasses may override this routine to provide different behavior.
+  QualType RebuildPackExpansionType(QualType Pattern, 
+                                    SourceRange PatternRange,
+                                    SourceLocation EllipsisLoc,
+                                    llvm::Optional<unsigned> NumExpansions) {
+    return getSema().CheckPackExpansion(Pattern, PatternRange, EllipsisLoc,
+                                        NumExpansions);
+  }
+
+  /// \brief Build a new atomic type given its value type.
+  ///
+  /// By default, performs semantic analysis when building the atomic type.
+  /// Subclasses may override this routine to provide different behavior.
+  QualType RebuildAtomicType(QualType ValueType, SourceLocation KWLoc);
+
+  /// \brief Build a new template name given a nested name specifier, a flag
+  /// indicating whether the "template" keyword was provided, and the template
+  /// that the template name refers to.
+  ///
+  /// By default, builds the new template name directly. Subclasses may override
+  /// this routine to provide different behavior.
+  TemplateName RebuildTemplateName(CXXScopeSpec &SS,
+                                   bool TemplateKW,
+                                   TemplateDecl *Template);
+
+  /// \brief Build a new template name given a nested name specifier and the
+  /// name that is referred to as a template.
+  ///
+  /// By default, performs semantic analysis to determine whether the name can
+  /// be resolved to a specific template, then builds the appropriate kind of
+  /// template name. Subclasses may override this routine to provide different
+  /// behavior.
+  TemplateName RebuildTemplateName(CXXScopeSpec &SS,
+                                   const IdentifierInfo &Name,
+                                   SourceLocation NameLoc,
+                                   QualType ObjectType,
+                                   NamedDecl *FirstQualifierInScope);
+
+  /// \brief Build a new template name given a nested name specifier and the
+  /// overloaded operator name that is referred to as a template.
+  ///
+  /// By default, performs semantic analysis to determine whether the name can
+  /// be resolved to a specific template, then builds the appropriate kind of
+  /// template name. Subclasses may override this routine to provide different
+  /// behavior.
+  TemplateName RebuildTemplateName(CXXScopeSpec &SS,
+                                   OverloadedOperatorKind Operator,
+                                   SourceLocation NameLoc,
+                                   QualType ObjectType);
+
+  /// \brief Build a new template name given a template template parameter pack
+  /// and the 
+  ///
+  /// By default, performs semantic analysis to determine whether the name can
+  /// be resolved to a specific template, then builds the appropriate kind of
+  /// template name. Subclasses may override this routine to provide different
+  /// behavior.
+  TemplateName RebuildTemplateName(TemplateTemplateParmDecl *Param,
+                                   const TemplateArgument &ArgPack) {
+    return getSema().Context.getSubstTemplateTemplateParmPack(Param, ArgPack);
+  }
+
+  /// \brief Build a new compound statement.
+  ///
+  /// By default, performs semantic analysis to build the new statement.
+  /// Subclasses may override this routine to provide different behavior.
+  StmtResult RebuildCompoundStmt(SourceLocation LBraceLoc,
+                                       MultiStmtArg Statements,
+                                       SourceLocation RBraceLoc,
+                                       bool IsStmtExpr) {
+    return getSema().ActOnCompoundStmt(LBraceLoc, RBraceLoc, Statements,
+                                       IsStmtExpr);
+  }
+
+  /// \brief Build a new case statement.
+  ///
+  /// By default, performs semantic analysis to build the new statement.
+  /// Subclasses may override this routine to provide different behavior.
+  StmtResult RebuildCaseStmt(SourceLocation CaseLoc,
+                                   Expr *LHS,
+                                   SourceLocation EllipsisLoc,
+                                   Expr *RHS,
+                                   SourceLocation ColonLoc) {
+    return getSema().ActOnCaseStmt(CaseLoc, LHS, EllipsisLoc, RHS,
+                                   ColonLoc);
+  }
+
+  /// \brief Attach the body to a new case statement.
+  ///
+  /// By default, performs semantic analysis to build the new statement.
+  /// Subclasses may override this routine to provide different behavior.
+  StmtResult RebuildCaseStmtBody(Stmt *S, Stmt *Body) {
+    getSema().ActOnCaseStmtBody(S, Body);
+    return S;
+  }
+
+  /// \brief Build a new default statement.
+  ///
+  /// By default, performs semantic analysis to build the new statement.
+  /// Subclasses may override this routine to provide different behavior.
+  StmtResult RebuildDefaultStmt(SourceLocation DefaultLoc,
+                                      SourceLocation ColonLoc,
+                                      Stmt *SubStmt) {
+    return getSema().ActOnDefaultStmt(DefaultLoc, ColonLoc, SubStmt,
+                                      /*CurScope=*/0);
+  }
+
+  /// \brief Build a new label statement.
+  ///
+  /// By default, performs semantic analysis to build the new statement.
+  /// Subclasses may override this routine to provide different behavior.
+  StmtResult RebuildLabelStmt(SourceLocation IdentLoc, LabelDecl *L,
+                              SourceLocation ColonLoc, Stmt *SubStmt) {
+    return SemaRef.ActOnLabelStmt(IdentLoc, L, ColonLoc, SubStmt);
+  }
+
+  /// \brief Build a new label statement.
+  ///
+  /// By default, performs semantic analysis to build the new statement.
+  /// Subclasses may override this routine to provide different behavior.
+  StmtResult RebuildAttributedStmt(SourceLocation AttrLoc, const AttrVec &Attrs,
+                                   Stmt *SubStmt) {
+    return SemaRef.ActOnAttributedStmt(AttrLoc, Attrs, SubStmt);
+  }
+
+  /// \brief Build a new "if" statement.
+  ///
+  /// By default, performs semantic analysis to build the new statement.
+  /// Subclasses may override this routine to provide different behavior.
+  StmtResult RebuildIfStmt(SourceLocation IfLoc, Sema::FullExprArg Cond,
+                           VarDecl *CondVar, Stmt *Then, 
+                           SourceLocation ElseLoc, Stmt *Else) {
+    return getSema().ActOnIfStmt(IfLoc, Cond, CondVar, Then, ElseLoc, Else);
+  }
+
+  /// \brief Start building a new switch statement.
+  ///
+  /// By default, performs semantic analysis to build the new statement.
+  /// Subclasses may override this routine to provide different behavior.
+  StmtResult RebuildSwitchStmtStart(SourceLocation SwitchLoc,
+                                    Expr *Cond, VarDecl *CondVar) {
+    return getSema().ActOnStartOfSwitchStmt(SwitchLoc, Cond, 
+                                            CondVar);
+  }
+
+  /// \brief Attach the body to the switch statement.
+  ///
+  /// By default, performs semantic analysis to build the new statement.
+  /// Subclasses may override this routine to provide different behavior.
+  StmtResult RebuildSwitchStmtBody(SourceLocation SwitchLoc,
+                                   Stmt *Switch, Stmt *Body) {
+    return getSema().ActOnFinishSwitchStmt(SwitchLoc, Switch, Body);
+  }
+
+  /// \brief Build a new while statement.
+  ///
+  /// By default, performs semantic analysis to build the new statement.
+  /// Subclasses may override this routine to provide different behavior.
+  StmtResult RebuildWhileStmt(SourceLocation WhileLoc, Sema::FullExprArg Cond,
+                              VarDecl *CondVar, Stmt *Body) {
+    return getSema().ActOnWhileStmt(WhileLoc, Cond, CondVar, Body);
+  }
+
+  /// \brief Build a new do-while statement.
+  ///
+  /// By default, performs semantic analysis to build the new statement.
+  /// Subclasses may override this routine to provide different behavior.
+  StmtResult RebuildDoStmt(SourceLocation DoLoc, Stmt *Body,
+                           SourceLocation WhileLoc, SourceLocation LParenLoc,
+                           Expr *Cond, SourceLocation RParenLoc) {
+    return getSema().ActOnDoStmt(DoLoc, Body, WhileLoc, LParenLoc,
+                                 Cond, RParenLoc);
+  }
+
+  /// \brief Build a new for statement.
+  ///
+  /// By default, performs semantic analysis to build the new statement.
+  /// Subclasses may override this routine to provide different behavior.
+  StmtResult RebuildForStmt(SourceLocation ForLoc, SourceLocation LParenLoc,
+                            Stmt *Init, Sema::FullExprArg Cond, 
+                            VarDecl *CondVar, Sema::FullExprArg Inc,
+                            SourceLocation RParenLoc, Stmt *Body) {
+    return getSema().ActOnForStmt(ForLoc, LParenLoc, Init, Cond, 
+                                  CondVar, Inc, RParenLoc, Body);
+  }
+
+  /// \brief Build a new goto statement.
+  ///
+  /// By default, performs semantic analysis to build the new statement.
+  /// Subclasses may override this routine to provide different behavior.
+  StmtResult RebuildGotoStmt(SourceLocation GotoLoc, SourceLocation LabelLoc,
+                             LabelDecl *Label) {
+    return getSema().ActOnGotoStmt(GotoLoc, LabelLoc, Label);
+  }
+
+  /// \brief Build a new indirect goto statement.
+  ///
+  /// By default, performs semantic analysis to build the new statement.
+  /// Subclasses may override this routine to provide different behavior.
+  StmtResult RebuildIndirectGotoStmt(SourceLocation GotoLoc,
+                                     SourceLocation StarLoc,
+                                     Expr *Target) {
+    return getSema().ActOnIndirectGotoStmt(GotoLoc, StarLoc, Target);
+  }
+
+  /// \brief Build a new return statement.
+  ///
+  /// By default, performs semantic analysis to build the new statement.
+  /// Subclasses may override this routine to provide different behavior.
+  StmtResult RebuildReturnStmt(SourceLocation ReturnLoc, Expr *Result) {
+    return getSema().ActOnReturnStmt(ReturnLoc, Result);
+  }
+
+  /// \brief Build a new declaration statement.
+  ///
+  /// By default, performs semantic analysis to build the new statement.
+  /// Subclasses may override this routine to provide different behavior.
+  StmtResult RebuildDeclStmt(Decl **Decls, unsigned NumDecls,
+                                   SourceLocation StartLoc,
+                                   SourceLocation EndLoc) {
+    Sema::DeclGroupPtrTy DG = getSema().BuildDeclaratorGroup(Decls, NumDecls);
+    return getSema().ActOnDeclStmt(DG, StartLoc, EndLoc);
+  }
+
+  /// \brief Build a new inline asm statement.
+  ///
+  /// By default, performs semantic analysis to build the new statement.
+  /// Subclasses may override this routine to provide different behavior.
+  StmtResult RebuildAsmStmt(SourceLocation AsmLoc,
+                                  bool IsSimple,
+                                  bool IsVolatile,
+                                  unsigned NumOutputs,
+                                  unsigned NumInputs,
+                                  IdentifierInfo **Names,
+                                  MultiExprArg Constraints,
+                                  MultiExprArg Exprs,
+                                  Expr *AsmString,
+                                  MultiExprArg Clobbers,
+                                  SourceLocation RParenLoc,
+                                  bool MSAsm) {
+    return getSema().ActOnAsmStmt(AsmLoc, IsSimple, IsVolatile, NumOutputs, 
+                                  NumInputs, Names, move(Constraints),
+                                  Exprs, AsmString, Clobbers,
+                                  RParenLoc, MSAsm);
+  }
+
+  /// \brief Build a new Objective-C @try statement.
+  ///
+  /// By default, performs semantic analysis to build the new statement.
+  /// Subclasses may override this routine to provide different behavior.
+  StmtResult RebuildObjCAtTryStmt(SourceLocation AtLoc,
+                                        Stmt *TryBody,
+                                        MultiStmtArg CatchStmts,
+                                        Stmt *Finally) {
+    return getSema().ActOnObjCAtTryStmt(AtLoc, TryBody, move(CatchStmts),
+                                        Finally);
+  }
+
+  /// \brief Rebuild an Objective-C exception declaration.
+  ///
+  /// By default, performs semantic analysis to build the new declaration.
+  /// Subclasses may override this routine to provide different behavior.
+  VarDecl *RebuildObjCExceptionDecl(VarDecl *ExceptionDecl,
+                                    TypeSourceInfo *TInfo, QualType T) {
+    return getSema().BuildObjCExceptionDecl(TInfo, T,
+                                            ExceptionDecl->getInnerLocStart(),
+                                            ExceptionDecl->getLocation(),
+                                            ExceptionDecl->getIdentifier());
+  }
+  
+  /// \brief Build a new Objective-C @catch statement.
+  ///
+  /// By default, performs semantic analysis to build the new statement.
+  /// Subclasses may override this routine to provide different behavior.
+  StmtResult RebuildObjCAtCatchStmt(SourceLocation AtLoc,
+                                          SourceLocation RParenLoc,
+                                          VarDecl *Var,
+                                          Stmt *Body) {
+    return getSema().ActOnObjCAtCatchStmt(AtLoc, RParenLoc,
+                                          Var, Body);
+  }
+  
+  /// \brief Build a new Objective-C @finally statement.
+  ///
+  /// By default, performs semantic analysis to build the new statement.
+  /// Subclasses may override this routine to provide different behavior.
+  StmtResult RebuildObjCAtFinallyStmt(SourceLocation AtLoc,
+                                            Stmt *Body) {
+    return getSema().ActOnObjCAtFinallyStmt(AtLoc, Body);
+  }
+  
+  /// \brief Build a new Objective-C @throw statement.
+  ///
+  /// By default, performs semantic analysis to build the new statement.
+  /// Subclasses may override this routine to provide different behavior.
+  StmtResult RebuildObjCAtThrowStmt(SourceLocation AtLoc,
+                                          Expr *Operand) {
+    return getSema().BuildObjCAtThrowStmt(AtLoc, Operand);
+  }
+  
+  /// \brief Rebuild the operand to an Objective-C @synchronized statement.
+  ///
+  /// By default, performs semantic analysis to build the new statement.
+  /// Subclasses may override this routine to provide different behavior.
+  ExprResult RebuildObjCAtSynchronizedOperand(SourceLocation atLoc,
+                                              Expr *object) {
+    return getSema().ActOnObjCAtSynchronizedOperand(atLoc, object);
+  }
+
+  /// \brief Build a new Objective-C @synchronized statement.
+  ///
+  /// By default, performs semantic analysis to build the new statement.
+  /// Subclasses may override this routine to provide different behavior.
+  StmtResult RebuildObjCAtSynchronizedStmt(SourceLocation AtLoc,
+                                           Expr *Object, Stmt *Body) {
+    return getSema().ActOnObjCAtSynchronizedStmt(AtLoc, Object, Body);
+  }
+
+  /// \brief Build a new Objective-C @autoreleasepool statement.
+  ///
+  /// By default, performs semantic analysis to build the new statement.
+  /// Subclasses may override this routine to provide different behavior.
+  StmtResult RebuildObjCAutoreleasePoolStmt(SourceLocation AtLoc,
+                                            Stmt *Body) {
+    return getSema().ActOnObjCAutoreleasePoolStmt(AtLoc, Body);
+  }
+
+  /// \brief Build the collection operand to a new Objective-C fast
+  /// enumeration statement.
+  ///
+  /// By default, performs semantic analysis to build the new statement.
+  /// Subclasses may override this routine to provide different behavior.
+  ExprResult RebuildObjCForCollectionOperand(SourceLocation forLoc,
+                                             Expr *collection) {
+    return getSema().ActOnObjCForCollectionOperand(forLoc, collection);
+  }
+
+  /// \brief Build a new Objective-C fast enumeration statement.
+  ///
+  /// By default, performs semantic analysis to build the new statement.
+  /// Subclasses may override this routine to provide different behavior.
+  StmtResult RebuildObjCForCollectionStmt(SourceLocation ForLoc,
+                                          SourceLocation LParenLoc,
+                                          Stmt *Element,
+                                          Expr *Collection,
+                                          SourceLocation RParenLoc,
+                                          Stmt *Body) {
+    return getSema().ActOnObjCForCollectionStmt(ForLoc, LParenLoc,
+                                                Element, 
+                                                Collection,
+                                                RParenLoc,
+                                                Body);
+  }
+  
+  /// \brief Build a new C++ exception declaration.
+  ///
+  /// By default, performs semantic analysis to build the new decaration.
+  /// Subclasses may override this routine to provide different behavior.
+  VarDecl *RebuildExceptionDecl(VarDecl *ExceptionDecl,
+                                TypeSourceInfo *Declarator,
+                                SourceLocation StartLoc,
+                                SourceLocation IdLoc,
+                                IdentifierInfo *Id) {
+    VarDecl *Var = getSema().BuildExceptionDeclaration(0, Declarator,
+                                                       StartLoc, IdLoc, Id);
+    if (Var)
+      getSema().CurContext->addDecl(Var);
+    return Var;
+  }
+
+  /// \brief Build a new C++ catch statement.
+  ///
+  /// By default, performs semantic analysis to build the new statement.
+  /// Subclasses may override this routine to provide different behavior.
+  StmtResult RebuildCXXCatchStmt(SourceLocation CatchLoc,
+                                 VarDecl *ExceptionDecl,
+                                 Stmt *Handler) {
+    return Owned(new (getSema().Context) CXXCatchStmt(CatchLoc, ExceptionDecl,
+                                                      Handler));
+  }
+
+  /// \brief Build a new C++ try statement.
+  ///
+  /// By default, performs semantic analysis to build the new statement.
+  /// Subclasses may override this routine to provide different behavior.
+  StmtResult RebuildCXXTryStmt(SourceLocation TryLoc,
+                               Stmt *TryBlock,
+                               MultiStmtArg Handlers) {
+    return getSema().ActOnCXXTryBlock(TryLoc, TryBlock, move(Handlers));
+  }
+
+  /// \brief Build a new C++0x range-based for statement.
+  ///
+  /// By default, performs semantic analysis to build the new statement.
+  /// Subclasses may override this routine to provide different behavior.
+  StmtResult RebuildCXXForRangeStmt(SourceLocation ForLoc,
+                                    SourceLocation ColonLoc,
+                                    Stmt *Range, Stmt *BeginEnd,
+                                    Expr *Cond, Expr *Inc,
+                                    Stmt *LoopVar,
+                                    SourceLocation RParenLoc) {
+    return getSema().BuildCXXForRangeStmt(ForLoc, ColonLoc, Range, BeginEnd,
+                                          Cond, Inc, LoopVar, RParenLoc);
+  }
+
+  /// \brief Build a new C++0x range-based for statement.
+  ///
+  /// By default, performs semantic analysis to build the new statement.
+  /// Subclasses may override this routine to provide different behavior.
+  StmtResult RebuildMSDependentExistsStmt(SourceLocation KeywordLoc, 
+                                          bool IsIfExists,
+                                          NestedNameSpecifierLoc QualifierLoc,
+                                          DeclarationNameInfo NameInfo,
+                                          Stmt *Nested) {
+    return getSema().BuildMSDependentExistsStmt(KeywordLoc, IsIfExists,
+                                                QualifierLoc, NameInfo, Nested);
+  }
+
+  /// \brief Attach body to a C++0x range-based for statement.
+  ///
+  /// By default, performs semantic analysis to finish the new statement.
+  /// Subclasses may override this routine to provide different behavior.
+  StmtResult FinishCXXForRangeStmt(Stmt *ForRange, Stmt *Body) {
+    return getSema().FinishCXXForRangeStmt(ForRange, Body);
+  }
+  
+  StmtResult RebuildSEHTryStmt(bool IsCXXTry,
+                               SourceLocation TryLoc,
+                               Stmt *TryBlock,
+                               Stmt *Handler) {
+    return getSema().ActOnSEHTryBlock(IsCXXTry,TryLoc,TryBlock,Handler);
+  }
+
+  StmtResult RebuildSEHExceptStmt(SourceLocation Loc,
+                                  Expr *FilterExpr,
+                                  Stmt *Block) {
+    return getSema().ActOnSEHExceptBlock(Loc,FilterExpr,Block);
+  }
+
+  StmtResult RebuildSEHFinallyStmt(SourceLocation Loc,
+                                   Stmt *Block) {
+    return getSema().ActOnSEHFinallyBlock(Loc,Block);
+  }
+
+  /// \brief Build a new expression that references a declaration.
+  ///
+  /// By default, performs semantic analysis to build the new expression.
+  /// Subclasses may override this routine to provide different behavior.
+  ExprResult RebuildDeclarationNameExpr(const CXXScopeSpec &SS,
+                                        LookupResult &R,
+                                        bool RequiresADL) {
+    return getSema().BuildDeclarationNameExpr(SS, R, RequiresADL);
+  }
+
+
+  /// \brief Build a new expression that references a declaration.
+  ///
+  /// By default, performs semantic analysis to build the new expression.
+  /// Subclasses may override this routine to provide different behavior.
+  ExprResult RebuildDeclRefExpr(NestedNameSpecifierLoc QualifierLoc,
+                                ValueDecl *VD,
+                                const DeclarationNameInfo &NameInfo,
+                                TemplateArgumentListInfo *TemplateArgs) {
+    CXXScopeSpec SS;
+    SS.Adopt(QualifierLoc);
+
+    // FIXME: loses template args.
+
+    return getSema().BuildDeclarationNameExpr(SS, NameInfo, VD);
+  }
+
+  /// \brief Build a new expression in parentheses.
+  ///
+  /// By default, performs semantic analysis to build the new expression.
+  /// Subclasses may override this routine to provide different behavior.
+  ExprResult RebuildParenExpr(Expr *SubExpr, SourceLocation LParen,
+                                    SourceLocation RParen) {
+    return getSema().ActOnParenExpr(LParen, RParen, SubExpr);
+  }
+
+  /// \brief Build a new pseudo-destructor expression.
+  ///
+  /// By default, performs semantic analysis to build the new expression.
+  /// Subclasses may override this routine to provide different behavior.
+  ExprResult RebuildCXXPseudoDestructorExpr(Expr *Base,
+                                            SourceLocation OperatorLoc,
+                                            bool isArrow,
+                                            CXXScopeSpec &SS,
+                                            TypeSourceInfo *ScopeType,
+                                            SourceLocation CCLoc,
+                                            SourceLocation TildeLoc,
+                                        PseudoDestructorTypeStorage Destroyed);
+
+  /// \brief Build a new unary operator expression.
+  ///
+  /// By default, performs semantic analysis to build the new expression.
+  /// Subclasses may override this routine to provide different behavior.
+  ExprResult RebuildUnaryOperator(SourceLocation OpLoc,
+                                        UnaryOperatorKind Opc,
+                                        Expr *SubExpr) {
+    return getSema().BuildUnaryOp(/*Scope=*/0, OpLoc, Opc, SubExpr);
+  }
+
+  /// \brief Build a new builtin offsetof expression.
+  ///
+  /// By default, performs semantic analysis to build the new expression.
+  /// Subclasses may override this routine to provide different behavior.
+  ExprResult RebuildOffsetOfExpr(SourceLocation OperatorLoc,
+                                       TypeSourceInfo *Type,
+                                       Sema::OffsetOfComponent *Components,
+                                       unsigned NumComponents,
+                                       SourceLocation RParenLoc) {
+    return getSema().BuildBuiltinOffsetOf(OperatorLoc, Type, Components,
+                                          NumComponents, RParenLoc);
+  }
+  
+  /// \brief Build a new sizeof, alignof or vec_step expression with a 
+  /// type argument.
+  ///
+  /// By default, performs semantic analysis to build the new expression.
+  /// Subclasses may override this routine to provide different behavior.
+  ExprResult RebuildUnaryExprOrTypeTrait(TypeSourceInfo *TInfo,
+                                         SourceLocation OpLoc,
+                                         UnaryExprOrTypeTrait ExprKind,
+                                         SourceRange R) {
+    return getSema().CreateUnaryExprOrTypeTraitExpr(TInfo, OpLoc, ExprKind, R);
+  }
+
+  /// \brief Build a new sizeof, alignof or vec step expression with an
+  /// expression argument.
+  ///
+  /// By default, performs semantic analysis to build the new expression.
+  /// Subclasses may override this routine to provide different behavior.
+  ExprResult RebuildUnaryExprOrTypeTrait(Expr *SubExpr, SourceLocation OpLoc,
+                                         UnaryExprOrTypeTrait ExprKind,
+                                         SourceRange R) {
+    ExprResult Result
+      = getSema().CreateUnaryExprOrTypeTraitExpr(SubExpr, OpLoc, ExprKind);
+    if (Result.isInvalid())
+      return ExprError();
+
+    return move(Result);
+  }
+
+  /// \brief Build a new array subscript expression.
+  ///
+  /// By default, performs semantic analysis to build the new expression.
+  /// Subclasses may override this routine to provide different behavior.
+  ExprResult RebuildArraySubscriptExpr(Expr *LHS,
+                                             SourceLocation LBracketLoc,
+                                             Expr *RHS,
+                                             SourceLocation RBracketLoc) {
+    return getSema().ActOnArraySubscriptExpr(/*Scope=*/0, LHS,
+                                             LBracketLoc, RHS,
+                                             RBracketLoc);
+  }
+
+  /// \brief Build a new call expression.
+  ///
+  /// By default, performs semantic analysis to build the new expression.
+  /// Subclasses may override this routine to provide different behavior.
+  ExprResult RebuildCallExpr(Expr *Callee, SourceLocation LParenLoc,
+                                   MultiExprArg Args,
+                                   SourceLocation RParenLoc,
+                                   Expr *ExecConfig = 0) {
+    return getSema().ActOnCallExpr(/*Scope=*/0, Callee, LParenLoc,
+                                   move(Args), RParenLoc, ExecConfig);
+  }
+
+  /// \brief Build a new member access expression.
+  ///
+  /// By default, performs semantic analysis to build the new expression.
+  /// Subclasses may override this routine to provide different behavior.
+  ExprResult RebuildMemberExpr(Expr *Base, SourceLocation OpLoc,
+                               bool isArrow,
+                               NestedNameSpecifierLoc QualifierLoc,
+                               SourceLocation TemplateKWLoc,
+                               const DeclarationNameInfo &MemberNameInfo,
+                               ValueDecl *Member,
+                               NamedDecl *FoundDecl,
+                        const TemplateArgumentListInfo *ExplicitTemplateArgs,
+                               NamedDecl *FirstQualifierInScope) {
+    ExprResult BaseResult = getSema().PerformMemberExprBaseConversion(Base,
+                                                                      isArrow);
+    if (!Member->getDeclName()) {
+      // We have a reference to an unnamed field.  This is always the
+      // base of an anonymous struct/union member access, i.e. the
+      // field is always of record type.
+      assert(!QualifierLoc && "Can't have an unnamed field with a qualifier!");
+      assert(Member->getType()->isRecordType() &&
+             "unnamed member not of record type?");
+
+      BaseResult =
+        getSema().PerformObjectMemberConversion(BaseResult.take(),
+                                                QualifierLoc.getNestedNameSpecifier(),
+                                                FoundDecl, Member);
+      if (BaseResult.isInvalid())
+        return ExprError();
+      Base = BaseResult.take();
+      ExprValueKind VK = isArrow ? VK_LValue : Base->getValueKind();
+      MemberExpr *ME =
+        new (getSema().Context) MemberExpr(Base, isArrow,
+                                           Member, MemberNameInfo,
+                                           cast<FieldDecl>(Member)->getType(),
+                                           VK, OK_Ordinary);
+      return getSema().Owned(ME);
+    }
+
+    CXXScopeSpec SS;
+    SS.Adopt(QualifierLoc);
+
+    Base = BaseResult.take();
+    QualType BaseType = Base->getType();
+
+    // FIXME: this involves duplicating earlier analysis in a lot of
+    // cases; we should avoid this when possible.
+    LookupResult R(getSema(), MemberNameInfo, Sema::LookupMemberName);
+    R.addDecl(FoundDecl);
+    R.resolveKind();
+
+    return getSema().BuildMemberReferenceExpr(Base, BaseType, OpLoc, isArrow,
+                                              SS, TemplateKWLoc,
+                                              FirstQualifierInScope,
+                                              R, ExplicitTemplateArgs);
+  }
+
+  /// \brief Build a new binary operator expression.
+  ///
+  /// By default, performs semantic analysis to build the new expression.
+  /// Subclasses may override this routine to provide different behavior.
+  ExprResult RebuildBinaryOperator(SourceLocation OpLoc,
+                                         BinaryOperatorKind Opc,
+                                         Expr *LHS, Expr *RHS) {
+    return getSema().BuildBinOp(/*Scope=*/0, OpLoc, Opc, LHS, RHS);
+  }
+
+  /// \brief Build a new conditional operator expression.
+  ///
+  /// By default, performs semantic analysis to build the new expression.
+  /// Subclasses may override this routine to provide different behavior.
+  ExprResult RebuildConditionalOperator(Expr *Cond,
+                                        SourceLocation QuestionLoc,
+                                        Expr *LHS,
+                                        SourceLocation ColonLoc,
+                                        Expr *RHS) {
+    return getSema().ActOnConditionalOp(QuestionLoc, ColonLoc, Cond,
+                                        LHS, RHS);
+  }
+
+  /// \brief Build a new C-style cast expression.
+  ///
+  /// By default, performs semantic analysis to build the new expression.
+  /// Subclasses may override this routine to provide different behavior.
+  ExprResult RebuildCStyleCastExpr(SourceLocation LParenLoc,
+                                         TypeSourceInfo *TInfo,
+                                         SourceLocation RParenLoc,
+                                         Expr *SubExpr) {
+    return getSema().BuildCStyleCastExpr(LParenLoc, TInfo, RParenLoc,
+                                         SubExpr);
+  }
+
+  /// \brief Build a new compound literal expression.
+  ///
+  /// By default, performs semantic analysis to build the new expression.
+  /// Subclasses may override this routine to provide different behavior.
+  ExprResult RebuildCompoundLiteralExpr(SourceLocation LParenLoc,
+                                              TypeSourceInfo *TInfo,
+                                              SourceLocation RParenLoc,
+                                              Expr *Init) {
+    return getSema().BuildCompoundLiteralExpr(LParenLoc, TInfo, RParenLoc,
+                                              Init);
+  }
+
+  /// \brief Build a new extended vector element access expression.
+  ///
+  /// By default, performs semantic analysis to build the new expression.
+  /// Subclasses may override this routine to provide different behavior.
+  ExprResult RebuildExtVectorElementExpr(Expr *Base,
+                                               SourceLocation OpLoc,
+                                               SourceLocation AccessorLoc,
+                                               IdentifierInfo &Accessor) {
+
+    CXXScopeSpec SS;
+    DeclarationNameInfo NameInfo(&Accessor, AccessorLoc);
+    return getSema().BuildMemberReferenceExpr(Base, Base->getType(),
+                                              OpLoc, /*IsArrow*/ false,
+                                              SS, SourceLocation(),
+                                              /*FirstQualifierInScope*/ 0,
+                                              NameInfo,
+                                              /* TemplateArgs */ 0);
+  }
+
+  /// \brief Build a new initializer list expression.
+  ///
+  /// By default, performs semantic analysis to build the new expression.
+  /// Subclasses may override this routine to provide different behavior.
+  ExprResult RebuildInitList(SourceLocation LBraceLoc,
+                             MultiExprArg Inits,
+                             SourceLocation RBraceLoc,
+                             QualType ResultTy) {
+    ExprResult Result
+      = SemaRef.ActOnInitList(LBraceLoc, move(Inits), RBraceLoc);
+    if (Result.isInvalid() || ResultTy->isDependentType())
+      return move(Result);
+    
+    // Patch in the result type we were given, which may have been computed
+    // when the initial InitListExpr was built.
+    InitListExpr *ILE = cast<InitListExpr>((Expr *)Result.get());
+    ILE->setType(ResultTy);
+    return move(Result);
+  }
+
+  /// \brief Build a new designated initializer expression.
+  ///
+  /// By default, performs semantic analysis to build the new expression.
+  /// Subclasses may override this routine to provide different behavior.
+  ExprResult RebuildDesignatedInitExpr(Designation &Desig,
+                                             MultiExprArg ArrayExprs,
+                                             SourceLocation EqualOrColonLoc,
+                                             bool GNUSyntax,
+                                             Expr *Init) {
+    ExprResult Result
+      = SemaRef.ActOnDesignatedInitializer(Desig, EqualOrColonLoc, GNUSyntax,
+                                           Init);
+    if (Result.isInvalid())
+      return ExprError();
+
+    ArrayExprs.release();
+    return move(Result);
+  }
+
+  /// \brief Build a new value-initialized expression.
+  ///
+  /// By default, builds the implicit value initialization without performing
+  /// any semantic analysis. Subclasses may override this routine to provide
+  /// different behavior.
+  ExprResult RebuildImplicitValueInitExpr(QualType T) {
+    return SemaRef.Owned(new (SemaRef.Context) ImplicitValueInitExpr(T));
+  }
+
+  /// \brief Build a new \c va_arg expression.
+  ///
+  /// By default, performs semantic analysis to build the new expression.
+  /// Subclasses may override this routine to provide different behavior.
+  ExprResult RebuildVAArgExpr(SourceLocation BuiltinLoc,
+                                    Expr *SubExpr, TypeSourceInfo *TInfo,
+                                    SourceLocation RParenLoc) {
+    return getSema().BuildVAArgExpr(BuiltinLoc,
+                                    SubExpr, TInfo,
+                                    RParenLoc);
+  }
+
+  /// \brief Build a new expression list in parentheses.
+  ///
+  /// By default, performs semantic analysis to build the new expression.
+  /// Subclasses may override this routine to provide different behavior.
+  ExprResult RebuildParenListExpr(SourceLocation LParenLoc,
+                                  MultiExprArg SubExprs,
+                                  SourceLocation RParenLoc) {
+    return getSema().ActOnParenListExpr(LParenLoc, RParenLoc, move(SubExprs));
+  }
+
+  /// \brief Build a new address-of-label expression.
+  ///
+  /// By default, performs semantic analysis, using the name of the label
+  /// rather than attempting to map the label statement itself.
+  /// Subclasses may override this routine to provide different behavior.
+  ExprResult RebuildAddrLabelExpr(SourceLocation AmpAmpLoc,
+                                  SourceLocation LabelLoc, LabelDecl *Label) {
+    return getSema().ActOnAddrLabel(AmpAmpLoc, LabelLoc, Label);
+  }
+
+  /// \brief Build a new GNU statement expression.
+  ///
+  /// By default, performs semantic analysis to build the new expression.
+  /// Subclasses may override this routine to provide different behavior.
+  ExprResult RebuildStmtExpr(SourceLocation LParenLoc,
+                                   Stmt *SubStmt,
+                                   SourceLocation RParenLoc) {
+    return getSema().ActOnStmtExpr(LParenLoc, SubStmt, RParenLoc);
+  }
+
+  /// \brief Build a new __builtin_choose_expr expression.
+  ///
+  /// By default, performs semantic analysis to build the new expression.
+  /// Subclasses may override this routine to provide different behavior.
+  ExprResult RebuildChooseExpr(SourceLocation BuiltinLoc,
+                                     Expr *Cond, Expr *LHS, Expr *RHS,
+                                     SourceLocation RParenLoc) {
+    return SemaRef.ActOnChooseExpr(BuiltinLoc,
+                                   Cond, LHS, RHS,
+                                   RParenLoc);
+  }
+
+  /// \brief Build a new generic selection expression.
+  ///
+  /// By default, performs semantic analysis to build the new expression.
+  /// Subclasses may override this routine to provide different behavior.
+  ExprResult RebuildGenericSelectionExpr(SourceLocation KeyLoc,
+                                         SourceLocation DefaultLoc,
+                                         SourceLocation RParenLoc,
+                                         Expr *ControllingExpr,
+                                         TypeSourceInfo **Types,
+                                         Expr **Exprs,
+                                         unsigned NumAssocs) {
+    return getSema().CreateGenericSelectionExpr(KeyLoc, DefaultLoc, RParenLoc,
+                                                ControllingExpr, Types, Exprs,
+                                                NumAssocs);
+  }
+
+  /// \brief Build a new overloaded operator call expression.
+  ///
+  /// By default, performs semantic analysis to build the new expression.
+  /// The semantic analysis provides the behavior of template instantiation,
+  /// copying with transformations that turn what looks like an overloaded
+  /// operator call into a use of a builtin operator, performing
+  /// argument-dependent lookup, etc. Subclasses may override this routine to
+  /// provide different behavior.
+  ExprResult RebuildCXXOperatorCallExpr(OverloadedOperatorKind Op,
+                                              SourceLocation OpLoc,
+                                              Expr *Callee,
+                                              Expr *First,
+                                              Expr *Second);
+
+  /// \brief Build a new C++ "named" cast expression, such as static_cast or
+  /// reinterpret_cast.
+  ///
+  /// By default, this routine dispatches to one of the more-specific routines
+  /// for a particular named case, e.g., RebuildCXXStaticCastExpr().
+  /// Subclasses may override this routine to provide different behavior.
+  ExprResult RebuildCXXNamedCastExpr(SourceLocation OpLoc,
+                                           Stmt::StmtClass Class,
+                                           SourceLocation LAngleLoc,
+                                           TypeSourceInfo *TInfo,
+                                           SourceLocation RAngleLoc,
+                                           SourceLocation LParenLoc,
+                                           Expr *SubExpr,
+                                           SourceLocation RParenLoc) {
+    switch (Class) {
+    case Stmt::CXXStaticCastExprClass:
+      return getDerived().RebuildCXXStaticCastExpr(OpLoc, LAngleLoc, TInfo,
+                                                   RAngleLoc, LParenLoc,
+                                                   SubExpr, RParenLoc);
+
+    case Stmt::CXXDynamicCastExprClass:
+      return getDerived().RebuildCXXDynamicCastExpr(OpLoc, LAngleLoc, TInfo,
+                                                    RAngleLoc, LParenLoc,
+                                                    SubExpr, RParenLoc);
+
+    case Stmt::CXXReinterpretCastExprClass:
+      return getDerived().RebuildCXXReinterpretCastExpr(OpLoc, LAngleLoc, TInfo,
+                                                        RAngleLoc, LParenLoc,
+                                                        SubExpr,
+                                                        RParenLoc);
+
+    case Stmt::CXXConstCastExprClass:
+      return getDerived().RebuildCXXConstCastExpr(OpLoc, LAngleLoc, TInfo,
+                                                   RAngleLoc, LParenLoc,
+                                                   SubExpr, RParenLoc);
+
+    default:
+      llvm_unreachable("Invalid C++ named cast");
+    }
+  }
+
+  /// \brief Build a new C++ static_cast expression.
+  ///
+  /// By default, performs semantic analysis to build the new expression.
+  /// Subclasses may override this routine to provide different behavior.
+  ExprResult RebuildCXXStaticCastExpr(SourceLocation OpLoc,
+                                            SourceLocation LAngleLoc,
+                                            TypeSourceInfo *TInfo,
+                                            SourceLocation RAngleLoc,
+                                            SourceLocation LParenLoc,
+                                            Expr *SubExpr,
+                                            SourceLocation RParenLoc) {
+    return getSema().BuildCXXNamedCast(OpLoc, tok::kw_static_cast,
+                                       TInfo, SubExpr,
+                                       SourceRange(LAngleLoc, RAngleLoc),
+                                       SourceRange(LParenLoc, RParenLoc));
+  }
+
+  /// \brief Build a new C++ dynamic_cast expression.
+  ///
+  /// By default, performs semantic analysis to build the new expression.
+  /// Subclasses may override this routine to provide different behavior.
+  ExprResult RebuildCXXDynamicCastExpr(SourceLocation OpLoc,
+                                             SourceLocation LAngleLoc,
+                                             TypeSourceInfo *TInfo,
+                                             SourceLocation RAngleLoc,
+                                             SourceLocation LParenLoc,
+                                             Expr *SubExpr,
+                                             SourceLocation RParenLoc) {
+    return getSema().BuildCXXNamedCast(OpLoc, tok::kw_dynamic_cast,
+                                       TInfo, SubExpr,
+                                       SourceRange(LAngleLoc, RAngleLoc),
+                                       SourceRange(LParenLoc, RParenLoc));
+  }
+
+  /// \brief Build a new C++ reinterpret_cast expression.
+  ///
+  /// By default, performs semantic analysis to build the new expression.
+  /// Subclasses may override this routine to provide different behavior.
+  ExprResult RebuildCXXReinterpretCastExpr(SourceLocation OpLoc,
+                                                 SourceLocation LAngleLoc,
+                                                 TypeSourceInfo *TInfo,
+                                                 SourceLocation RAngleLoc,
+                                                 SourceLocation LParenLoc,
+                                                 Expr *SubExpr,
+                                                 SourceLocation RParenLoc) {
+    return getSema().BuildCXXNamedCast(OpLoc, tok::kw_reinterpret_cast,
+                                       TInfo, SubExpr,
+                                       SourceRange(LAngleLoc, RAngleLoc),
+                                       SourceRange(LParenLoc, RParenLoc));
+  }
+
+  /// \brief Build a new C++ const_cast expression.
+  ///
+  /// By default, performs semantic analysis to build the new expression.
+  /// Subclasses may override this routine to provide different behavior.
+  ExprResult RebuildCXXConstCastExpr(SourceLocation OpLoc,
+                                           SourceLocation LAngleLoc,
+                                           TypeSourceInfo *TInfo,
+                                           SourceLocation RAngleLoc,
+                                           SourceLocation LParenLoc,
+                                           Expr *SubExpr,
+                                           SourceLocation RParenLoc) {
+    return getSema().BuildCXXNamedCast(OpLoc, tok::kw_const_cast,
+                                       TInfo, SubExpr,
+                                       SourceRange(LAngleLoc, RAngleLoc),
+                                       SourceRange(LParenLoc, RParenLoc));
+  }
+
+  /// \brief Build a new C++ functional-style cast expression.
+  ///
+  /// By default, performs semantic analysis to build the new expression.
+  /// Subclasses may override this routine to provide different behavior.
+  ExprResult RebuildCXXFunctionalCastExpr(TypeSourceInfo *TInfo,
+                                          SourceLocation LParenLoc,
+                                          Expr *Sub,
+                                          SourceLocation RParenLoc) {
+    return getSema().BuildCXXTypeConstructExpr(TInfo, LParenLoc,
+                                               MultiExprArg(&Sub, 1),
+                                               RParenLoc);
+  }
+
+  /// \brief Build a new C++ typeid(type) expression.
+  ///
+  /// By default, performs semantic analysis to build the new expression.
+  /// Subclasses may override this routine to provide different behavior.
+  ExprResult RebuildCXXTypeidExpr(QualType TypeInfoType,
+                                        SourceLocation TypeidLoc,
+                                        TypeSourceInfo *Operand,
+                                        SourceLocation RParenLoc) {
+    return getSema().BuildCXXTypeId(TypeInfoType, TypeidLoc, Operand, 
+                                    RParenLoc);
+  }
+
+
+  /// \brief Build a new C++ typeid(expr) expression.
+  ///
+  /// By default, performs semantic analysis to build the new expression.
+  /// Subclasses may override this routine to provide different behavior.
+  ExprResult RebuildCXXTypeidExpr(QualType TypeInfoType,
+                                        SourceLocation TypeidLoc,
+                                        Expr *Operand,
+                                        SourceLocation RParenLoc) {
+    return getSema().BuildCXXTypeId(TypeInfoType, TypeidLoc, Operand,
+                                    RParenLoc);
+  }
+
+  /// \brief Build a new C++ __uuidof(type) expression.
+  ///
+  /// By default, performs semantic analysis to build the new expression.
+  /// Subclasses may override this routine to provide different behavior.
+  ExprResult RebuildCXXUuidofExpr(QualType TypeInfoType,
+                                        SourceLocation TypeidLoc,
+                                        TypeSourceInfo *Operand,
+                                        SourceLocation RParenLoc) {
+    return getSema().BuildCXXUuidof(TypeInfoType, TypeidLoc, Operand, 
+                                    RParenLoc);
+  }
+
+  /// \brief Build a new C++ __uuidof(expr) expression.
+  ///
+  /// By default, performs semantic analysis to build the new expression.
+  /// Subclasses may override this routine to provide different behavior.
+  ExprResult RebuildCXXUuidofExpr(QualType TypeInfoType,
+                                        SourceLocation TypeidLoc,
+                                        Expr *Operand,
+                                        SourceLocation RParenLoc) {
+    return getSema().BuildCXXUuidof(TypeInfoType, TypeidLoc, Operand,
+                                    RParenLoc);
+  }
+
+  /// \brief Build a new C++ "this" expression.
+  ///
+  /// By default, builds a new "this" expression without performing any
+  /// semantic analysis. Subclasses may override this routine to provide
+  /// different behavior.
+  ExprResult RebuildCXXThisExpr(SourceLocation ThisLoc,
+                                QualType ThisType,
+                                bool isImplicit) {
+    getSema().CheckCXXThisCapture(ThisLoc);
+    return getSema().Owned(
+                      new (getSema().Context) CXXThisExpr(ThisLoc, ThisType,
+                                                          isImplicit));
+  }
+
+  /// \brief Build a new C++ throw expression.
+  ///
+  /// By default, performs semantic analysis to build the new expression.
+  /// Subclasses may override this routine to provide different behavior.
+  ExprResult RebuildCXXThrowExpr(SourceLocation ThrowLoc, Expr *Sub,
+                                 bool IsThrownVariableInScope) {
+    return getSema().BuildCXXThrow(ThrowLoc, Sub, IsThrownVariableInScope);
+  }
+
+  /// \brief Build a new C++ default-argument expression.
+  ///
+  /// By default, builds a new default-argument expression, which does not
+  /// require any semantic analysis. Subclasses may override this routine to
+  /// provide different behavior.
+  ExprResult RebuildCXXDefaultArgExpr(SourceLocation Loc, 
+                                            ParmVarDecl *Param) {
+    return getSema().Owned(CXXDefaultArgExpr::Create(getSema().Context, Loc,
+                                                     Param));
+  }
+
+  /// \brief Build a new C++ zero-initialization expression.
+  ///
+  /// By default, performs semantic analysis to build the new expression.
+  /// Subclasses may override this routine to provide different behavior.
+  ExprResult RebuildCXXScalarValueInitExpr(TypeSourceInfo *TSInfo,
+                                           SourceLocation LParenLoc,
+                                           SourceLocation RParenLoc) {
+    return getSema().BuildCXXTypeConstructExpr(TSInfo, LParenLoc,
+                                               MultiExprArg(getSema(), 0, 0),
+                                               RParenLoc);
+  }
+
+  /// \brief Build a new C++ "new" expression.
+  ///
+  /// By default, performs semantic analysis to build the new expression.
+  /// Subclasses may override this routine to provide different behavior.
+  ExprResult RebuildCXXNewExpr(SourceLocation StartLoc,
+                               bool UseGlobal,
+                               SourceLocation PlacementLParen,
+                               MultiExprArg PlacementArgs,
+                               SourceLocation PlacementRParen,
+                               SourceRange TypeIdParens,
+                               QualType AllocatedType,
+                               TypeSourceInfo *AllocatedTypeInfo,
+                               Expr *ArraySize,
+                               SourceRange DirectInitRange,
+                               Expr *Initializer) {
+    return getSema().BuildCXXNew(StartLoc, UseGlobal,
+                                 PlacementLParen,
+                                 move(PlacementArgs),
+                                 PlacementRParen,
+                                 TypeIdParens,
+                                 AllocatedType,
+                                 AllocatedTypeInfo,
+                                 ArraySize,
+                                 DirectInitRange,
+                                 Initializer);
+  }
+
+  /// \brief Build a new C++ "delete" expression.
+  ///
+  /// By default, performs semantic analysis to build the new expression.
+  /// Subclasses may override this routine to provide different behavior.
+  ExprResult RebuildCXXDeleteExpr(SourceLocation StartLoc,
+                                        bool IsGlobalDelete,
+                                        bool IsArrayForm,
+                                        Expr *Operand) {
+    return getSema().ActOnCXXDelete(StartLoc, IsGlobalDelete, IsArrayForm,
+                                    Operand);
+  }
+
+  /// \brief Build a new unary type trait expression.
+  ///
+  /// By default, performs semantic analysis to build the new expression.
+  /// Subclasses may override this routine to provide different behavior.
+  ExprResult RebuildUnaryTypeTrait(UnaryTypeTrait Trait,
+                                   SourceLocation StartLoc,
+                                   TypeSourceInfo *T,
+                                   SourceLocation RParenLoc) {
+    return getSema().BuildUnaryTypeTrait(Trait, StartLoc, T, RParenLoc);
+  }
+
+  /// \brief Build a new binary type trait expression.
+  ///
+  /// By default, performs semantic analysis to build the new expression.
+  /// Subclasses may override this routine to provide different behavior.
+  ExprResult RebuildBinaryTypeTrait(BinaryTypeTrait Trait,
+                                    SourceLocation StartLoc,
+                                    TypeSourceInfo *LhsT,
+                                    TypeSourceInfo *RhsT,
+                                    SourceLocation RParenLoc) {
+    return getSema().BuildBinaryTypeTrait(Trait, StartLoc, LhsT, RhsT, RParenLoc);
+  }
+
+  /// \brief Build a new type trait expression.
+  ///
+  /// By default, performs semantic analysis to build the new expression.
+  /// Subclasses may override this routine to provide different behavior.
+  ExprResult RebuildTypeTrait(TypeTrait Trait,
+                              SourceLocation StartLoc,
+                              ArrayRef<TypeSourceInfo *> Args,
+                              SourceLocation RParenLoc) {
+    return getSema().BuildTypeTrait(Trait, StartLoc, Args, RParenLoc);
+  }
+  
+  /// \brief Build a new array type trait expression.
+  ///
+  /// By default, performs semantic analysis to build the new expression.
+  /// Subclasses may override this routine to provide different behavior.
+  ExprResult RebuildArrayTypeTrait(ArrayTypeTrait Trait,
+                                   SourceLocation StartLoc,
+                                   TypeSourceInfo *TSInfo,
+                                   Expr *DimExpr,
+                                   SourceLocation RParenLoc) {
+    return getSema().BuildArrayTypeTrait(Trait, StartLoc, TSInfo, DimExpr, RParenLoc);
+  }
+
+  /// \brief Build a new expression trait expression.
+  ///
+  /// By default, performs semantic analysis to build the new expression.
+  /// Subclasses may override this routine to provide different behavior.
+  ExprResult RebuildExpressionTrait(ExpressionTrait Trait,
+                                   SourceLocation StartLoc,
+                                   Expr *Queried,
+                                   SourceLocation RParenLoc) {
+    return getSema().BuildExpressionTrait(Trait, StartLoc, Queried, RParenLoc);
+  }
+
+  /// \brief Build a new (previously unresolved) declaration reference
+  /// expression.
+  ///
+  /// By default, performs semantic analysis to build the new expression.
+  /// Subclasses may override this routine to provide different behavior.
+  ExprResult RebuildDependentScopeDeclRefExpr(
+                                          NestedNameSpecifierLoc QualifierLoc,
+                                          SourceLocation TemplateKWLoc,
+                                       const DeclarationNameInfo &NameInfo,
+                              const TemplateArgumentListInfo *TemplateArgs) {
+    CXXScopeSpec SS;
+    SS.Adopt(QualifierLoc);
+
+    if (TemplateArgs || TemplateKWLoc.isValid())
+      return getSema().BuildQualifiedTemplateIdExpr(SS, TemplateKWLoc,
+                                                    NameInfo, TemplateArgs);
+
+    return getSema().BuildQualifiedDeclarationNameExpr(SS, NameInfo);
+  }
+
+  /// \brief Build a new template-id expression.
+  ///
+  /// By default, performs semantic analysis to build the new expression.
+  /// Subclasses may override this routine to provide different behavior.
+  ExprResult RebuildTemplateIdExpr(const CXXScopeSpec &SS,
+                                   SourceLocation TemplateKWLoc,
+                                   LookupResult &R,
+                                   bool RequiresADL,
+                              const TemplateArgumentListInfo *TemplateArgs) {
+    return getSema().BuildTemplateIdExpr(SS, TemplateKWLoc, R, RequiresADL,
+                                         TemplateArgs);
+  }
+
+  /// \brief Build a new object-construction expression.
+  ///
+  /// By default, performs semantic analysis to build the new expression.
+  /// Subclasses may override this routine to provide different behavior.
+  ExprResult RebuildCXXConstructExpr(QualType T,
+                                     SourceLocation Loc,
+                                     CXXConstructorDecl *Constructor,
+                                     bool IsElidable,
+                                     MultiExprArg Args,
+                                     bool HadMultipleCandidates,
+                                     bool RequiresZeroInit,
+                             CXXConstructExpr::ConstructionKind ConstructKind,
+                                     SourceRange ParenRange) {
+    ASTOwningVector<Expr*> ConvertedArgs(SemaRef);
+    if (getSema().CompleteConstructorCall(Constructor, move(Args), Loc, 
+                                          ConvertedArgs))
+      return ExprError();
+    
+    return getSema().BuildCXXConstructExpr(Loc, T, Constructor, IsElidable,
+                                           move_arg(ConvertedArgs),
+                                           HadMultipleCandidates,
+                                           RequiresZeroInit, ConstructKind,
+                                           ParenRange);
+  }
+
+  /// \brief Build a new object-construction expression.
+  ///
+  /// By default, performs semantic analysis to build the new expression.
+  /// Subclasses may override this routine to provide different behavior.
+  ExprResult RebuildCXXTemporaryObjectExpr(TypeSourceInfo *TSInfo,
+                                           SourceLocation LParenLoc,
+                                           MultiExprArg Args,
+                                           SourceLocation RParenLoc) {
+    return getSema().BuildCXXTypeConstructExpr(TSInfo,
+                                               LParenLoc,
+                                               move(Args),
+                                               RParenLoc);
+  }
+
+  /// \brief Build a new object-construction expression.
+  ///
+  /// By default, performs semantic analysis to build the new expression.
+  /// Subclasses may override this routine to provide different behavior.
+  ExprResult RebuildCXXUnresolvedConstructExpr(TypeSourceInfo *TSInfo,
+                                               SourceLocation LParenLoc,
+                                               MultiExprArg Args,
+                                               SourceLocation RParenLoc) {
+    return getSema().BuildCXXTypeConstructExpr(TSInfo,
+                                               LParenLoc,
+                                               move(Args),
+                                               RParenLoc);
+  }
+
+  /// \brief Build a new member reference expression.
+  ///
+  /// By default, performs semantic analysis to build the new expression.
+  /// Subclasses may override this routine to provide different behavior.
+  ExprResult RebuildCXXDependentScopeMemberExpr(Expr *BaseE,
+                                                QualType BaseType,
+                                                bool IsArrow,
+                                                SourceLocation OperatorLoc,
+                                          NestedNameSpecifierLoc QualifierLoc,
+                                                SourceLocation TemplateKWLoc,
+                                            NamedDecl *FirstQualifierInScope,
+                                   const DeclarationNameInfo &MemberNameInfo,
+                              const TemplateArgumentListInfo *TemplateArgs) {
+    CXXScopeSpec SS;
+    SS.Adopt(QualifierLoc);
+
+    return SemaRef.BuildMemberReferenceExpr(BaseE, BaseType,
+                                            OperatorLoc, IsArrow,
+                                            SS, TemplateKWLoc,
+                                            FirstQualifierInScope,
+                                            MemberNameInfo,
+                                            TemplateArgs);
+  }
+
+  /// \brief Build a new member reference expression.
+  ///
+  /// By default, performs semantic analysis to build the new expression.
+  /// Subclasses may override this routine to provide different behavior.
+  ExprResult RebuildUnresolvedMemberExpr(Expr *BaseE, QualType BaseType,
+                                         SourceLocation OperatorLoc,
+                                         bool IsArrow,
+                                         NestedNameSpecifierLoc QualifierLoc,
+                                         SourceLocation TemplateKWLoc,
+                                         NamedDecl *FirstQualifierInScope,
+                                         LookupResult &R,
+                                const TemplateArgumentListInfo *TemplateArgs) {
+    CXXScopeSpec SS;
+    SS.Adopt(QualifierLoc);
+
+    return SemaRef.BuildMemberReferenceExpr(BaseE, BaseType,
+                                            OperatorLoc, IsArrow,
+                                            SS, TemplateKWLoc,
+                                            FirstQualifierInScope,
+                                            R, TemplateArgs);
+  }
+
+  /// \brief Build a new noexcept expression.
+  ///
+  /// By default, performs semantic analysis to build the new expression.
+  /// Subclasses may override this routine to provide different behavior.
+  ExprResult RebuildCXXNoexceptExpr(SourceRange Range, Expr *Arg) {
+    return SemaRef.BuildCXXNoexceptExpr(Range.getBegin(), Arg, Range.getEnd());
+  }
+
+  /// \brief Build a new expression to compute the length of a parameter pack.
+  ExprResult RebuildSizeOfPackExpr(SourceLocation OperatorLoc, NamedDecl *Pack, 
+                                   SourceLocation PackLoc, 
+                                   SourceLocation RParenLoc,
+                                   llvm::Optional<unsigned> Length) {
+    if (Length)
+      return new (SemaRef.Context) SizeOfPackExpr(SemaRef.Context.getSizeType(), 
+                                                  OperatorLoc, Pack, PackLoc, 
+                                                  RParenLoc, *Length);
+    
+    return new (SemaRef.Context) SizeOfPackExpr(SemaRef.Context.getSizeType(), 
+                                                OperatorLoc, Pack, PackLoc, 
+                                                RParenLoc);
+  }
+
+  /// \brief Build a new Objective-C array literal.
+  ///
+  /// By default, performs semantic analysis to build the new expression.
+  /// Subclasses may override this routine to provide different behavior.
+  ExprResult RebuildObjCArrayLiteral(SourceRange Range,
+                                     Expr **Elements, unsigned NumElements) {
+    return getSema().BuildObjCArrayLiteral(Range, 
+                                           MultiExprArg(Elements, NumElements));
+  }
+ 
+  ExprResult RebuildObjCSubscriptRefExpr(SourceLocation RB, 
+                                         Expr *Base, Expr *Key,
+                                         ObjCMethodDecl *getterMethod,
+                                         ObjCMethodDecl *setterMethod) {
+    return  getSema().BuildObjCSubscriptExpression(RB, Base, Key,
+                                                   getterMethod, setterMethod);
+  }
+
+  /// \brief Build a new Objective-C dictionary literal.
+  ///
+  /// By default, performs semantic analysis to build the new expression.
+  /// Subclasses may override this routine to provide different behavior.
+  ExprResult RebuildObjCDictionaryLiteral(SourceRange Range,
+                                          ObjCDictionaryElement *Elements,
+                                          unsigned NumElements) {
+    return getSema().BuildObjCDictionaryLiteral(Range, Elements, NumElements);
+  }
+  
+  /// \brief Build a new Objective-C @encode expression.
+  ///
+  /// By default, performs semantic analysis to build the new expression.
+  /// Subclasses may override this routine to provide different behavior.
+  ExprResult RebuildObjCEncodeExpr(SourceLocation AtLoc,
+                                         TypeSourceInfo *EncodeTypeInfo,
+                                         SourceLocation RParenLoc) {
+    return SemaRef.Owned(SemaRef.BuildObjCEncodeExpression(AtLoc, EncodeTypeInfo,
+                                                           RParenLoc));
+  }
+
+  /// \brief Build a new Objective-C class message.
+  ExprResult RebuildObjCMessageExpr(TypeSourceInfo *ReceiverTypeInfo,
+                                          Selector Sel,
+                                          ArrayRef<SourceLocation> SelectorLocs,
+                                          ObjCMethodDecl *Method,
+                                          SourceLocation LBracLoc, 
+                                          MultiExprArg Args,
+                                          SourceLocation RBracLoc) {
+    return SemaRef.BuildClassMessage(ReceiverTypeInfo,
+                                     ReceiverTypeInfo->getType(),
+                                     /*SuperLoc=*/SourceLocation(),
+                                     Sel, Method, LBracLoc, SelectorLocs,
+                                     RBracLoc, move(Args));
+  }
+
+  /// \brief Build a new Objective-C instance message.
+  ExprResult RebuildObjCMessageExpr(Expr *Receiver,
+                                          Selector Sel,
+                                          ArrayRef<SourceLocation> SelectorLocs,
+                                          ObjCMethodDecl *Method,
+                                          SourceLocation LBracLoc, 
+                                          MultiExprArg Args,
+                                          SourceLocation RBracLoc) {
+    return SemaRef.BuildInstanceMessage(Receiver,
+                                        Receiver->getType(),
+                                        /*SuperLoc=*/SourceLocation(),
+                                        Sel, Method, LBracLoc, SelectorLocs,
+                                        RBracLoc, move(Args));
+  }
+
+  /// \brief Build a new Objective-C ivar reference expression.
+  ///
+  /// By default, performs semantic analysis to build the new expression.
+  /// Subclasses may override this routine to provide different behavior.
+  ExprResult RebuildObjCIvarRefExpr(Expr *BaseArg, ObjCIvarDecl *Ivar,
+                                          SourceLocation IvarLoc,
+                                          bool IsArrow, bool IsFreeIvar) {
+    // FIXME: We lose track of the IsFreeIvar bit.
+    CXXScopeSpec SS;
+    ExprResult Base = getSema().Owned(BaseArg);
+    LookupResult R(getSema(), Ivar->getDeclName(), IvarLoc,
+                   Sema::LookupMemberName);
+    ExprResult Result = getSema().LookupMemberExpr(R, Base, IsArrow,
+                                                         /*FIME:*/IvarLoc,
+                                                         SS, 0,
+                                                         false);
+    if (Result.isInvalid() || Base.isInvalid())
+      return ExprError();
+    
+    if (Result.get())
+      return move(Result);
+    
+    return getSema().BuildMemberReferenceExpr(Base.get(), Base.get()->getType(),
+                                              /*FIXME:*/IvarLoc, IsArrow,
+                                              SS, SourceLocation(),
+                                              /*FirstQualifierInScope=*/0,
+                                              R, 
+                                              /*TemplateArgs=*/0);
+  }
+
+  /// \brief Build a new Objective-C property reference expression.
+  ///
+  /// By default, performs semantic analysis to build the new expression.
+  /// Subclasses may override this routine to provide different behavior.
+  ExprResult RebuildObjCPropertyRefExpr(Expr *BaseArg, 
+                                        ObjCPropertyDecl *Property,
+                                        SourceLocation PropertyLoc) {
+    CXXScopeSpec SS;
+    ExprResult Base = getSema().Owned(BaseArg);
+    LookupResult R(getSema(), Property->getDeclName(), PropertyLoc,
+                   Sema::LookupMemberName);
+    bool IsArrow = false;
+    ExprResult Result = getSema().LookupMemberExpr(R, Base, IsArrow,
+                                                         /*FIME:*/PropertyLoc,
+                                                         SS, 0, false);
+    if (Result.isInvalid() || Base.isInvalid())
+      return ExprError();
+    
+    if (Result.get())
+      return move(Result);
+    
+    return getSema().BuildMemberReferenceExpr(Base.get(), Base.get()->getType(),
+                                              /*FIXME:*/PropertyLoc, IsArrow, 
+                                              SS, SourceLocation(),
+                                              /*FirstQualifierInScope=*/0,
+                                              R, 
+                                              /*TemplateArgs=*/0);
+  }
+  
+  /// \brief Build a new Objective-C property reference expression.
+  ///
+  /// By default, performs semantic analysis to build the new expression.
+  /// Subclasses may override this routine to provide different behavior.
+  ExprResult RebuildObjCPropertyRefExpr(Expr *Base, QualType T,
+                                        ObjCMethodDecl *Getter,
+                                        ObjCMethodDecl *Setter,
+                                        SourceLocation PropertyLoc) {
+    // Since these expressions can only be value-dependent, we do not
+    // need to perform semantic analysis again.
+    return Owned(
+      new (getSema().Context) ObjCPropertyRefExpr(Getter, Setter, T,
+                                                  VK_LValue, OK_ObjCProperty,
+                                                  PropertyLoc, Base));
+  }
+
+  /// \brief Build a new Objective-C "isa" expression.
+  ///
+  /// By default, performs semantic analysis to build the new expression.
+  /// Subclasses may override this routine to provide different behavior.
+  ExprResult RebuildObjCIsaExpr(Expr *BaseArg, SourceLocation IsaLoc,
+                                      bool IsArrow) {
+    CXXScopeSpec SS;
+    ExprResult Base = getSema().Owned(BaseArg);
+    LookupResult R(getSema(), &getSema().Context.Idents.get("isa"), IsaLoc,
+                   Sema::LookupMemberName);
+    ExprResult Result = getSema().LookupMemberExpr(R, Base, IsArrow,
+                                                         /*FIME:*/IsaLoc,
+                                                         SS, 0, false);
+    if (Result.isInvalid() || Base.isInvalid())
+      return ExprError();
+    
+    if (Result.get())
+      return move(Result);
+    
+    return getSema().BuildMemberReferenceExpr(Base.get(), Base.get()->getType(),
+                                              /*FIXME:*/IsaLoc, IsArrow,
+                                              SS, SourceLocation(),
+                                              /*FirstQualifierInScope=*/0,
+                                              R, 
+                                              /*TemplateArgs=*/0);
+  }
+  
+  /// \brief Build a new shuffle vector expression.
+  ///
+  /// By default, performs semantic analysis to build the new expression.
+  /// Subclasses may override this routine to provide different behavior.
+  ExprResult RebuildShuffleVectorExpr(SourceLocation BuiltinLoc,
+                                      MultiExprArg SubExprs,
+                                      SourceLocation RParenLoc) {
+    // Find the declaration for __builtin_shufflevector
+    const IdentifierInfo &Name
+      = SemaRef.Context.Idents.get("__builtin_shufflevector");
+    TranslationUnitDecl *TUDecl = SemaRef.Context.getTranslationUnitDecl();
+    DeclContext::lookup_result Lookup = TUDecl->lookup(DeclarationName(&Name));
+    assert(Lookup.first != Lookup.second && "No __builtin_shufflevector?");
+
+    // Build a reference to the __builtin_shufflevector builtin
+    FunctionDecl *Builtin = cast<FunctionDecl>(*Lookup.first);
+    ExprResult Callee
+      = SemaRef.Owned(new (SemaRef.Context) DeclRefExpr(Builtin, false,
+                                                        Builtin->getType(),
+                                                        VK_LValue, BuiltinLoc));
+    Callee = SemaRef.UsualUnaryConversions(Callee.take());
+    if (Callee.isInvalid())
+      return ExprError();
+
+    // Build the CallExpr
+    unsigned NumSubExprs = SubExprs.size();
+    Expr **Subs = (Expr **)SubExprs.release();
+    ExprResult TheCall = SemaRef.Owned(
+      new (SemaRef.Context) CallExpr(SemaRef.Context, Callee.take(),
+                                                       Subs, NumSubExprs,
+                                                   Builtin->getCallResultType(),
+                            Expr::getValueKindForType(Builtin->getResultType()),
+                                     RParenLoc));
+
+    // Type-check the __builtin_shufflevector expression.
+    return SemaRef.SemaBuiltinShuffleVector(cast<CallExpr>(TheCall.take()));
+  }
+
+  /// \brief Build a new template argument pack expansion.
+  ///
+  /// By default, performs semantic analysis to build a new pack expansion
+  /// for a template argument. Subclasses may override this routine to provide 
+  /// different behavior.
+  TemplateArgumentLoc RebuildPackExpansion(TemplateArgumentLoc Pattern,
+                                           SourceLocation EllipsisLoc,
+                                       llvm::Optional<unsigned> NumExpansions) {
+    switch (Pattern.getArgument().getKind()) {
+    case TemplateArgument::Expression: {
+      ExprResult Result
+        = getSema().CheckPackExpansion(Pattern.getSourceExpression(),
+                                       EllipsisLoc, NumExpansions);
+      if (Result.isInvalid())
+        return TemplateArgumentLoc();
+          
+      return TemplateArgumentLoc(Result.get(), Result.get());
+    }
+        
+    case TemplateArgument::Template:
+      return TemplateArgumentLoc(TemplateArgument(
+                                          Pattern.getArgument().getAsTemplate(),
+                                                  NumExpansions),
+                                 Pattern.getTemplateQualifierLoc(),
+                                 Pattern.getTemplateNameLoc(),
+                                 EllipsisLoc);
+        
+    case TemplateArgument::Null:
+    case TemplateArgument::Integral:
+    case TemplateArgument::Declaration:
+    case TemplateArgument::Pack:
+    case TemplateArgument::TemplateExpansion:
+      llvm_unreachable("Pack expansion pattern has no parameter packs");
+        
+    case TemplateArgument::Type:
+      if (TypeSourceInfo *Expansion 
+            = getSema().CheckPackExpansion(Pattern.getTypeSourceInfo(),
+                                           EllipsisLoc,
+                                           NumExpansions))
+        return TemplateArgumentLoc(TemplateArgument(Expansion->getType()),
+                                   Expansion);
+      break;
+    }
+    
+    return TemplateArgumentLoc();
+  }
+  
+  /// \brief Build a new expression pack expansion.
+  ///
+  /// By default, performs semantic analysis to build a new pack expansion
+  /// for an expression. Subclasses may override this routine to provide 
+  /// different behavior.
+  ExprResult RebuildPackExpansion(Expr *Pattern, SourceLocation EllipsisLoc,
+                                  llvm::Optional<unsigned> NumExpansions) {
+    return getSema().CheckPackExpansion(Pattern, EllipsisLoc, NumExpansions);
+  }
+
+  /// \brief Build a new atomic operation expression.
+  ///
+  /// By default, performs semantic analysis to build the new expression.
+  /// Subclasses may override this routine to provide different behavior.
+  ExprResult RebuildAtomicExpr(SourceLocation BuiltinLoc,
+                               MultiExprArg SubExprs,
+                               QualType RetTy,
+                               AtomicExpr::AtomicOp Op,
+                               SourceLocation RParenLoc) {
+    // Just create the expression; there is not any interesting semantic
+    // analysis here because we can't actually build an AtomicExpr until
+    // we are sure it is semantically sound.
+    unsigned NumSubExprs = SubExprs.size();
+    Expr **Subs = (Expr **)SubExprs.release();
+    return new (SemaRef.Context) AtomicExpr(BuiltinLoc, Subs,
+                                            NumSubExprs, RetTy, Op,
+                                            RParenLoc);
+  }
+
+private:
+  TypeLoc TransformTypeInObjectScope(TypeLoc TL,
+                                     QualType ObjectType,
+                                     NamedDecl *FirstQualifierInScope,
+                                     CXXScopeSpec &SS);
+
+  TypeSourceInfo *TransformTypeInObjectScope(TypeSourceInfo *TSInfo,
+                                             QualType ObjectType,
+                                             NamedDecl *FirstQualifierInScope,
+                                             CXXScopeSpec &SS);
+};
+
+template<typename Derived>
+StmtResult TreeTransform<Derived>::TransformStmt(Stmt *S) {
+  if (!S)
+    return SemaRef.Owned(S);
+
+  switch (S->getStmtClass()) {
+  case Stmt::NoStmtClass: break;
+
+  // Transform individual statement nodes
+#define STMT(Node, Parent)                                              \
+  case Stmt::Node##Class: return getDerived().Transform##Node(cast<Node>(S));
+#define ABSTRACT_STMT(Node)
+#define EXPR(Node, Parent)
+#include "clang/AST/StmtNodes.inc"
+
+  // Transform expressions by calling TransformExpr.
+#define STMT(Node, Parent)
+#define ABSTRACT_STMT(Stmt)
+#define EXPR(Node, Parent) case Stmt::Node##Class:
+#include "clang/AST/StmtNodes.inc"
+    {
+      ExprResult E = getDerived().TransformExpr(cast<Expr>(S));
+      if (E.isInvalid())
+        return StmtError();
+
+      return getSema().ActOnExprStmt(getSema().MakeFullExpr(E.take()));
+    }
+  }
+
+  return SemaRef.Owned(S);
+}
+
+
+template<typename Derived>
+ExprResult TreeTransform<Derived>::TransformExpr(Expr *E) {
+  if (!E)
+    return SemaRef.Owned(E);
+
+  switch (E->getStmtClass()) {
+    case Stmt::NoStmtClass: break;
+#define STMT(Node, Parent) case Stmt::Node##Class: break;
+#define ABSTRACT_STMT(Stmt)
+#define EXPR(Node, Parent)                                              \
+    case Stmt::Node##Class: return getDerived().Transform##Node(cast<Node>(E));
+#include "clang/AST/StmtNodes.inc"
+  }
+
+  return SemaRef.Owned(E);
+}
+
+template<typename Derived>
+bool TreeTransform<Derived>::TransformExprs(Expr **Inputs, 
+                                            unsigned NumInputs, 
+                                            bool IsCall,
+                                      SmallVectorImpl<Expr *> &Outputs,
+                                            bool *ArgChanged) {
+  for (unsigned I = 0; I != NumInputs; ++I) {
+    // If requested, drop call arguments that need to be dropped.
+    if (IsCall && getDerived().DropCallArgument(Inputs[I])) {
+      if (ArgChanged)
+        *ArgChanged = true;
+      
+      break;
+    }
+    
+    if (PackExpansionExpr *Expansion = dyn_cast<PackExpansionExpr>(Inputs[I])) {
+      Expr *Pattern = Expansion->getPattern();
+        
+      SmallVector<UnexpandedParameterPack, 2> Unexpanded;
+      getSema().collectUnexpandedParameterPacks(Pattern, Unexpanded);
+      assert(!Unexpanded.empty() && "Pack expansion without parameter packs?");
+      
+      // Determine whether the set of unexpanded parameter packs can and should
+      // be expanded.
+      bool Expand = true;
+      bool RetainExpansion = false;
+      llvm::Optional<unsigned> OrigNumExpansions
+        = Expansion->getNumExpansions();
+      llvm::Optional<unsigned> NumExpansions = OrigNumExpansions;
+      if (getDerived().TryExpandParameterPacks(Expansion->getEllipsisLoc(),
+                                               Pattern->getSourceRange(),
+                                               Unexpanded,
+                                               Expand, RetainExpansion,
+                                               NumExpansions))
+        return true;
+        
+      if (!Expand) {
+        // The transform has determined that we should perform a simple
+        // transformation on the pack expansion, producing another pack 
+        // expansion.
+        Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(getSema(), -1);
+        ExprResult OutPattern = getDerived().TransformExpr(Pattern);
+        if (OutPattern.isInvalid())
+          return true;
+        
+        ExprResult Out = getDerived().RebuildPackExpansion(OutPattern.get(), 
+                                                Expansion->getEllipsisLoc(),
+                                                           NumExpansions);
+        if (Out.isInvalid())
+          return true;
+        
+        if (ArgChanged)
+          *ArgChanged = true;
+        Outputs.push_back(Out.get());
+        continue;
+      }
+
+      // Record right away that the argument was changed.  This needs
+      // to happen even if the array expands to nothing.
+      if (ArgChanged) *ArgChanged = true;
+      
+      // The transform has determined that we should perform an elementwise
+      // expansion of the pattern. Do so.
+      for (unsigned I = 0; I != *NumExpansions; ++I) {
+        Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(getSema(), I);
+        ExprResult Out = getDerived().TransformExpr(Pattern);
+        if (Out.isInvalid())
+          return true;
+
+        if (Out.get()->containsUnexpandedParameterPack()) {
+          Out = RebuildPackExpansion(Out.get(), Expansion->getEllipsisLoc(),
+                                     OrigNumExpansions);
+          if (Out.isInvalid())
+            return true;
+        }
+        
+        Outputs.push_back(Out.get());
+      }
+        
+      continue;
+    }
+    
+    ExprResult Result = getDerived().TransformExpr(Inputs[I]);
+    if (Result.isInvalid())
+      return true;
+    
+    if (Result.get() != Inputs[I] && ArgChanged)
+      *ArgChanged = true;
+    
+    Outputs.push_back(Result.get());    
+  }
+  
+  return false;
+}
+
+template<typename Derived>
+NestedNameSpecifierLoc
+TreeTransform<Derived>::TransformNestedNameSpecifierLoc(
+                                                    NestedNameSpecifierLoc NNS,
+                                                     QualType ObjectType,
+                                             NamedDecl *FirstQualifierInScope) {
+  SmallVector<NestedNameSpecifierLoc, 4> Qualifiers;
+  for (NestedNameSpecifierLoc Qualifier = NNS; Qualifier; 
+       Qualifier = Qualifier.getPrefix())
+    Qualifiers.push_back(Qualifier);
+
+  CXXScopeSpec SS;
+  while (!Qualifiers.empty()) {
+    NestedNameSpecifierLoc Q = Qualifiers.pop_back_val();
+    NestedNameSpecifier *QNNS = Q.getNestedNameSpecifier();
+    
+    switch (QNNS->getKind()) {
+    case NestedNameSpecifier::Identifier:
+      if (SemaRef.BuildCXXNestedNameSpecifier(/*Scope=*/0, 
+                                              *QNNS->getAsIdentifier(),
+                                              Q.getLocalBeginLoc(), 
+                                              Q.getLocalEndLoc(),
+                                              ObjectType, false, SS, 
+                                              FirstQualifierInScope, false))
+        return NestedNameSpecifierLoc();
+        
+      break;
+      
+    case NestedNameSpecifier::Namespace: {
+      NamespaceDecl *NS
+        = cast_or_null<NamespaceDecl>(
+                                    getDerived().TransformDecl(
+                                                          Q.getLocalBeginLoc(),
+                                                       QNNS->getAsNamespace()));
+      SS.Extend(SemaRef.Context, NS, Q.getLocalBeginLoc(), Q.getLocalEndLoc());
+      break;
+    }
+      
+    case NestedNameSpecifier::NamespaceAlias: {
+      NamespaceAliasDecl *Alias
+        = cast_or_null<NamespaceAliasDecl>(
+                      getDerived().TransformDecl(Q.getLocalBeginLoc(),
+                                                 QNNS->getAsNamespaceAlias()));
+      SS.Extend(SemaRef.Context, Alias, Q.getLocalBeginLoc(), 
+                Q.getLocalEndLoc());
+      break;
+    }
+      
+    case NestedNameSpecifier::Global:
+      // There is no meaningful transformation that one could perform on the
+      // global scope.
+      SS.MakeGlobal(SemaRef.Context, Q.getBeginLoc());
+      break;
+      
+    case NestedNameSpecifier::TypeSpecWithTemplate:
+    case NestedNameSpecifier::TypeSpec: {
+      TypeLoc TL = TransformTypeInObjectScope(Q.getTypeLoc(), ObjectType,
+                                              FirstQualifierInScope, SS);
+      
+      if (!TL)
+        return NestedNameSpecifierLoc();
+      
+      if (TL.getType()->isDependentType() || TL.getType()->isRecordType() ||
+          (SemaRef.getLangOpts().CPlusPlus0x && 
+           TL.getType()->isEnumeralType())) {
+        assert(!TL.getType().hasLocalQualifiers() && 
+               "Can't get cv-qualifiers here");
+        if (TL.getType()->isEnumeralType())
+          SemaRef.Diag(TL.getBeginLoc(),
+                       diag::warn_cxx98_compat_enum_nested_name_spec);
+        SS.Extend(SemaRef.Context, /*FIXME:*/SourceLocation(), TL,
+                  Q.getLocalEndLoc());
+        break;
+      }
+      // If the nested-name-specifier is an invalid type def, don't emit an
+      // error because a previous error should have already been emitted.
+      TypedefTypeLoc* TTL = dyn_cast<TypedefTypeLoc>(&TL);
+      if (!TTL || !TTL->getTypedefNameDecl()->isInvalidDecl()) {
+        SemaRef.Diag(TL.getBeginLoc(), diag::err_nested_name_spec_non_tag) 
+          << TL.getType() << SS.getRange();
+      }
+      return NestedNameSpecifierLoc();
+    }
+    }
+    
+    // The qualifier-in-scope and object type only apply to the leftmost entity.
+    FirstQualifierInScope = 0;
+    ObjectType = QualType();
+  }
+  
+  // Don't rebuild the nested-name-specifier if we don't have to.
+  if (SS.getScopeRep() == NNS.getNestedNameSpecifier() && 
+      !getDerived().AlwaysRebuild())
+    return NNS;
+  
+  // If we can re-use the source-location data from the original 
+  // nested-name-specifier, do so.
+  if (SS.location_size() == NNS.getDataLength() &&
+      memcmp(SS.location_data(), NNS.getOpaqueData(), SS.location_size()) == 0)
+    return NestedNameSpecifierLoc(SS.getScopeRep(), NNS.getOpaqueData());
+
+  // Allocate new nested-name-specifier location information.
+  return SS.getWithLocInContext(SemaRef.Context);
+}
+
+template<typename Derived>
+DeclarationNameInfo
+TreeTransform<Derived>
+::TransformDeclarationNameInfo(const DeclarationNameInfo &NameInfo) {
+  DeclarationName Name = NameInfo.getName();
+  if (!Name)
+    return DeclarationNameInfo();
+
+  switch (Name.getNameKind()) {
+  case DeclarationName::Identifier:
+  case DeclarationName::ObjCZeroArgSelector:
+  case DeclarationName::ObjCOneArgSelector:
+  case DeclarationName::ObjCMultiArgSelector:
+  case DeclarationName::CXXOperatorName:
+  case DeclarationName::CXXLiteralOperatorName:
+  case DeclarationName::CXXUsingDirective:
+    return NameInfo;
+
+  case DeclarationName::CXXConstructorName:
+  case DeclarationName::CXXDestructorName:
+  case DeclarationName::CXXConversionFunctionName: {
+    TypeSourceInfo *NewTInfo;
+    CanQualType NewCanTy;
+    if (TypeSourceInfo *OldTInfo = NameInfo.getNamedTypeInfo()) {
+      NewTInfo = getDerived().TransformType(OldTInfo);
+      if (!NewTInfo)
+        return DeclarationNameInfo();
+      NewCanTy = SemaRef.Context.getCanonicalType(NewTInfo->getType());
+    }
+    else {
+      NewTInfo = 0;
+      TemporaryBase Rebase(*this, NameInfo.getLoc(), Name);
+      QualType NewT = getDerived().TransformType(Name.getCXXNameType());
+      if (NewT.isNull())
+        return DeclarationNameInfo();
+      NewCanTy = SemaRef.Context.getCanonicalType(NewT);
+    }
+
+    DeclarationName NewName
+      = SemaRef.Context.DeclarationNames.getCXXSpecialName(Name.getNameKind(),
+                                                           NewCanTy);
+    DeclarationNameInfo NewNameInfo(NameInfo);
+    NewNameInfo.setName(NewName);
+    NewNameInfo.setNamedTypeInfo(NewTInfo);
+    return NewNameInfo;
+  }
+  }
+
+  llvm_unreachable("Unknown name kind.");
+}
+
+template<typename Derived>
+TemplateName
+TreeTransform<Derived>::TransformTemplateName(CXXScopeSpec &SS,
+                                              TemplateName Name,
+                                              SourceLocation NameLoc,
+                                              QualType ObjectType,
+                                              NamedDecl *FirstQualifierInScope) {
+  if (QualifiedTemplateName *QTN = Name.getAsQualifiedTemplateName()) {
+    TemplateDecl *Template = QTN->getTemplateDecl();
+    assert(Template && "qualified template name must refer to a template");
+    
+    TemplateDecl *TransTemplate
+      = cast_or_null<TemplateDecl>(getDerived().TransformDecl(NameLoc, 
+                                                              Template));
+    if (!TransTemplate)
+      return TemplateName();
+      
+    if (!getDerived().AlwaysRebuild() &&
+        SS.getScopeRep() == QTN->getQualifier() &&
+        TransTemplate == Template)
+      return Name;
+      
+    return getDerived().RebuildTemplateName(SS, QTN->hasTemplateKeyword(),
+                                            TransTemplate);
+  }
+  
+  if (DependentTemplateName *DTN = Name.getAsDependentTemplateName()) {
+    if (SS.getScopeRep()) {
+      // These apply to the scope specifier, not the template.
+      ObjectType = QualType();
+      FirstQualifierInScope = 0;
+    }      
+    
+    if (!getDerived().AlwaysRebuild() &&
+        SS.getScopeRep() == DTN->getQualifier() &&
+        ObjectType.isNull())
+      return Name;
+    
+    if (DTN->isIdentifier()) {
+      return getDerived().RebuildTemplateName(SS,
+                                              *DTN->getIdentifier(), 
+                                              NameLoc,
+                                              ObjectType,
+                                              FirstQualifierInScope);
+    }
+    
+    return getDerived().RebuildTemplateName(SS, DTN->getOperator(), NameLoc,
+                                            ObjectType);
+  }
+  
+  if (TemplateDecl *Template = Name.getAsTemplateDecl()) {
+    TemplateDecl *TransTemplate
+      = cast_or_null<TemplateDecl>(getDerived().TransformDecl(NameLoc, 
+                                                              Template));
+    if (!TransTemplate)
+      return TemplateName();
+    
+    if (!getDerived().AlwaysRebuild() &&
+        TransTemplate == Template)
+      return Name;
+    
+    return TemplateName(TransTemplate);
+  }
+  
+  if (SubstTemplateTemplateParmPackStorage *SubstPack
+      = Name.getAsSubstTemplateTemplateParmPack()) {
+    TemplateTemplateParmDecl *TransParam
+    = cast_or_null<TemplateTemplateParmDecl>(
+            getDerived().TransformDecl(NameLoc, SubstPack->getParameterPack()));
+    if (!TransParam)
+      return TemplateName();
+    
+    if (!getDerived().AlwaysRebuild() &&
+        TransParam == SubstPack->getParameterPack())
+      return Name;
+    
+    return getDerived().RebuildTemplateName(TransParam, 
+                                            SubstPack->getArgumentPack());
+  }
+  
+  // These should be getting filtered out before they reach the AST.
+  llvm_unreachable("overloaded function decl survived to here");
+}
+
+template<typename Derived>
+void TreeTransform<Derived>::InventTemplateArgumentLoc(
+                                         const TemplateArgument &Arg,
+                                         TemplateArgumentLoc &Output) {
+  SourceLocation Loc = getDerived().getBaseLocation();
+  switch (Arg.getKind()) {
+  case TemplateArgument::Null:
+    llvm_unreachable("null template argument in TreeTransform");
+    break;
+
+  case TemplateArgument::Type:
+    Output = TemplateArgumentLoc(Arg,
+               SemaRef.Context.getTrivialTypeSourceInfo(Arg.getAsType(), Loc));
+                                            
+    break;
+
+  case TemplateArgument::Template:
+  case TemplateArgument::TemplateExpansion: {
+    NestedNameSpecifierLocBuilder Builder;
+    TemplateName Template = Arg.getAsTemplate();
+    if (DependentTemplateName *DTN = Template.getAsDependentTemplateName())
+      Builder.MakeTrivial(SemaRef.Context, DTN->getQualifier(), Loc);
+    else if (QualifiedTemplateName *QTN = Template.getAsQualifiedTemplateName())
+      Builder.MakeTrivial(SemaRef.Context, QTN->getQualifier(), Loc);
+        
+    if (Arg.getKind() == TemplateArgument::Template)
+      Output = TemplateArgumentLoc(Arg, 
+                                   Builder.getWithLocInContext(SemaRef.Context),
+                                   Loc);
+    else
+      Output = TemplateArgumentLoc(Arg, 
+                                   Builder.getWithLocInContext(SemaRef.Context),
+                                   Loc, Loc);
+    
+    break;
+  }
+
+  case TemplateArgument::Expression:
+    Output = TemplateArgumentLoc(Arg, Arg.getAsExpr());
+    break;
+
+  case TemplateArgument::Declaration:
+  case TemplateArgument::Integral:
+  case TemplateArgument::Pack:
+    Output = TemplateArgumentLoc(Arg, TemplateArgumentLocInfo());
+    break;
+  }
+}
+
+template<typename Derived>
+bool TreeTransform<Derived>::TransformTemplateArgument(
+                                         const TemplateArgumentLoc &Input,
+                                         TemplateArgumentLoc &Output) {
+  const TemplateArgument &Arg = Input.getArgument();
+  switch (Arg.getKind()) {
+  case TemplateArgument::Null:
+  case TemplateArgument::Integral:
+    Output = Input;
+    return false;
+
+  case TemplateArgument::Type: {
+    TypeSourceInfo *DI = Input.getTypeSourceInfo();
+    if (DI == NULL)
+      DI = InventTypeSourceInfo(Input.getArgument().getAsType());
+
+    DI = getDerived().TransformType(DI);
+    if (!DI) return true;
+
+    Output = TemplateArgumentLoc(TemplateArgument(DI->getType()), DI);
+    return false;
+  }
+
+  case TemplateArgument::Declaration: {
+    // FIXME: we should never have to transform one of these.
+    DeclarationName Name;
+    if (NamedDecl *ND = dyn_cast<NamedDecl>(Arg.getAsDecl()))
+      Name = ND->getDeclName();
+    TemporaryBase Rebase(*this, Input.getLocation(), Name);
+    Decl *D = getDerived().TransformDecl(Input.getLocation(), Arg.getAsDecl());
+    if (!D) return true;
+
+    Expr *SourceExpr = Input.getSourceDeclExpression();
+    if (SourceExpr) {
+      EnterExpressionEvaluationContext Unevaluated(getSema(),
+                                                   Sema::ConstantEvaluated);
+      ExprResult E = getDerived().TransformExpr(SourceExpr);
+      E = SemaRef.ActOnConstantExpression(E);
+      SourceExpr = (E.isInvalid() ? 0 : E.take());
+    }
+
+    Output = TemplateArgumentLoc(TemplateArgument(D), SourceExpr);
+    return false;
+  }
+
+  case TemplateArgument::Template: {
+    NestedNameSpecifierLoc QualifierLoc = Input.getTemplateQualifierLoc();
+    if (QualifierLoc) {
+      QualifierLoc = getDerived().TransformNestedNameSpecifierLoc(QualifierLoc);
+      if (!QualifierLoc)
+        return true;
+    }
+    
+    CXXScopeSpec SS;
+    SS.Adopt(QualifierLoc);
+    TemplateName Template
+      = getDerived().TransformTemplateName(SS, Arg.getAsTemplate(),
+                                           Input.getTemplateNameLoc());
+    if (Template.isNull())
+      return true;
+    
+    Output = TemplateArgumentLoc(TemplateArgument(Template), QualifierLoc,
+                                 Input.getTemplateNameLoc());
+    return false;
+  }
+
+  case TemplateArgument::TemplateExpansion:
+    llvm_unreachable("Caller should expand pack expansions");
+
+  case TemplateArgument::Expression: {
+    // Template argument expressions are constant expressions.
+    EnterExpressionEvaluationContext Unevaluated(getSema(),
+                                                 Sema::ConstantEvaluated);
+
+    Expr *InputExpr = Input.getSourceExpression();
+    if (!InputExpr) InputExpr = Input.getArgument().getAsExpr();
+
+    ExprResult E = getDerived().TransformExpr(InputExpr);
+    E = SemaRef.ActOnConstantExpression(E);
+    if (E.isInvalid()) return true;
+    Output = TemplateArgumentLoc(TemplateArgument(E.take()), E.take());
+    return false;
+  }
+
+  case TemplateArgument::Pack: {
+    SmallVector<TemplateArgument, 4> TransformedArgs;
+    TransformedArgs.reserve(Arg.pack_size());
+    for (TemplateArgument::pack_iterator A = Arg.pack_begin(),
+                                      AEnd = Arg.pack_end();
+         A != AEnd; ++A) {
+
+      // FIXME: preserve source information here when we start
+      // caring about parameter packs.
+
+      TemplateArgumentLoc InputArg;
+      TemplateArgumentLoc OutputArg;
+      getDerived().InventTemplateArgumentLoc(*A, InputArg);
+      if (getDerived().TransformTemplateArgument(InputArg, OutputArg))
+        return true;
+
+      TransformedArgs.push_back(OutputArg.getArgument());
+    }
+
+    TemplateArgument *TransformedArgsPtr
+      = new (getSema().Context) TemplateArgument[TransformedArgs.size()];
+    std::copy(TransformedArgs.begin(), TransformedArgs.end(),
+              TransformedArgsPtr);
+    Output = TemplateArgumentLoc(TemplateArgument(TransformedArgsPtr, 
+                                                  TransformedArgs.size()), 
+                                 Input.getLocInfo());
+    return false;
+  }
+  }
+
+  // Work around bogus GCC warning
+  return true;
+}
+
+/// \brief Iterator adaptor that invents template argument location information
+/// for each of the template arguments in its underlying iterator.
+template<typename Derived, typename InputIterator>
+class TemplateArgumentLocInventIterator {
+  TreeTransform<Derived> &Self;
+  InputIterator Iter;
+  
+public:
+  typedef TemplateArgumentLoc value_type;
+  typedef TemplateArgumentLoc reference;
+  typedef typename std::iterator_traits<InputIterator>::difference_type
+    difference_type;
+  typedef std::input_iterator_tag iterator_category;
+  
+  class pointer {
+    TemplateArgumentLoc Arg;
+    
+  public:
+    explicit pointer(TemplateArgumentLoc Arg) : Arg(Arg) { }
+    
+    const TemplateArgumentLoc *operator->() const { return &Arg; }
+  };
+  
+  TemplateArgumentLocInventIterator() { }
+  
+  explicit TemplateArgumentLocInventIterator(TreeTransform<Derived> &Self,
+                                             InputIterator Iter)
+    : Self(Self), Iter(Iter) { }
+  
+  TemplateArgumentLocInventIterator &operator++() {
+    ++Iter;
+    return *this;
+  }
+  
+  TemplateArgumentLocInventIterator operator++(int) {
+    TemplateArgumentLocInventIterator Old(*this);
+    ++(*this);
+    return Old;
+  }
+  
+  reference operator*() const {
+    TemplateArgumentLoc Result;
+    Self.InventTemplateArgumentLoc(*Iter, Result);
+    return Result;
+  }
+  
+  pointer operator->() const { return pointer(**this); }
+  
+  friend bool operator==(const TemplateArgumentLocInventIterator &X,
+                         const TemplateArgumentLocInventIterator &Y) {
+    return X.Iter == Y.Iter;
+  }
+
+  friend bool operator!=(const TemplateArgumentLocInventIterator &X,
+                         const TemplateArgumentLocInventIterator &Y) {
+    return X.Iter != Y.Iter;
+  }
+};
+  
+template<typename Derived>
+template<typename InputIterator>
+bool TreeTransform<Derived>::TransformTemplateArguments(InputIterator First,
+                                                        InputIterator Last,
+                                            TemplateArgumentListInfo &Outputs) {
+  for (; First != Last; ++First) {
+    TemplateArgumentLoc Out;
+    TemplateArgumentLoc In = *First;
+    
+    if (In.getArgument().getKind() == TemplateArgument::Pack) {
+      // Unpack argument packs, which we translate them into separate
+      // arguments.
+      // FIXME: We could do much better if we could guarantee that the
+      // TemplateArgumentLocInfo for the pack expansion would be usable for
+      // all of the template arguments in the argument pack.
+      typedef TemplateArgumentLocInventIterator<Derived, 
+                                                TemplateArgument::pack_iterator>
+        PackLocIterator;
+      if (TransformTemplateArguments(PackLocIterator(*this, 
+                                                 In.getArgument().pack_begin()),
+                                     PackLocIterator(*this,
+                                                   In.getArgument().pack_end()),
+                                     Outputs))
+        return true;
+      
+      continue;
+    }
+    
+    if (In.getArgument().isPackExpansion()) {
+      // We have a pack expansion, for which we will be substituting into
+      // the pattern.
+      SourceLocation Ellipsis;
+      llvm::Optional<unsigned> OrigNumExpansions;
+      TemplateArgumentLoc Pattern
+        = In.getPackExpansionPattern(Ellipsis, OrigNumExpansions, 
+                                     getSema().Context);
+      
+      SmallVector<UnexpandedParameterPack, 2> Unexpanded;
+      getSema().collectUnexpandedParameterPacks(Pattern, Unexpanded);
+      assert(!Unexpanded.empty() && "Pack expansion without parameter packs?");
+      
+      // Determine whether the set of unexpanded parameter packs can and should
+      // be expanded.
+      bool Expand = true;
+      bool RetainExpansion = false;
+      llvm::Optional<unsigned> NumExpansions = OrigNumExpansions;
+      if (getDerived().TryExpandParameterPacks(Ellipsis,
+                                               Pattern.getSourceRange(),
+                                               Unexpanded,
+                                               Expand, 
+                                               RetainExpansion,
+                                               NumExpansions))
+        return true;
+      
+      if (!Expand) {
+        // The transform has determined that we should perform a simple
+        // transformation on the pack expansion, producing another pack 
+        // expansion.
+        TemplateArgumentLoc OutPattern;
+        Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(getSema(), -1);
+        if (getDerived().TransformTemplateArgument(Pattern, OutPattern))
+          return true;
+                
+        Out = getDerived().RebuildPackExpansion(OutPattern, Ellipsis,
+                                                NumExpansions);
+        if (Out.getArgument().isNull())
+          return true;
+        
+        Outputs.addArgument(Out);
+        continue;
+      }
+      
+      // The transform has determined that we should perform an elementwise
+      // expansion of the pattern. Do so.
+      for (unsigned I = 0; I != *NumExpansions; ++I) {
+        Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(getSema(), I);
+
+        if (getDerived().TransformTemplateArgument(Pattern, Out))
+          return true;
+        
+        if (Out.getArgument().containsUnexpandedParameterPack()) {
+          Out = getDerived().RebuildPackExpansion(Out, Ellipsis,
+                                                  OrigNumExpansions);
+          if (Out.getArgument().isNull())
+            return true;
+        }
+          
+        Outputs.addArgument(Out);
+      }
+      
+      // If we're supposed to retain a pack expansion, do so by temporarily
+      // forgetting the partially-substituted parameter pack.
+      if (RetainExpansion) {
+        ForgetPartiallySubstitutedPackRAII Forget(getDerived());
+        
+        if (getDerived().TransformTemplateArgument(Pattern, Out))
+          return true;
+        
+        Out = getDerived().RebuildPackExpansion(Out, Ellipsis,
+                                                OrigNumExpansions);
+        if (Out.getArgument().isNull())
+          return true;
+        
+        Outputs.addArgument(Out);
+      }
+      
+      continue;
+    }
+    
+    // The simple case: 
+    if (getDerived().TransformTemplateArgument(In, Out))
+      return true;
+    
+    Outputs.addArgument(Out);
+  }
+  
+  return false;
+
+}
+
+//===----------------------------------------------------------------------===//
+// Type transformation
+//===----------------------------------------------------------------------===//
+
+template<typename Derived>
+QualType TreeTransform<Derived>::TransformType(QualType T) {
+  if (getDerived().AlreadyTransformed(T))
+    return T;
+
+  // Temporary workaround.  All of these transformations should
+  // eventually turn into transformations on TypeLocs.
+  TypeSourceInfo *DI = getSema().Context.getTrivialTypeSourceInfo(T,
+                                                getDerived().getBaseLocation());
+  
+  TypeSourceInfo *NewDI = getDerived().TransformType(DI);
+
+  if (!NewDI)
+    return QualType();
+
+  return NewDI->getType();
+}
+
+template<typename Derived>
+TypeSourceInfo *TreeTransform<Derived>::TransformType(TypeSourceInfo *DI) {
+  // Refine the base location to the type's location.
+  TemporaryBase Rebase(*this, DI->getTypeLoc().getBeginLoc(),
+                       getDerived().getBaseEntity());
+  if (getDerived().AlreadyTransformed(DI->getType()))
+    return DI;
+
+  TypeLocBuilder TLB;
+
+  TypeLoc TL = DI->getTypeLoc();
+  TLB.reserve(TL.getFullDataSize());
+
+  QualType Result = getDerived().TransformType(TLB, TL);
+  if (Result.isNull())
+    return 0;
+
+  return TLB.getTypeSourceInfo(SemaRef.Context, Result);
+}
+
+template<typename Derived>
+QualType
+TreeTransform<Derived>::TransformType(TypeLocBuilder &TLB, TypeLoc T) {
+  switch (T.getTypeLocClass()) {
+#define ABSTRACT_TYPELOC(CLASS, PARENT)
+#define TYPELOC(CLASS, PARENT) \
+  case TypeLoc::CLASS: \
+    return getDerived().Transform##CLASS##Type(TLB, cast<CLASS##TypeLoc>(T));
+#include "clang/AST/TypeLocNodes.def"
+  }
+
+  llvm_unreachable("unhandled type loc!");
+}
+
+/// FIXME: By default, this routine adds type qualifiers only to types
+/// that can have qualifiers, and silently suppresses those qualifiers
+/// that are not permitted (e.g., qualifiers on reference or function
+/// types). This is the right thing for template instantiation, but
+/// probably not for other clients.
+template<typename Derived>
+QualType
+TreeTransform<Derived>::TransformQualifiedType(TypeLocBuilder &TLB,
+                                               QualifiedTypeLoc T) {
+  Qualifiers Quals = T.getType().getLocalQualifiers();
+
+  QualType Result = getDerived().TransformType(TLB, T.getUnqualifiedLoc());
+  if (Result.isNull())
+    return QualType();
+
+  // Silently suppress qualifiers if the result type can't be qualified.
+  // FIXME: this is the right thing for template instantiation, but
+  // probably not for other clients.
+  if (Result->isFunctionType() || Result->isReferenceType())
+    return Result;
+
+  // Suppress Objective-C lifetime qualifiers if they don't make sense for the
+  // resulting type.
+  if (Quals.hasObjCLifetime()) {
+    if (!Result->isObjCLifetimeType() && !Result->isDependentType())
+      Quals.removeObjCLifetime();
+    else if (Result.getObjCLifetime()) {
+      // Objective-C ARC: 
+      //   A lifetime qualifier applied to a substituted template parameter
+      //   overrides the lifetime qualifier from the template argument.
+      if (const SubstTemplateTypeParmType *SubstTypeParam 
+                                = dyn_cast<SubstTemplateTypeParmType>(Result)) {
+        QualType Replacement = SubstTypeParam->getReplacementType();
+        Qualifiers Qs = Replacement.getQualifiers();
+        Qs.removeObjCLifetime();
+        Replacement 
+          = SemaRef.Context.getQualifiedType(Replacement.getUnqualifiedType(),
+                                             Qs);
+        Result = SemaRef.Context.getSubstTemplateTypeParmType(
+                                        SubstTypeParam->getReplacedParameter(), 
+                                                              Replacement);
+        TLB.TypeWasModifiedSafely(Result);
+      } else {
+        // Otherwise, complain about the addition of a qualifier to an
+        // already-qualified type.
+        SourceRange R = TLB.getTemporaryTypeLoc(Result).getSourceRange();
+        SemaRef.Diag(R.getBegin(), diag::err_attr_objc_ownership_redundant)
+          << Result << R;
+        
+        Quals.removeObjCLifetime();
+      }
+    }
+  }
+  if (!Quals.empty()) {
+    Result = SemaRef.BuildQualifiedType(Result, T.getBeginLoc(), Quals);
+    TLB.push<QualifiedTypeLoc>(Result);
+    // No location information to preserve.
+  }
+
+  return Result;
+}
+
+template<typename Derived>
+TypeLoc
+TreeTransform<Derived>::TransformTypeInObjectScope(TypeLoc TL,
+                                                   QualType ObjectType,
+                                                   NamedDecl *UnqualLookup,
+                                                   CXXScopeSpec &SS) {
+  QualType T = TL.getType();
+  if (getDerived().AlreadyTransformed(T))
+    return TL;
+  
+  TypeLocBuilder TLB;
+  QualType Result;
+  
+  if (isa<TemplateSpecializationType>(T)) {
+    TemplateSpecializationTypeLoc SpecTL
+      = cast<TemplateSpecializationTypeLoc>(TL);
+    
+    TemplateName Template =
+      getDerived().TransformTemplateName(SS,
+                                         SpecTL.getTypePtr()->getTemplateName(),
+                                         SpecTL.getTemplateNameLoc(),
+                                         ObjectType, UnqualLookup);
+    if (Template.isNull()) 
+      return TypeLoc();
+    
+    Result = getDerived().TransformTemplateSpecializationType(TLB, SpecTL, 
+                                                              Template);
+  } else if (isa<DependentTemplateSpecializationType>(T)) {
+    DependentTemplateSpecializationTypeLoc SpecTL
+      = cast<DependentTemplateSpecializationTypeLoc>(TL);
+    
+    TemplateName Template
+      = getDerived().RebuildTemplateName(SS, 
+                                         *SpecTL.getTypePtr()->getIdentifier(), 
+                                         SpecTL.getTemplateNameLoc(),
+                                         ObjectType, UnqualLookup);
+    if (Template.isNull())
+      return TypeLoc();
+    
+    Result = getDerived().TransformDependentTemplateSpecializationType(TLB, 
+                                                                       SpecTL,
+                                                                     Template,
+                                                                       SS);
+  } else {
+    // Nothing special needs to be done for these.
+    Result = getDerived().TransformType(TLB, TL);
+  }
+  
+  if (Result.isNull()) 
+    return TypeLoc();
+  
+  return TLB.getTypeSourceInfo(SemaRef.Context, Result)->getTypeLoc();
+}
+
+template<typename Derived>
+TypeSourceInfo *
+TreeTransform<Derived>::TransformTypeInObjectScope(TypeSourceInfo *TSInfo,
+                                                   QualType ObjectType,
+                                                   NamedDecl *UnqualLookup,
+                                                   CXXScopeSpec &SS) {
+  // FIXME: Painfully copy-paste from the above!
+  
+  QualType T = TSInfo->getType();
+  if (getDerived().AlreadyTransformed(T))
+    return TSInfo;
+  
+  TypeLocBuilder TLB;
+  QualType Result;
+  
+  TypeLoc TL = TSInfo->getTypeLoc();
+  if (isa<TemplateSpecializationType>(T)) {
+    TemplateSpecializationTypeLoc SpecTL
+      = cast<TemplateSpecializationTypeLoc>(TL);
+    
+    TemplateName Template
+    = getDerived().TransformTemplateName(SS,
+                                         SpecTL.getTypePtr()->getTemplateName(),
+                                         SpecTL.getTemplateNameLoc(),
+                                         ObjectType, UnqualLookup);
+    if (Template.isNull()) 
+      return 0;
+    
+    Result = getDerived().TransformTemplateSpecializationType(TLB, SpecTL, 
+                                                              Template);
+  } else if (isa<DependentTemplateSpecializationType>(T)) {
+    DependentTemplateSpecializationTypeLoc SpecTL
+      = cast<DependentTemplateSpecializationTypeLoc>(TL);
+    
+    TemplateName Template
+      = getDerived().RebuildTemplateName(SS, 
+                                         *SpecTL.getTypePtr()->getIdentifier(), 
+                                         SpecTL.getTemplateNameLoc(),
+                                         ObjectType, UnqualLookup);
+    if (Template.isNull())
+      return 0;
+    
+    Result = getDerived().TransformDependentTemplateSpecializationType(TLB, 
+                                                                       SpecTL,
+                                                                       Template,
+                                                                       SS);
+  } else {
+    // Nothing special needs to be done for these.
+    Result = getDerived().TransformType(TLB, TL);
+  }
+  
+  if (Result.isNull()) 
+    return 0;
+  
+  return TLB.getTypeSourceInfo(SemaRef.Context, Result);
+}
+
+template <class TyLoc> static inline
+QualType TransformTypeSpecType(TypeLocBuilder &TLB, TyLoc T) {
+  TyLoc NewT = TLB.push<TyLoc>(T.getType());
+  NewT.setNameLoc(T.getNameLoc());
+  return T.getType();
+}
+
+template<typename Derived>
+QualType TreeTransform<Derived>::TransformBuiltinType(TypeLocBuilder &TLB,
+                                                      BuiltinTypeLoc T) {
+  BuiltinTypeLoc NewT = TLB.push<BuiltinTypeLoc>(T.getType());
+  NewT.setBuiltinLoc(T.getBuiltinLoc());
+  if (T.needsExtraLocalData())
+    NewT.getWrittenBuiltinSpecs() = T.getWrittenBuiltinSpecs();
+  return T.getType();
+}
+
+template<typename Derived>
+QualType TreeTransform<Derived>::TransformComplexType(TypeLocBuilder &TLB,
+                                                      ComplexTypeLoc T) {
+  // FIXME: recurse?
+  return TransformTypeSpecType(TLB, T);
+}
+
+template<typename Derived>
+QualType TreeTransform<Derived>::TransformPointerType(TypeLocBuilder &TLB,
+                                                      PointerTypeLoc TL) {
+  QualType PointeeType                                      
+    = getDerived().TransformType(TLB, TL.getPointeeLoc());  
+  if (PointeeType.isNull())
+    return QualType();
+
+  QualType Result = TL.getType();
+  if (PointeeType->getAs<ObjCObjectType>()) {
+    // A dependent pointer type 'T *' has is being transformed such
+    // that an Objective-C class type is being replaced for 'T'. The
+    // resulting pointer type is an ObjCObjectPointerType, not a
+    // PointerType.
+    Result = SemaRef.Context.getObjCObjectPointerType(PointeeType);
+    
+    ObjCObjectPointerTypeLoc NewT = TLB.push<ObjCObjectPointerTypeLoc>(Result);
+    NewT.setStarLoc(TL.getStarLoc());
+    return Result;
+  }
+
+  if (getDerived().AlwaysRebuild() ||
+      PointeeType != TL.getPointeeLoc().getType()) {
+    Result = getDerived().RebuildPointerType(PointeeType, TL.getSigilLoc());
+    if (Result.isNull())
+      return QualType();
+  }
+               
+  // Objective-C ARC can add lifetime qualifiers to the type that we're
+  // pointing to.
+  TLB.TypeWasModifiedSafely(Result->getPointeeType());
+  
+  PointerTypeLoc NewT = TLB.push<PointerTypeLoc>(Result);
+  NewT.setSigilLoc(TL.getSigilLoc());
+  return Result;  
+}
+
+template<typename Derived>
+QualType
+TreeTransform<Derived>::TransformBlockPointerType(TypeLocBuilder &TLB,
+                                                  BlockPointerTypeLoc TL) {
+  QualType PointeeType
+    = getDerived().TransformType(TLB, TL.getPointeeLoc());  
+  if (PointeeType.isNull())                                 
+    return QualType();                                      
+  
+  QualType Result = TL.getType();                           
+  if (getDerived().AlwaysRebuild() ||                       
+      PointeeType != TL.getPointeeLoc().getType()) {        
+    Result = getDerived().RebuildBlockPointerType(PointeeType, 
+                                                  TL.getSigilLoc());
+    if (Result.isNull())
+      return QualType();
+  }
+
+  BlockPointerTypeLoc NewT = TLB.push<BlockPointerTypeLoc>(Result);
+  NewT.setSigilLoc(TL.getSigilLoc());
+  return Result;
+}
+
+/// Transforms a reference type.  Note that somewhat paradoxically we
+/// don't care whether the type itself is an l-value type or an r-value
+/// type;  we only care if the type was *written* as an l-value type
+/// or an r-value type.
+template<typename Derived>
+QualType
+TreeTransform<Derived>::TransformReferenceType(TypeLocBuilder &TLB,
+                                               ReferenceTypeLoc TL) {
+  const ReferenceType *T = TL.getTypePtr();
+
+  // Note that this works with the pointee-as-written.
+  QualType PointeeType = getDerived().TransformType(TLB, TL.getPointeeLoc());
+  if (PointeeType.isNull())
+    return QualType();
+
+  QualType Result = TL.getType();
+  if (getDerived().AlwaysRebuild() ||
+      PointeeType != T->getPointeeTypeAsWritten()) {
+    Result = getDerived().RebuildReferenceType(PointeeType,
+                                               T->isSpelledAsLValue(),
+                                               TL.getSigilLoc());
+    if (Result.isNull())
+      return QualType();
+  }
+
+  // Objective-C ARC can add lifetime qualifiers to the type that we're
+  // referring to.
+  TLB.TypeWasModifiedSafely(
+                     Result->getAs<ReferenceType>()->getPointeeTypeAsWritten());
+
+  // r-value references can be rebuilt as l-value references.
+  ReferenceTypeLoc NewTL;
+  if (isa<LValueReferenceType>(Result))
+    NewTL = TLB.push<LValueReferenceTypeLoc>(Result);
+  else
+    NewTL = TLB.push<RValueReferenceTypeLoc>(Result);
+  NewTL.setSigilLoc(TL.getSigilLoc());
+
+  return Result;
+}
+
+template<typename Derived>
+QualType
+TreeTransform<Derived>::TransformLValueReferenceType(TypeLocBuilder &TLB,
+                                                 LValueReferenceTypeLoc TL) {
+  return TransformReferenceType(TLB, TL);
+}
+
+template<typename Derived>
+QualType
+TreeTransform<Derived>::TransformRValueReferenceType(TypeLocBuilder &TLB,
+                                                 RValueReferenceTypeLoc TL) {
+  return TransformReferenceType(TLB, TL);
+}
+
+template<typename Derived>
+QualType
+TreeTransform<Derived>::TransformMemberPointerType(TypeLocBuilder &TLB,
+                                                   MemberPointerTypeLoc TL) {
+  QualType PointeeType = getDerived().TransformType(TLB, TL.getPointeeLoc());
+  if (PointeeType.isNull())
+    return QualType();
+
+  TypeSourceInfo* OldClsTInfo = TL.getClassTInfo();
+  TypeSourceInfo* NewClsTInfo = 0;
+  if (OldClsTInfo) {
+    NewClsTInfo = getDerived().TransformType(OldClsTInfo);
+    if (!NewClsTInfo)
+      return QualType();
+  }
+
+  const MemberPointerType *T = TL.getTypePtr();
+  QualType OldClsType = QualType(T->getClass(), 0);
+  QualType NewClsType;
+  if (NewClsTInfo)
+    NewClsType = NewClsTInfo->getType();
+  else {
+    NewClsType = getDerived().TransformType(OldClsType);
+    if (NewClsType.isNull())
+      return QualType();
+  }
+
+  QualType Result = TL.getType();
+  if (getDerived().AlwaysRebuild() ||
+      PointeeType != T->getPointeeType() ||
+      NewClsType != OldClsType) {
+    Result = getDerived().RebuildMemberPointerType(PointeeType, NewClsType,
+                                                   TL.getStarLoc());
+    if (Result.isNull())
+      return QualType();
+  }
+
+  MemberPointerTypeLoc NewTL = TLB.push<MemberPointerTypeLoc>(Result);
+  NewTL.setSigilLoc(TL.getSigilLoc());
+  NewTL.setClassTInfo(NewClsTInfo);
+
+  return Result;
+}
+
+template<typename Derived>
+QualType
+TreeTransform<Derived>::TransformConstantArrayType(TypeLocBuilder &TLB,
+                                                   ConstantArrayTypeLoc TL) {
+  const ConstantArrayType *T = TL.getTypePtr();
+  QualType ElementType = getDerived().TransformType(TLB, TL.getElementLoc());
+  if (ElementType.isNull())
+    return QualType();
+
+  QualType Result = TL.getType();
+  if (getDerived().AlwaysRebuild() ||
+      ElementType != T->getElementType()) {
+    Result = getDerived().RebuildConstantArrayType(ElementType,
+                                                   T->getSizeModifier(),
+                                                   T->getSize(),
+                                             T->getIndexTypeCVRQualifiers(),
+                                                   TL.getBracketsRange());
+    if (Result.isNull())
+      return QualType();
+  }
+
+  // We might have either a ConstantArrayType or a VariableArrayType now:
+  // a ConstantArrayType is allowed to have an element type which is a
+  // VariableArrayType if the type is dependent.  Fortunately, all array
+  // types have the same location layout.
+  ArrayTypeLoc NewTL = TLB.push<ArrayTypeLoc>(Result);
+  NewTL.setLBracketLoc(TL.getLBracketLoc());
+  NewTL.setRBracketLoc(TL.getRBracketLoc());
+
+  Expr *Size = TL.getSizeExpr();
+  if (Size) {
+    EnterExpressionEvaluationContext Unevaluated(SemaRef,
+                                                 Sema::ConstantEvaluated);
+    Size = getDerived().TransformExpr(Size).template takeAs<Expr>();
+    Size = SemaRef.ActOnConstantExpression(Size).take();
+  }
+  NewTL.setSizeExpr(Size);
+
+  return Result;
+}
+
+template<typename Derived>
+QualType TreeTransform<Derived>::TransformIncompleteArrayType(
+                                              TypeLocBuilder &TLB,
+                                              IncompleteArrayTypeLoc TL) {
+  const IncompleteArrayType *T = TL.getTypePtr();
+  QualType ElementType = getDerived().TransformType(TLB, TL.getElementLoc());
+  if (ElementType.isNull())
+    return QualType();
+
+  QualType Result = TL.getType();
+  if (getDerived().AlwaysRebuild() ||
+      ElementType != T->getElementType()) {
+    Result = getDerived().RebuildIncompleteArrayType(ElementType,
+                                                     T->getSizeModifier(),
+                                           T->getIndexTypeCVRQualifiers(),
+                                                     TL.getBracketsRange());
+    if (Result.isNull())
+      return QualType();
+  }
+  
+  IncompleteArrayTypeLoc NewTL = TLB.push<IncompleteArrayTypeLoc>(Result);
+  NewTL.setLBracketLoc(TL.getLBracketLoc());
+  NewTL.setRBracketLoc(TL.getRBracketLoc());
+  NewTL.setSizeExpr(0);
+
+  return Result;
+}
+
+template<typename Derived>
+QualType
+TreeTransform<Derived>::TransformVariableArrayType(TypeLocBuilder &TLB,
+                                                   VariableArrayTypeLoc TL) {
+  const VariableArrayType *T = TL.getTypePtr();
+  QualType ElementType = getDerived().TransformType(TLB, TL.getElementLoc());
+  if (ElementType.isNull())
+    return QualType();
+
+  ExprResult SizeResult
+    = getDerived().TransformExpr(T->getSizeExpr());
+  if (SizeResult.isInvalid())
+    return QualType();
+
+  Expr *Size = SizeResult.take();
+
+  QualType Result = TL.getType();
+  if (getDerived().AlwaysRebuild() ||
+      ElementType != T->getElementType() ||
+      Size != T->getSizeExpr()) {
+    Result = getDerived().RebuildVariableArrayType(ElementType,
+                                                   T->getSizeModifier(),
+                                                   Size,
+                                             T->getIndexTypeCVRQualifiers(),
+                                                   TL.getBracketsRange());
+    if (Result.isNull())
+      return QualType();
+  }
+  
+  VariableArrayTypeLoc NewTL = TLB.push<VariableArrayTypeLoc>(Result);
+  NewTL.setLBracketLoc(TL.getLBracketLoc());
+  NewTL.setRBracketLoc(TL.getRBracketLoc());
+  NewTL.setSizeExpr(Size);
+
+  return Result;
+}
+
+template<typename Derived>
+QualType
+TreeTransform<Derived>::TransformDependentSizedArrayType(TypeLocBuilder &TLB,
+                                             DependentSizedArrayTypeLoc TL) {
+  const DependentSizedArrayType *T = TL.getTypePtr();
+  QualType ElementType = getDerived().TransformType(TLB, TL.getElementLoc());
+  if (ElementType.isNull())
+    return QualType();
+
+  // Array bounds are constant expressions.
+  EnterExpressionEvaluationContext Unevaluated(SemaRef,
+                                               Sema::ConstantEvaluated);
+
+  // Prefer the expression from the TypeLoc;  the other may have been uniqued.
+  Expr *origSize = TL.getSizeExpr();
+  if (!origSize) origSize = T->getSizeExpr();
+
+  ExprResult sizeResult
+    = getDerived().TransformExpr(origSize);
+  sizeResult = SemaRef.ActOnConstantExpression(sizeResult);
+  if (sizeResult.isInvalid())
+    return QualType();
+
+  Expr *size = sizeResult.get();
+
+  QualType Result = TL.getType();
+  if (getDerived().AlwaysRebuild() ||
+      ElementType != T->getElementType() ||
+      size != origSize) {
+    Result = getDerived().RebuildDependentSizedArrayType(ElementType,
+                                                         T->getSizeModifier(),
+                                                         size,
+                                                T->getIndexTypeCVRQualifiers(),
+                                                        TL.getBracketsRange());
+    if (Result.isNull())
+      return QualType();
+  }
+
+  // We might have any sort of array type now, but fortunately they
+  // all have the same location layout.
+  ArrayTypeLoc NewTL = TLB.push<ArrayTypeLoc>(Result);
+  NewTL.setLBracketLoc(TL.getLBracketLoc());
+  NewTL.setRBracketLoc(TL.getRBracketLoc());
+  NewTL.setSizeExpr(size);
+
+  return Result;
+}
+
+template<typename Derived>
+QualType TreeTransform<Derived>::TransformDependentSizedExtVectorType(
+                                      TypeLocBuilder &TLB,
+                                      DependentSizedExtVectorTypeLoc TL) {
+  const DependentSizedExtVectorType *T = TL.getTypePtr();
+
+  // FIXME: ext vector locs should be nested
+  QualType ElementType = getDerived().TransformType(T->getElementType());
+  if (ElementType.isNull())
+    return QualType();
+
+  // Vector sizes are constant expressions.
+  EnterExpressionEvaluationContext Unevaluated(SemaRef,
+                                               Sema::ConstantEvaluated);
+
+  ExprResult Size = getDerived().TransformExpr(T->getSizeExpr());
+  Size = SemaRef.ActOnConstantExpression(Size);
+  if (Size.isInvalid())
+    return QualType();
+
+  QualType Result = TL.getType();
+  if (getDerived().AlwaysRebuild() ||
+      ElementType != T->getElementType() ||
+      Size.get() != T->getSizeExpr()) {
+    Result = getDerived().RebuildDependentSizedExtVectorType(ElementType,
+                                                             Size.take(),
+                                                         T->getAttributeLoc());
+    if (Result.isNull())
+      return QualType();
+  }
+
+  // Result might be dependent or not.
+  if (isa<DependentSizedExtVectorType>(Result)) {
+    DependentSizedExtVectorTypeLoc NewTL
+      = TLB.push<DependentSizedExtVectorTypeLoc>(Result);
+    NewTL.setNameLoc(TL.getNameLoc());
+  } else {
+    ExtVectorTypeLoc NewTL = TLB.push<ExtVectorTypeLoc>(Result);
+    NewTL.setNameLoc(TL.getNameLoc());
+  }
+
+  return Result;
+}
+
+template<typename Derived>
+QualType TreeTransform<Derived>::TransformVectorType(TypeLocBuilder &TLB,
+                                                     VectorTypeLoc TL) {
+  const VectorType *T = TL.getTypePtr();
+  QualType ElementType = getDerived().TransformType(T->getElementType());
+  if (ElementType.isNull())
+    return QualType();
+
+  QualType Result = TL.getType();
+  if (getDerived().AlwaysRebuild() ||
+      ElementType != T->getElementType()) {
+    Result = getDerived().RebuildVectorType(ElementType, T->getNumElements(),
+                                            T->getVectorKind());
+    if (Result.isNull())
+      return QualType();
+  }
+  
+  VectorTypeLoc NewTL = TLB.push<VectorTypeLoc>(Result);
+  NewTL.setNameLoc(TL.getNameLoc());
+
+  return Result;
+}
+
+template<typename Derived>
+QualType TreeTransform<Derived>::TransformExtVectorType(TypeLocBuilder &TLB,
+                                                        ExtVectorTypeLoc TL) {
+  const VectorType *T = TL.getTypePtr();
+  QualType ElementType = getDerived().TransformType(T->getElementType());
+  if (ElementType.isNull())
+    return QualType();
+
+  QualType Result = TL.getType();
+  if (getDerived().AlwaysRebuild() ||
+      ElementType != T->getElementType()) {
+    Result = getDerived().RebuildExtVectorType(ElementType,
+                                               T->getNumElements(),
+                                               /*FIXME*/ SourceLocation());
+    if (Result.isNull())
+      return QualType();
+  }
+  
+  ExtVectorTypeLoc NewTL = TLB.push<ExtVectorTypeLoc>(Result);
+  NewTL.setNameLoc(TL.getNameLoc());
+
+  return Result;
+}
+
+template<typename Derived>
+ParmVarDecl *
+TreeTransform<Derived>::TransformFunctionTypeParam(ParmVarDecl *OldParm,
+                                                   int indexAdjustment,
+                                         llvm::Optional<unsigned> NumExpansions,
+                                                   bool ExpectParameterPack) {
+  TypeSourceInfo *OldDI = OldParm->getTypeSourceInfo();
+  TypeSourceInfo *NewDI = 0;
+  
+  if (NumExpansions && isa<PackExpansionType>(OldDI->getType())) {
+    // If we're substituting into a pack expansion type and we know the 
+    // length we want to expand to, just substitute for the pattern.
+    TypeLoc OldTL = OldDI->getTypeLoc();
+    PackExpansionTypeLoc OldExpansionTL = cast<PackExpansionTypeLoc>(OldTL);
+    
+    TypeLocBuilder TLB;
+    TypeLoc NewTL = OldDI->getTypeLoc();
+    TLB.reserve(NewTL.getFullDataSize());
+    
+    QualType Result = getDerived().TransformType(TLB, 
+                                               OldExpansionTL.getPatternLoc());
+    if (Result.isNull())
+      return 0;
+   
+    Result = RebuildPackExpansionType(Result, 
+                                OldExpansionTL.getPatternLoc().getSourceRange(), 
+                                      OldExpansionTL.getEllipsisLoc(),
+                                      NumExpansions);
+    if (Result.isNull())
+      return 0;
+    
+    PackExpansionTypeLoc NewExpansionTL
+      = TLB.push<PackExpansionTypeLoc>(Result);
+    NewExpansionTL.setEllipsisLoc(OldExpansionTL.getEllipsisLoc());
+    NewDI = TLB.getTypeSourceInfo(SemaRef.Context, Result);
+  } else
+    NewDI = getDerived().TransformType(OldDI);
+  if (!NewDI)
+    return 0;
+
+  if (NewDI == OldDI && indexAdjustment == 0)
+    return OldParm;
+
+  ParmVarDecl *newParm = ParmVarDecl::Create(SemaRef.Context,
+                                             OldParm->getDeclContext(),
+                                             OldParm->getInnerLocStart(),
+                                             OldParm->getLocation(),
+                                             OldParm->getIdentifier(),
+                                             NewDI->getType(),
+                                             NewDI,
+                                             OldParm->getStorageClass(),
+                                             OldParm->getStorageClassAsWritten(),
+                                             /* DefArg */ NULL);
+  newParm->setScopeInfo(OldParm->getFunctionScopeDepth(),
+                        OldParm->getFunctionScopeIndex() + indexAdjustment);
+  return newParm;
+}
+
+template<typename Derived>
+bool TreeTransform<Derived>::
+  TransformFunctionTypeParams(SourceLocation Loc,
+                              ParmVarDecl **Params, unsigned NumParams,
+                              const QualType *ParamTypes,
+                              SmallVectorImpl<QualType> &OutParamTypes,
+                              SmallVectorImpl<ParmVarDecl*> *PVars) {
+  int indexAdjustment = 0;
+
+  for (unsigned i = 0; i != NumParams; ++i) {
+    if (ParmVarDecl *OldParm = Params[i]) {
+      assert(OldParm->getFunctionScopeIndex() == i);
+
+      llvm::Optional<unsigned> NumExpansions;
+      ParmVarDecl *NewParm = 0;
+      if (OldParm->isParameterPack()) {
+        // We have a function parameter pack that may need to be expanded.
+        SmallVector<UnexpandedParameterPack, 2> Unexpanded;
+
+        // Find the parameter packs that could be expanded.
+        TypeLoc TL = OldParm->getTypeSourceInfo()->getTypeLoc();
+        PackExpansionTypeLoc ExpansionTL = cast<PackExpansionTypeLoc>(TL);
+        TypeLoc Pattern = ExpansionTL.getPatternLoc();
+        SemaRef.collectUnexpandedParameterPacks(Pattern, Unexpanded);
+        assert(Unexpanded.size() > 0 && "Could not find parameter packs!");
+
+        // Determine whether we should expand the parameter packs.
+        bool ShouldExpand = false;
+        bool RetainExpansion = false;
+        llvm::Optional<unsigned> OrigNumExpansions
+          = ExpansionTL.getTypePtr()->getNumExpansions();
+        NumExpansions = OrigNumExpansions;
+        if (getDerived().TryExpandParameterPacks(ExpansionTL.getEllipsisLoc(),
+                                                 Pattern.getSourceRange(),
+                                                 Unexpanded, 
+                                                 ShouldExpand, 
+                                                 RetainExpansion,
+                                                 NumExpansions)) {
+          return true;
+        }
+        
+        if (ShouldExpand) {
+          // Expand the function parameter pack into multiple, separate
+          // parameters.
+          getDerived().ExpandingFunctionParameterPack(OldParm);
+          for (unsigned I = 0; I != *NumExpansions; ++I) {
+            Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(getSema(), I);
+            ParmVarDecl *NewParm 
+              = getDerived().TransformFunctionTypeParam(OldParm,
+                                                        indexAdjustment++,
+                                                        OrigNumExpansions,
+                                                /*ExpectParameterPack=*/false);
+            if (!NewParm)
+              return true;
+            
+            OutParamTypes.push_back(NewParm->getType());
+            if (PVars)
+              PVars->push_back(NewParm);
+          }
+
+          // If we're supposed to retain a pack expansion, do so by temporarily
+          // forgetting the partially-substituted parameter pack.
+          if (RetainExpansion) {
+            ForgetPartiallySubstitutedPackRAII Forget(getDerived());
+            ParmVarDecl *NewParm 
+              = getDerived().TransformFunctionTypeParam(OldParm,
+                                                        indexAdjustment++,
+                                                        OrigNumExpansions,
+                                                /*ExpectParameterPack=*/false);
+            if (!NewParm)
+              return true;
+            
+            OutParamTypes.push_back(NewParm->getType());
+            if (PVars)
+              PVars->push_back(NewParm);
+          }
+
+          // The next parameter should have the same adjustment as the
+          // last thing we pushed, but we post-incremented indexAdjustment
+          // on every push.  Also, if we push nothing, the adjustment should
+          // go down by one.
+          indexAdjustment--;
+
+          // We're done with the pack expansion.
+          continue;
+        }
+        
+        // We'll substitute the parameter now without expanding the pack 
+        // expansion.
+        Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(getSema(), -1);
+        NewParm = getDerived().TransformFunctionTypeParam(OldParm,
+                                                          indexAdjustment,
+                                                          NumExpansions,
+                                                  /*ExpectParameterPack=*/true);
+      } else {
+        NewParm = getDerived().TransformFunctionTypeParam(OldParm,
+                                                          indexAdjustment,
+                                                          llvm::Optional<unsigned>(),
+                                                /*ExpectParameterPack=*/false);
+      }
+
+      if (!NewParm)
+        return true;
+      
+      OutParamTypes.push_back(NewParm->getType());
+      if (PVars)
+        PVars->push_back(NewParm);
+      continue;
+    }
+
+    // Deal with the possibility that we don't have a parameter
+    // declaration for this parameter.
+    QualType OldType = ParamTypes[i];
+    bool IsPackExpansion = false;
+    llvm::Optional<unsigned> NumExpansions;
+    QualType NewType;
+    if (const PackExpansionType *Expansion 
+                                       = dyn_cast<PackExpansionType>(OldType)) {
+      // We have a function parameter pack that may need to be expanded.
+      QualType Pattern = Expansion->getPattern();
+      SmallVector<UnexpandedParameterPack, 2> Unexpanded;
+      getSema().collectUnexpandedParameterPacks(Pattern, Unexpanded);
+      
+      // Determine whether we should expand the parameter packs.
+      bool ShouldExpand = false;
+      bool RetainExpansion = false;
+      if (getDerived().TryExpandParameterPacks(Loc, SourceRange(),
+                                               Unexpanded, 
+                                               ShouldExpand, 
+                                               RetainExpansion,
+                                               NumExpansions)) {
+        return true;
+      }
+      
+      if (ShouldExpand) {
+        // Expand the function parameter pack into multiple, separate 
+        // parameters.
+        for (unsigned I = 0; I != *NumExpansions; ++I) {
+          Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(getSema(), I);
+          QualType NewType = getDerived().TransformType(Pattern);
+          if (NewType.isNull())
+            return true;
+
+          OutParamTypes.push_back(NewType);
+          if (PVars)
+            PVars->push_back(0);
+        }
+        
+        // We're done with the pack expansion.
+        continue;
+      }
+      
+      // If we're supposed to retain a pack expansion, do so by temporarily
+      // forgetting the partially-substituted parameter pack.
+      if (RetainExpansion) {
+        ForgetPartiallySubstitutedPackRAII Forget(getDerived());
+        QualType NewType = getDerived().TransformType(Pattern);
+        if (NewType.isNull())
+          return true;
+        
+        OutParamTypes.push_back(NewType);
+        if (PVars)
+          PVars->push_back(0);
+      }
+
+      // We'll substitute the parameter now without expanding the pack 
+      // expansion.
+      OldType = Expansion->getPattern();
+      IsPackExpansion = true;
+      Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(getSema(), -1);
+      NewType = getDerived().TransformType(OldType);
+    } else {
+      NewType = getDerived().TransformType(OldType);
+    }
+    
+    if (NewType.isNull())
+      return true;
+
+    if (IsPackExpansion)
+      NewType = getSema().Context.getPackExpansionType(NewType,
+                                                       NumExpansions);
+      
+    OutParamTypes.push_back(NewType);
+    if (PVars)
+      PVars->push_back(0);
+  }
+
+#ifndef NDEBUG
+  if (PVars) {
+    for (unsigned i = 0, e = PVars->size(); i != e; ++i)
+      if (ParmVarDecl *parm = (*PVars)[i])
+        assert(parm->getFunctionScopeIndex() == i);
+  }
+#endif
+
+  return false;
+}
+
+template<typename Derived>
+QualType
+TreeTransform<Derived>::TransformFunctionProtoType(TypeLocBuilder &TLB,
+                                                   FunctionProtoTypeLoc TL) {
+  return getDerived().TransformFunctionProtoType(TLB, TL, 0, 0);
+}
+
+template<typename Derived>
+QualType
+TreeTransform<Derived>::TransformFunctionProtoType(TypeLocBuilder &TLB,
+                                                   FunctionProtoTypeLoc TL,
+                                                   CXXRecordDecl *ThisContext,
+                                                   unsigned ThisTypeQuals) {
+  // Transform the parameters and return type.
+  //
+  // We are required to instantiate the params and return type in source order.
+  // When the function has a trailing return type, we instantiate the
+  // parameters before the return type,  since the return type can then refer
+  // to the parameters themselves (via decltype, sizeof, etc.).
+  //
+  SmallVector<QualType, 4> ParamTypes;
+  SmallVector<ParmVarDecl*, 4> ParamDecls;
+  const FunctionProtoType *T = TL.getTypePtr();
+
+  QualType ResultType;
+
+  if (TL.getTrailingReturn()) {
+    if (getDerived().TransformFunctionTypeParams(TL.getBeginLoc(), 
+                                                 TL.getParmArray(),
+                                                 TL.getNumArgs(),
+                                             TL.getTypePtr()->arg_type_begin(),                                                
+                                                 ParamTypes, &ParamDecls))
+      return QualType();
+
+    {
+      // C++11 [expr.prim.general]p3:
+      //   If a declaration declares a member function or member function 
+      //   template of a class X, the expression this is a prvalue of type 
+      //   "pointer to cv-qualifier-seq X" between the optional cv-qualifer-seq
+      //   and the end of the function-definition, member-declarator, or 
+      //   declarator.
+      Sema::CXXThisScopeRAII ThisScope(SemaRef, ThisContext, ThisTypeQuals);
+      
+      ResultType = getDerived().TransformType(TLB, TL.getResultLoc());
+      if (ResultType.isNull())
+        return QualType();
+    }
+  }
+  else {
+    ResultType = getDerived().TransformType(TLB, TL.getResultLoc());
+    if (ResultType.isNull())
+      return QualType();
+
+    if (getDerived().TransformFunctionTypeParams(TL.getBeginLoc(), 
+                                                 TL.getParmArray(),
+                                                 TL.getNumArgs(),
+                                             TL.getTypePtr()->arg_type_begin(),                                                
+                                                 ParamTypes, &ParamDecls))
+      return QualType();
+  }
+
+  // FIXME: Need to transform the exception-specification too.
+
+  QualType Result = TL.getType();
+  if (getDerived().AlwaysRebuild() ||
+      ResultType != T->getResultType() ||
+      T->getNumArgs() != ParamTypes.size() ||
+      !std::equal(T->arg_type_begin(), T->arg_type_end(), ParamTypes.begin())) {
+    Result = getDerived().RebuildFunctionProtoType(ResultType,
+                                                   ParamTypes.data(),
+                                                   ParamTypes.size(),
+                                                   T->isVariadic(),
+                                                   T->hasTrailingReturn(),
+                                                   T->getTypeQuals(),
+                                                   T->getRefQualifier(),
+                                                   T->getExtInfo());
+    if (Result.isNull())
+      return QualType();
+  }
+
+  FunctionProtoTypeLoc NewTL = TLB.push<FunctionProtoTypeLoc>(Result);
+  NewTL.setLocalRangeBegin(TL.getLocalRangeBegin());
+  NewTL.setLocalRangeEnd(TL.getLocalRangeEnd());
+  NewTL.setTrailingReturn(TL.getTrailingReturn());
+  for (unsigned i = 0, e = NewTL.getNumArgs(); i != e; ++i)
+    NewTL.setArg(i, ParamDecls[i]);
+
+  return Result;
+}
+
+template<typename Derived>
+QualType TreeTransform<Derived>::TransformFunctionNoProtoType(
+                                                 TypeLocBuilder &TLB,
+                                                 FunctionNoProtoTypeLoc TL) {
+  const FunctionNoProtoType *T = TL.getTypePtr();
+  QualType ResultType = getDerived().TransformType(TLB, TL.getResultLoc());
+  if (ResultType.isNull())
+    return QualType();
+
+  QualType Result = TL.getType();
+  if (getDerived().AlwaysRebuild() ||
+      ResultType != T->getResultType())
+    Result = getDerived().RebuildFunctionNoProtoType(ResultType);
+
+  FunctionNoProtoTypeLoc NewTL = TLB.push<FunctionNoProtoTypeLoc>(Result);
+  NewTL.setLocalRangeBegin(TL.getLocalRangeBegin());
+  NewTL.setLocalRangeEnd(TL.getLocalRangeEnd());
+  NewTL.setTrailingReturn(false);
+
+  return Result;
+}
+
+template<typename Derived> QualType
+TreeTransform<Derived>::TransformUnresolvedUsingType(TypeLocBuilder &TLB,
+                                                 UnresolvedUsingTypeLoc TL) {
+  const UnresolvedUsingType *T = TL.getTypePtr();
+  Decl *D = getDerived().TransformDecl(TL.getNameLoc(), T->getDecl());
+  if (!D)
+    return QualType();
+
+  QualType Result = TL.getType();
+  if (getDerived().AlwaysRebuild() || D != T->getDecl()) {
+    Result = getDerived().RebuildUnresolvedUsingType(D);
+    if (Result.isNull())
+      return QualType();
+  }
+
+  // We might get an arbitrary type spec type back.  We should at
+  // least always get a type spec type, though.
+  TypeSpecTypeLoc NewTL = TLB.pushTypeSpec(Result);
+  NewTL.setNameLoc(TL.getNameLoc());
+
+  return Result;
+}
+
+template<typename Derived>
+QualType TreeTransform<Derived>::TransformTypedefType(TypeLocBuilder &TLB,
+                                                      TypedefTypeLoc TL) {
+  const TypedefType *T = TL.getTypePtr();
+  TypedefNameDecl *Typedef
+    = cast_or_null<TypedefNameDecl>(getDerived().TransformDecl(TL.getNameLoc(),
+                                                               T->getDecl()));
+  if (!Typedef)
+    return QualType();
+
+  QualType Result = TL.getType();
+  if (getDerived().AlwaysRebuild() ||
+      Typedef != T->getDecl()) {
+    Result = getDerived().RebuildTypedefType(Typedef);
+    if (Result.isNull())
+      return QualType();
+  }
+
+  TypedefTypeLoc NewTL = TLB.push<TypedefTypeLoc>(Result);
+  NewTL.setNameLoc(TL.getNameLoc());
+
+  return Result;
+}
+
+template<typename Derived>
+QualType TreeTransform<Derived>::TransformTypeOfExprType(TypeLocBuilder &TLB,
+                                                      TypeOfExprTypeLoc TL) {
+  // typeof expressions are not potentially evaluated contexts
+  EnterExpressionEvaluationContext Unevaluated(SemaRef, Sema::Unevaluated);
+
+  ExprResult E = getDerived().TransformExpr(TL.getUnderlyingExpr());
+  if (E.isInvalid())
+    return QualType();
+
+  E = SemaRef.HandleExprEvaluationContextForTypeof(E.get());
+  if (E.isInvalid())
+    return QualType();
+
+  QualType Result = TL.getType();
+  if (getDerived().AlwaysRebuild() ||
+      E.get() != TL.getUnderlyingExpr()) {
+    Result = getDerived().RebuildTypeOfExprType(E.get(), TL.getTypeofLoc());
+    if (Result.isNull())
+      return QualType();
+  }
+  else E.take();
+
+  TypeOfExprTypeLoc NewTL = TLB.push<TypeOfExprTypeLoc>(Result);
+  NewTL.setTypeofLoc(TL.getTypeofLoc());
+  NewTL.setLParenLoc(TL.getLParenLoc());
+  NewTL.setRParenLoc(TL.getRParenLoc());
+
+  return Result;
+}
+
+template<typename Derived>
+QualType TreeTransform<Derived>::TransformTypeOfType(TypeLocBuilder &TLB,
+                                                     TypeOfTypeLoc TL) {
+  TypeSourceInfo* Old_Under_TI = TL.getUnderlyingTInfo();
+  TypeSourceInfo* New_Under_TI = getDerived().TransformType(Old_Under_TI);
+  if (!New_Under_TI)
+    return QualType();
+
+  QualType Result = TL.getType();
+  if (getDerived().AlwaysRebuild() || New_Under_TI != Old_Under_TI) {
+    Result = getDerived().RebuildTypeOfType(New_Under_TI->getType());
+    if (Result.isNull())
+      return QualType();
+  }
+
+  TypeOfTypeLoc NewTL = TLB.push<TypeOfTypeLoc>(Result);
+  NewTL.setTypeofLoc(TL.getTypeofLoc());
+  NewTL.setLParenLoc(TL.getLParenLoc());
+  NewTL.setRParenLoc(TL.getRParenLoc());
+  NewTL.setUnderlyingTInfo(New_Under_TI);
+
+  return Result;
+}
+
+template<typename Derived>
+QualType TreeTransform<Derived>::TransformDecltypeType(TypeLocBuilder &TLB,
+                                                       DecltypeTypeLoc TL) {
+  const DecltypeType *T = TL.getTypePtr();
+
+  // decltype expressions are not potentially evaluated contexts
+  EnterExpressionEvaluationContext Unevaluated(SemaRef, Sema::Unevaluated, 0,
+                                               /*IsDecltype=*/ true);
+
+  ExprResult E = getDerived().TransformExpr(T->getUnderlyingExpr());
+  if (E.isInvalid())
+    return QualType();
+
+  E = getSema().ActOnDecltypeExpression(E.take());
+  if (E.isInvalid())
+    return QualType();
+
+  QualType Result = TL.getType();
+  if (getDerived().AlwaysRebuild() ||
+      E.get() != T->getUnderlyingExpr()) {
+    Result = getDerived().RebuildDecltypeType(E.get(), TL.getNameLoc());
+    if (Result.isNull())
+      return QualType();
+  }
+  else E.take();
+
+  DecltypeTypeLoc NewTL = TLB.push<DecltypeTypeLoc>(Result);
+  NewTL.setNameLoc(TL.getNameLoc());
+
+  return Result;
+}
+
+template<typename Derived>
+QualType TreeTransform<Derived>::TransformUnaryTransformType(
+                                                            TypeLocBuilder &TLB,
+                                                     UnaryTransformTypeLoc TL) {
+  QualType Result = TL.getType();
+  if (Result->isDependentType()) {
+    const UnaryTransformType *T = TL.getTypePtr();
+    QualType NewBase =
+      getDerived().TransformType(TL.getUnderlyingTInfo())->getType();
+    Result = getDerived().RebuildUnaryTransformType(NewBase,
+                                                    T->getUTTKind(),
+                                                    TL.getKWLoc());
+    if (Result.isNull())
+      return QualType();
+  }
+
+  UnaryTransformTypeLoc NewTL = TLB.push<UnaryTransformTypeLoc>(Result);
+  NewTL.setKWLoc(TL.getKWLoc());
+  NewTL.setParensRange(TL.getParensRange());
+  NewTL.setUnderlyingTInfo(TL.getUnderlyingTInfo());
+  return Result;
+}
+
+template<typename Derived>
+QualType TreeTransform<Derived>::TransformAutoType(TypeLocBuilder &TLB,
+                                                   AutoTypeLoc TL) {
+  const AutoType *T = TL.getTypePtr();
+  QualType OldDeduced = T->getDeducedType();
+  QualType NewDeduced;
+  if (!OldDeduced.isNull()) {
+    NewDeduced = getDerived().TransformType(OldDeduced);
+    if (NewDeduced.isNull())
+      return QualType();
+  }
+
+  QualType Result = TL.getType();
+  if (getDerived().AlwaysRebuild() || NewDeduced != OldDeduced) {
+    Result = getDerived().RebuildAutoType(NewDeduced);
+    if (Result.isNull())
+      return QualType();
+  }
+
+  AutoTypeLoc NewTL = TLB.push<AutoTypeLoc>(Result);
+  NewTL.setNameLoc(TL.getNameLoc());
+
+  return Result;
+}
+
+template<typename Derived>
+QualType TreeTransform<Derived>::TransformRecordType(TypeLocBuilder &TLB,
+                                                     RecordTypeLoc TL) {
+  const RecordType *T = TL.getTypePtr();
+  RecordDecl *Record
+    = cast_or_null<RecordDecl>(getDerived().TransformDecl(TL.getNameLoc(),
+                                                          T->getDecl()));
+  if (!Record)
+    return QualType();
+
+  QualType Result = TL.getType();
+  if (getDerived().AlwaysRebuild() ||
+      Record != T->getDecl()) {
+    Result = getDerived().RebuildRecordType(Record);
+    if (Result.isNull())
+      return QualType();
+  }
+
+  RecordTypeLoc NewTL = TLB.push<RecordTypeLoc>(Result);
+  NewTL.setNameLoc(TL.getNameLoc());
+
+  return Result;
+}
+
+template<typename Derived>
+QualType TreeTransform<Derived>::TransformEnumType(TypeLocBuilder &TLB,
+                                                   EnumTypeLoc TL) {
+  const EnumType *T = TL.getTypePtr();
+  EnumDecl *Enum
+    = cast_or_null<EnumDecl>(getDerived().TransformDecl(TL.getNameLoc(),
+                                                        T->getDecl()));
+  if (!Enum)
+    return QualType();
+
+  QualType Result = TL.getType();
+  if (getDerived().AlwaysRebuild() ||
+      Enum != T->getDecl()) {
+    Result = getDerived().RebuildEnumType(Enum);
+    if (Result.isNull())
+      return QualType();
+  }
+
+  EnumTypeLoc NewTL = TLB.push<EnumTypeLoc>(Result);
+  NewTL.setNameLoc(TL.getNameLoc());
+
+  return Result;
+}
+
+template<typename Derived>
+QualType TreeTransform<Derived>::TransformInjectedClassNameType(
+                                         TypeLocBuilder &TLB,
+                                         InjectedClassNameTypeLoc TL) {
+  Decl *D = getDerived().TransformDecl(TL.getNameLoc(),
+                                       TL.getTypePtr()->getDecl());
+  if (!D) return QualType();
+
+  QualType T = SemaRef.Context.getTypeDeclType(cast<TypeDecl>(D));
+  TLB.pushTypeSpec(T).setNameLoc(TL.getNameLoc());
+  return T;
+}
+
+template<typename Derived>
+QualType TreeTransform<Derived>::TransformTemplateTypeParmType(
+                                                TypeLocBuilder &TLB,
+                                                TemplateTypeParmTypeLoc TL) {
+  return TransformTypeSpecType(TLB, TL);
+}
+
+template<typename Derived>
+QualType TreeTransform<Derived>::TransformSubstTemplateTypeParmType(
+                                         TypeLocBuilder &TLB,
+                                         SubstTemplateTypeParmTypeLoc TL) {
+  const SubstTemplateTypeParmType *T = TL.getTypePtr();
+  
+  // Substitute into the replacement type, which itself might involve something
+  // that needs to be transformed. This only tends to occur with default
+  // template arguments of template template parameters.
+  TemporaryBase Rebase(*this, TL.getNameLoc(), DeclarationName());
+  QualType Replacement = getDerived().TransformType(T->getReplacementType());
+  if (Replacement.isNull())
+    return QualType();
+  
+  // Always canonicalize the replacement type.
+  Replacement = SemaRef.Context.getCanonicalType(Replacement);
+  QualType Result
+    = SemaRef.Context.getSubstTemplateTypeParmType(T->getReplacedParameter(), 
+                                                   Replacement);
+  
+  // Propagate type-source information.
+  SubstTemplateTypeParmTypeLoc NewTL
+    = TLB.push<SubstTemplateTypeParmTypeLoc>(Result);
+  NewTL.setNameLoc(TL.getNameLoc());
+  return Result;
+
+}
+
+template<typename Derived>
+QualType TreeTransform<Derived>::TransformSubstTemplateTypeParmPackType(
+                                          TypeLocBuilder &TLB,
+                                          SubstTemplateTypeParmPackTypeLoc TL) {
+  return TransformTypeSpecType(TLB, TL);
+}
+
+template<typename Derived>
+QualType TreeTransform<Derived>::TransformTemplateSpecializationType(
+                                                        TypeLocBuilder &TLB,
+                                           TemplateSpecializationTypeLoc TL) {
+  const TemplateSpecializationType *T = TL.getTypePtr();
+
+  // The nested-name-specifier never matters in a TemplateSpecializationType,
+  // because we can't have a dependent nested-name-specifier anyway.
+  CXXScopeSpec SS;
+  TemplateName Template
+    = getDerived().TransformTemplateName(SS, T->getTemplateName(),
+                                         TL.getTemplateNameLoc());
+  if (Template.isNull())
+    return QualType();
+
+  return getDerived().TransformTemplateSpecializationType(TLB, TL, Template);
+}
+
+template<typename Derived>
+QualType TreeTransform<Derived>::TransformAtomicType(TypeLocBuilder &TLB,
+                                                     AtomicTypeLoc TL) {
+  QualType ValueType = getDerived().TransformType(TLB, TL.getValueLoc());
+  if (ValueType.isNull())
+    return QualType();
+
+  QualType Result = TL.getType();
+  if (getDerived().AlwaysRebuild() ||
+      ValueType != TL.getValueLoc().getType()) {
+    Result = getDerived().RebuildAtomicType(ValueType, TL.getKWLoc());
+    if (Result.isNull())
+      return QualType();
+  }
+
+  AtomicTypeLoc NewTL = TLB.push<AtomicTypeLoc>(Result);
+  NewTL.setKWLoc(TL.getKWLoc());
+  NewTL.setLParenLoc(TL.getLParenLoc());
+  NewTL.setRParenLoc(TL.getRParenLoc());
+
+  return Result;
+}
+
+namespace {
+  /// \brief Simple iterator that traverses the template arguments in a 
+  /// container that provides a \c getArgLoc() member function.
+  ///
+  /// This iterator is intended to be used with the iterator form of
+  /// \c TreeTransform<Derived>::TransformTemplateArguments().
+  template<typename ArgLocContainer>
+  class TemplateArgumentLocContainerIterator {
+    ArgLocContainer *Container;
+    unsigned Index;
+    
+  public:
+    typedef TemplateArgumentLoc value_type;
+    typedef TemplateArgumentLoc reference;
+    typedef int difference_type;
+    typedef std::input_iterator_tag iterator_category;
+    
+    class pointer {
+      TemplateArgumentLoc Arg;
+      
+    public:
+      explicit pointer(TemplateArgumentLoc Arg) : Arg(Arg) { }
+      
+      const TemplateArgumentLoc *operator->() const {
+        return &Arg;
+      }
+    };
+    
+    
+    TemplateArgumentLocContainerIterator() {}
+    
+    TemplateArgumentLocContainerIterator(ArgLocContainer &Container,
+                                 unsigned Index)
+      : Container(&Container), Index(Index) { }
+    
+    TemplateArgumentLocContainerIterator &operator++() {
+      ++Index;
+      return *this;
+    }
+    
+    TemplateArgumentLocContainerIterator operator++(int) {
+      TemplateArgumentLocContainerIterator Old(*this);
+      ++(*this);
+      return Old;
+    }
+    
+    TemplateArgumentLoc operator*() const {
+      return Container->getArgLoc(Index);
+    }
+    
+    pointer operator->() const {
+      return pointer(Container->getArgLoc(Index));
+    }
+    
+    friend bool operator==(const TemplateArgumentLocContainerIterator &X,
+                           const TemplateArgumentLocContainerIterator &Y) {
+      return X.Container == Y.Container && X.Index == Y.Index;
+    }
+    
+    friend bool operator!=(const TemplateArgumentLocContainerIterator &X,
+                           const TemplateArgumentLocContainerIterator &Y) {
+      return !(X == Y);
+    }
+  };
+}
+  
+  
+template <typename Derived>
+QualType TreeTransform<Derived>::TransformTemplateSpecializationType(
+                                                        TypeLocBuilder &TLB,
+                                           TemplateSpecializationTypeLoc TL,
+                                                      TemplateName Template) {
+  TemplateArgumentListInfo NewTemplateArgs;
+  NewTemplateArgs.setLAngleLoc(TL.getLAngleLoc());
+  NewTemplateArgs.setRAngleLoc(TL.getRAngleLoc());
+  typedef TemplateArgumentLocContainerIterator<TemplateSpecializationTypeLoc>
+    ArgIterator;
+  if (getDerived().TransformTemplateArguments(ArgIterator(TL, 0), 
+                                              ArgIterator(TL, TL.getNumArgs()),
+                                              NewTemplateArgs))
+    return QualType();
+
+  // FIXME: maybe don't rebuild if all the template arguments are the same.
+
+  QualType Result =
+    getDerived().RebuildTemplateSpecializationType(Template,
+                                                   TL.getTemplateNameLoc(),
+                                                   NewTemplateArgs);
+
+  if (!Result.isNull()) {
+    // Specializations of template template parameters are represented as
+    // TemplateSpecializationTypes, and substitution of type alias templates
+    // within a dependent context can transform them into
+    // DependentTemplateSpecializationTypes.
+    if (isa<DependentTemplateSpecializationType>(Result)) {
+      DependentTemplateSpecializationTypeLoc NewTL
+        = TLB.push<DependentTemplateSpecializationTypeLoc>(Result);
+      NewTL.setElaboratedKeywordLoc(SourceLocation());
+      NewTL.setQualifierLoc(NestedNameSpecifierLoc());
+      NewTL.setTemplateKeywordLoc(TL.getTemplateKeywordLoc());
+      NewTL.setTemplateNameLoc(TL.getTemplateNameLoc());
+      NewTL.setLAngleLoc(TL.getLAngleLoc());
+      NewTL.setRAngleLoc(TL.getRAngleLoc());
+      for (unsigned i = 0, e = NewTemplateArgs.size(); i != e; ++i)
+        NewTL.setArgLocInfo(i, NewTemplateArgs[i].getLocInfo());
+      return Result;
+    }
+
+    TemplateSpecializationTypeLoc NewTL
+      = TLB.push<TemplateSpecializationTypeLoc>(Result);
+    NewTL.setTemplateKeywordLoc(TL.getTemplateKeywordLoc());
+    NewTL.setTemplateNameLoc(TL.getTemplateNameLoc());
+    NewTL.setLAngleLoc(TL.getLAngleLoc());
+    NewTL.setRAngleLoc(TL.getRAngleLoc());
+    for (unsigned i = 0, e = NewTemplateArgs.size(); i != e; ++i)
+      NewTL.setArgLocInfo(i, NewTemplateArgs[i].getLocInfo());
+  }
+
+  return Result;
+}
+
+template <typename Derived>
+QualType TreeTransform<Derived>::TransformDependentTemplateSpecializationType(
+                                     TypeLocBuilder &TLB,
+                                     DependentTemplateSpecializationTypeLoc TL,
+                                     TemplateName Template,
+                                     CXXScopeSpec &SS) {
+  TemplateArgumentListInfo NewTemplateArgs;
+  NewTemplateArgs.setLAngleLoc(TL.getLAngleLoc());
+  NewTemplateArgs.setRAngleLoc(TL.getRAngleLoc());
+  typedef TemplateArgumentLocContainerIterator<
+            DependentTemplateSpecializationTypeLoc> ArgIterator;
+  if (getDerived().TransformTemplateArguments(ArgIterator(TL, 0), 
+                                              ArgIterator(TL, TL.getNumArgs()),
+                                              NewTemplateArgs))
+    return QualType();
+  
+  // FIXME: maybe don't rebuild if all the template arguments are the same.
+  
+  if (DependentTemplateName *DTN = Template.getAsDependentTemplateName()) {
+    QualType Result
+      = getSema().Context.getDependentTemplateSpecializationType(
+                                                TL.getTypePtr()->getKeyword(),
+                                                         DTN->getQualifier(),
+                                                         DTN->getIdentifier(),
+                                                               NewTemplateArgs);
+   
+    DependentTemplateSpecializationTypeLoc NewTL
+      = TLB.push<DependentTemplateSpecializationTypeLoc>(Result);
+    NewTL.setElaboratedKeywordLoc(TL.getElaboratedKeywordLoc());
+    NewTL.setQualifierLoc(SS.getWithLocInContext(SemaRef.Context));
+    NewTL.setTemplateKeywordLoc(TL.getTemplateKeywordLoc());
+    NewTL.setTemplateNameLoc(TL.getTemplateNameLoc());
+    NewTL.setLAngleLoc(TL.getLAngleLoc());
+    NewTL.setRAngleLoc(TL.getRAngleLoc());
+    for (unsigned i = 0, e = NewTemplateArgs.size(); i != e; ++i)
+      NewTL.setArgLocInfo(i, NewTemplateArgs[i].getLocInfo());
+    return Result;
+  }
+      
+  QualType Result 
+    = getDerived().RebuildTemplateSpecializationType(Template,
+                                                     TL.getTemplateNameLoc(),
+                                                     NewTemplateArgs);
+  
+  if (!Result.isNull()) {
+    /// FIXME: Wrap this in an elaborated-type-specifier?
+    TemplateSpecializationTypeLoc NewTL
+      = TLB.push<TemplateSpecializationTypeLoc>(Result);
+    NewTL.setTemplateKeywordLoc(TL.getTemplateKeywordLoc());
+    NewTL.setTemplateNameLoc(TL.getTemplateNameLoc());
+    NewTL.setLAngleLoc(TL.getLAngleLoc());
+    NewTL.setRAngleLoc(TL.getRAngleLoc());
+    for (unsigned i = 0, e = NewTemplateArgs.size(); i != e; ++i)
+      NewTL.setArgLocInfo(i, NewTemplateArgs[i].getLocInfo());
+  }
+  
+  return Result;
+}
+
+template<typename Derived>
+QualType
+TreeTransform<Derived>::TransformElaboratedType(TypeLocBuilder &TLB,
+                                                ElaboratedTypeLoc TL) {
+  const ElaboratedType *T = TL.getTypePtr();
+
+  NestedNameSpecifierLoc QualifierLoc;
+  // NOTE: the qualifier in an ElaboratedType is optional.
+  if (TL.getQualifierLoc()) {
+    QualifierLoc 
+      = getDerived().TransformNestedNameSpecifierLoc(TL.getQualifierLoc());
+    if (!QualifierLoc)
+      return QualType();
+  }
+
+  QualType NamedT = getDerived().TransformType(TLB, TL.getNamedTypeLoc());
+  if (NamedT.isNull())
+    return QualType();
+
+  // C++0x [dcl.type.elab]p2:
+  //   If the identifier resolves to a typedef-name or the simple-template-id
+  //   resolves to an alias template specialization, the
+  //   elaborated-type-specifier is ill-formed.
+  if (T->getKeyword() != ETK_None && T->getKeyword() != ETK_Typename) {
+    if (const TemplateSpecializationType *TST =
+          NamedT->getAs<TemplateSpecializationType>()) {
+      TemplateName Template = TST->getTemplateName();
+      if (TypeAliasTemplateDecl *TAT =
+          dyn_cast_or_null<TypeAliasTemplateDecl>(Template.getAsTemplateDecl())) {
+        SemaRef.Diag(TL.getNamedTypeLoc().getBeginLoc(),
+                     diag::err_tag_reference_non_tag) << 4;
+        SemaRef.Diag(TAT->getLocation(), diag::note_declared_at);
+      }
+    }
+  }
+
+  QualType Result = TL.getType();
+  if (getDerived().AlwaysRebuild() ||
+      QualifierLoc != TL.getQualifierLoc() ||
+      NamedT != T->getNamedType()) {
+    Result = getDerived().RebuildElaboratedType(TL.getElaboratedKeywordLoc(),
+                                                T->getKeyword(), 
+                                                QualifierLoc, NamedT);
+    if (Result.isNull())
+      return QualType();
+  }
+
+  ElaboratedTypeLoc NewTL = TLB.push<ElaboratedTypeLoc>(Result);
+  NewTL.setElaboratedKeywordLoc(TL.getElaboratedKeywordLoc());
+  NewTL.setQualifierLoc(QualifierLoc);
+  return Result;
+}
+
+template<typename Derived>
+QualType TreeTransform<Derived>::TransformAttributedType(
+                                                TypeLocBuilder &TLB,
+                                                AttributedTypeLoc TL) {
+  const AttributedType *oldType = TL.getTypePtr();
+  QualType modifiedType = getDerived().TransformType(TLB, TL.getModifiedLoc());
+  if (modifiedType.isNull())
+    return QualType();
+
+  QualType result = TL.getType();
+
+  // FIXME: dependent operand expressions?
+  if (getDerived().AlwaysRebuild() ||
+      modifiedType != oldType->getModifiedType()) {
+    // TODO: this is really lame; we should really be rebuilding the
+    // equivalent type from first principles.
+    QualType equivalentType
+      = getDerived().TransformType(oldType->getEquivalentType());
+    if (equivalentType.isNull())
+      return QualType();
+    result = SemaRef.Context.getAttributedType(oldType->getAttrKind(),
+                                               modifiedType,
+                                               equivalentType);
+  }
+
+  AttributedTypeLoc newTL = TLB.push<AttributedTypeLoc>(result);
+  newTL.setAttrNameLoc(TL.getAttrNameLoc());
+  if (TL.hasAttrOperand())
+    newTL.setAttrOperandParensRange(TL.getAttrOperandParensRange());
+  if (TL.hasAttrExprOperand())
+    newTL.setAttrExprOperand(TL.getAttrExprOperand());
+  else if (TL.hasAttrEnumOperand())
+    newTL.setAttrEnumOperandLoc(TL.getAttrEnumOperandLoc());
+
+  return result;
+}
+
+template<typename Derived>
+QualType
+TreeTransform<Derived>::TransformParenType(TypeLocBuilder &TLB,
+                                           ParenTypeLoc TL) {
+  QualType Inner = getDerived().TransformType(TLB, TL.getInnerLoc());
+  if (Inner.isNull())
+    return QualType();
+
+  QualType Result = TL.getType();
+  if (getDerived().AlwaysRebuild() ||
+      Inner != TL.getInnerLoc().getType()) {
+    Result = getDerived().RebuildParenType(Inner);
+    if (Result.isNull())
+      return QualType();
+  }
+
+  ParenTypeLoc NewTL = TLB.push<ParenTypeLoc>(Result);
+  NewTL.setLParenLoc(TL.getLParenLoc());
+  NewTL.setRParenLoc(TL.getRParenLoc());
+  return Result;
+}
+
+template<typename Derived>
+QualType TreeTransform<Derived>::TransformDependentNameType(TypeLocBuilder &TLB,
+                                                      DependentNameTypeLoc TL) {
+  const DependentNameType *T = TL.getTypePtr();
+
+  NestedNameSpecifierLoc QualifierLoc
+    = getDerived().TransformNestedNameSpecifierLoc(TL.getQualifierLoc());
+  if (!QualifierLoc)
+    return QualType();
+
+  QualType Result
+    = getDerived().RebuildDependentNameType(T->getKeyword(),
+                                            TL.getElaboratedKeywordLoc(),
+                                            QualifierLoc,
+                                            T->getIdentifier(),
+                                            TL.getNameLoc());
+  if (Result.isNull())
+    return QualType();
+
+  if (const ElaboratedType* ElabT = Result->getAs<ElaboratedType>()) {
+    QualType NamedT = ElabT->getNamedType();
+    TLB.pushTypeSpec(NamedT).setNameLoc(TL.getNameLoc());
+
+    ElaboratedTypeLoc NewTL = TLB.push<ElaboratedTypeLoc>(Result);
+    NewTL.setElaboratedKeywordLoc(TL.getElaboratedKeywordLoc());
+    NewTL.setQualifierLoc(QualifierLoc);
+  } else {
+    DependentNameTypeLoc NewTL = TLB.push<DependentNameTypeLoc>(Result);
+    NewTL.setElaboratedKeywordLoc(TL.getElaboratedKeywordLoc());
+    NewTL.setQualifierLoc(QualifierLoc);
+    NewTL.setNameLoc(TL.getNameLoc());
+  }
+  return Result;
+}
+
+template<typename Derived>
+QualType TreeTransform<Derived>::
+          TransformDependentTemplateSpecializationType(TypeLocBuilder &TLB,
+                                 DependentTemplateSpecializationTypeLoc TL) {
+  NestedNameSpecifierLoc QualifierLoc;
+  if (TL.getQualifierLoc()) {
+    QualifierLoc
+      = getDerived().TransformNestedNameSpecifierLoc(TL.getQualifierLoc());
+    if (!QualifierLoc)
+      return QualType();
+  }
+            
+  return getDerived()
+           .TransformDependentTemplateSpecializationType(TLB, TL, QualifierLoc);
+}
+
+template<typename Derived>
+QualType TreeTransform<Derived>::
+TransformDependentTemplateSpecializationType(TypeLocBuilder &TLB,
+                                   DependentTemplateSpecializationTypeLoc TL,
+                                       NestedNameSpecifierLoc QualifierLoc) {
+  const DependentTemplateSpecializationType *T = TL.getTypePtr();
+  
+  TemplateArgumentListInfo NewTemplateArgs;
+  NewTemplateArgs.setLAngleLoc(TL.getLAngleLoc());
+  NewTemplateArgs.setRAngleLoc(TL.getRAngleLoc());
+  
+  typedef TemplateArgumentLocContainerIterator<
+  DependentTemplateSpecializationTypeLoc> ArgIterator;
+  if (getDerived().TransformTemplateArguments(ArgIterator(TL, 0),
+                                              ArgIterator(TL, TL.getNumArgs()),
+                                              NewTemplateArgs))
+    return QualType();
+  
+  QualType Result
+    = getDerived().RebuildDependentTemplateSpecializationType(T->getKeyword(),
+                                                              QualifierLoc,
+                                                            T->getIdentifier(),
+                                                       TL.getTemplateNameLoc(),
+                                                            NewTemplateArgs);
+  if (Result.isNull())
+    return QualType();
+  
+  if (const ElaboratedType *ElabT = dyn_cast<ElaboratedType>(Result)) {
+    QualType NamedT = ElabT->getNamedType();
+    
+    // Copy information relevant to the template specialization.
+    TemplateSpecializationTypeLoc NamedTL
+      = TLB.push<TemplateSpecializationTypeLoc>(NamedT);
+    NamedTL.setTemplateKeywordLoc(TL.getTemplateKeywordLoc());
+    NamedTL.setTemplateNameLoc(TL.getTemplateNameLoc());
+    NamedTL.setLAngleLoc(TL.getLAngleLoc());
+    NamedTL.setRAngleLoc(TL.getRAngleLoc());
+    for (unsigned I = 0, E = NewTemplateArgs.size(); I != E; ++I)
+      NamedTL.setArgLocInfo(I, NewTemplateArgs[I].getLocInfo());
+    
+    // Copy information relevant to the elaborated type.
+    ElaboratedTypeLoc NewTL = TLB.push<ElaboratedTypeLoc>(Result);
+    NewTL.setElaboratedKeywordLoc(TL.getElaboratedKeywordLoc());
+    NewTL.setQualifierLoc(QualifierLoc);
+  } else if (isa<DependentTemplateSpecializationType>(Result)) {
+    DependentTemplateSpecializationTypeLoc SpecTL
+      = TLB.push<DependentTemplateSpecializationTypeLoc>(Result);
+    SpecTL.setElaboratedKeywordLoc(TL.getElaboratedKeywordLoc());
+    SpecTL.setQualifierLoc(QualifierLoc);
+    SpecTL.setTemplateKeywordLoc(TL.getTemplateKeywordLoc());
+    SpecTL.setTemplateNameLoc(TL.getTemplateNameLoc());
+    SpecTL.setLAngleLoc(TL.getLAngleLoc());
+    SpecTL.setRAngleLoc(TL.getRAngleLoc());
+    for (unsigned I = 0, E = NewTemplateArgs.size(); I != E; ++I)
+      SpecTL.setArgLocInfo(I, NewTemplateArgs[I].getLocInfo());
+  } else {
+    TemplateSpecializationTypeLoc SpecTL
+      = TLB.push<TemplateSpecializationTypeLoc>(Result);
+    SpecTL.setTemplateKeywordLoc(TL.getTemplateKeywordLoc());
+    SpecTL.setTemplateNameLoc(TL.getTemplateNameLoc());
+    SpecTL.setLAngleLoc(TL.getLAngleLoc());
+    SpecTL.setRAngleLoc(TL.getRAngleLoc());
+    for (unsigned I = 0, E = NewTemplateArgs.size(); I != E; ++I)
+      SpecTL.setArgLocInfo(I, NewTemplateArgs[I].getLocInfo());
+  }
+  return Result;
+}
+
+template<typename Derived>
+QualType TreeTransform<Derived>::TransformPackExpansionType(TypeLocBuilder &TLB,
+                                                      PackExpansionTypeLoc TL) {
+  QualType Pattern                                      
+    = getDerived().TransformType(TLB, TL.getPatternLoc());  
+  if (Pattern.isNull())
+    return QualType();
+  
+  QualType Result = TL.getType();  
+  if (getDerived().AlwaysRebuild() ||
+      Pattern != TL.getPatternLoc().getType()) {
+    Result = getDerived().RebuildPackExpansionType(Pattern, 
+                                           TL.getPatternLoc().getSourceRange(),
+                                                   TL.getEllipsisLoc(),
+                                           TL.getTypePtr()->getNumExpansions());
+    if (Result.isNull())
+      return QualType();
+  }
+  
+  PackExpansionTypeLoc NewT = TLB.push<PackExpansionTypeLoc>(Result);
+  NewT.setEllipsisLoc(TL.getEllipsisLoc());
+  return Result;
+}
+
+template<typename Derived>
+QualType
+TreeTransform<Derived>::TransformObjCInterfaceType(TypeLocBuilder &TLB,
+                                                   ObjCInterfaceTypeLoc TL) {
+  // ObjCInterfaceType is never dependent.
+  TLB.pushFullCopy(TL);
+  return TL.getType();
+}
+
+template<typename Derived>
+QualType
+TreeTransform<Derived>::TransformObjCObjectType(TypeLocBuilder &TLB,
+                                                ObjCObjectTypeLoc TL) {
+  // ObjCObjectType is never dependent.
+  TLB.pushFullCopy(TL);
+  return TL.getType();
+}
+
+template<typename Derived>
+QualType
+TreeTransform<Derived>::TransformObjCObjectPointerType(TypeLocBuilder &TLB,
+                                               ObjCObjectPointerTypeLoc TL) {
+  // ObjCObjectPointerType is never dependent.
+  TLB.pushFullCopy(TL);
+  return TL.getType();
+}
+
+//===----------------------------------------------------------------------===//
+// Statement transformation
+//===----------------------------------------------------------------------===//
+template<typename Derived>
+StmtResult
+TreeTransform<Derived>::TransformNullStmt(NullStmt *S) {
+  return SemaRef.Owned(S);
+}
+
+template<typename Derived>
+StmtResult
+TreeTransform<Derived>::TransformCompoundStmt(CompoundStmt *S) {
+  return getDerived().TransformCompoundStmt(S, false);
+}
+
+template<typename Derived>
+StmtResult
+TreeTransform<Derived>::TransformCompoundStmt(CompoundStmt *S,
+                                              bool IsStmtExpr) {
+  Sema::CompoundScopeRAII CompoundScope(getSema());
+
+  bool SubStmtInvalid = false;
+  bool SubStmtChanged = false;
+  ASTOwningVector<Stmt*> Statements(getSema());
+  for (CompoundStmt::body_iterator B = S->body_begin(), BEnd = S->body_end();
+       B != BEnd; ++B) {
+    StmtResult Result = getDerived().TransformStmt(*B);
+    if (Result.isInvalid()) {
+      // Immediately fail if this was a DeclStmt, since it's very
+      // likely that this will cause problems for future statements.
+      if (isa<DeclStmt>(*B))
+        return StmtError();
+
+      // Otherwise, just keep processing substatements and fail later.
+      SubStmtInvalid = true;
+      continue;
+    }
+
+    SubStmtChanged = SubStmtChanged || Result.get() != *B;
+    Statements.push_back(Result.takeAs<Stmt>());
+  }
+
+  if (SubStmtInvalid)
+    return StmtError();
+
+  if (!getDerived().AlwaysRebuild() &&
+      !SubStmtChanged)
+    return SemaRef.Owned(S);
+
+  return getDerived().RebuildCompoundStmt(S->getLBracLoc(),
+                                          move_arg(Statements),
+                                          S->getRBracLoc(),
+                                          IsStmtExpr);
+}
+
+template<typename Derived>
+StmtResult
+TreeTransform<Derived>::TransformCaseStmt(CaseStmt *S) {
+  ExprResult LHS, RHS;
+  {
+    EnterExpressionEvaluationContext Unevaluated(SemaRef,
+                                                 Sema::ConstantEvaluated);
+
+    // Transform the left-hand case value.
+    LHS = getDerived().TransformExpr(S->getLHS());
+    LHS = SemaRef.ActOnConstantExpression(LHS);
+    if (LHS.isInvalid())
+      return StmtError();
+
+    // Transform the right-hand case value (for the GNU case-range extension).
+    RHS = getDerived().TransformExpr(S->getRHS());
+    RHS = SemaRef.ActOnConstantExpression(RHS);
+    if (RHS.isInvalid())
+      return StmtError();
+  }
+
+  // Build the case statement.
+  // Case statements are always rebuilt so that they will attached to their
+  // transformed switch statement.
+  StmtResult Case = getDerived().RebuildCaseStmt(S->getCaseLoc(),
+                                                       LHS.get(),
+                                                       S->getEllipsisLoc(),
+                                                       RHS.get(),
+                                                       S->getColonLoc());
+  if (Case.isInvalid())
+    return StmtError();
+
+  // Transform the statement following the case
+  StmtResult SubStmt = getDerived().TransformStmt(S->getSubStmt());
+  if (SubStmt.isInvalid())
+    return StmtError();
+
+  // Attach the body to the case statement
+  return getDerived().RebuildCaseStmtBody(Case.get(), SubStmt.get());
+}
+
+template<typename Derived>
+StmtResult
+TreeTransform<Derived>::TransformDefaultStmt(DefaultStmt *S) {
+  // Transform the statement following the default case
+  StmtResult SubStmt = getDerived().TransformStmt(S->getSubStmt());
+  if (SubStmt.isInvalid())
+    return StmtError();
+
+  // Default statements are always rebuilt
+  return getDerived().RebuildDefaultStmt(S->getDefaultLoc(), S->getColonLoc(),
+                                         SubStmt.get());
+}
+
+template<typename Derived>
+StmtResult
+TreeTransform<Derived>::TransformLabelStmt(LabelStmt *S) {
+  StmtResult SubStmt = getDerived().TransformStmt(S->getSubStmt());
+  if (SubStmt.isInvalid())
+    return StmtError();
+
+  Decl *LD = getDerived().TransformDecl(S->getDecl()->getLocation(),
+                                        S->getDecl());
+  if (!LD)
+    return StmtError();
+
+
+  // FIXME: Pass the real colon location in.
+  return getDerived().RebuildLabelStmt(S->getIdentLoc(),
+                                       cast<LabelDecl>(LD), SourceLocation(),
+                                       SubStmt.get());
+}
+
+template<typename Derived>
+StmtResult
+TreeTransform<Derived>::TransformAttributedStmt(AttributedStmt *S) {
+  StmtResult SubStmt = getDerived().TransformStmt(S->getSubStmt());
+  if (SubStmt.isInvalid())
+    return StmtError();
+
+  // TODO: transform attributes
+  if (SubStmt.get() == S->getSubStmt() /* && attrs are the same */)
+    return S;
+
+  return getDerived().RebuildAttributedStmt(S->getAttrLoc(),
+                                            S->getAttrs(),
+                                            SubStmt.get());
+}
+
+template<typename Derived>
+StmtResult
+TreeTransform<Derived>::TransformIfStmt(IfStmt *S) {
+  // Transform the condition
+  ExprResult Cond;
+  VarDecl *ConditionVar = 0;
+  if (S->getConditionVariable()) {
+    ConditionVar 
+      = cast_or_null<VarDecl>(
+                   getDerived().TransformDefinition(
+                                      S->getConditionVariable()->getLocation(),
+                                                    S->getConditionVariable()));
+    if (!ConditionVar)
+      return StmtError();
+  } else {
+    Cond = getDerived().TransformExpr(S->getCond());
+  
+    if (Cond.isInvalid())
+      return StmtError();
+    
+    // Convert the condition to a boolean value.
+    if (S->getCond()) {
+      ExprResult CondE = getSema().ActOnBooleanCondition(0, S->getIfLoc(), 
+                                                         Cond.get());
+      if (CondE.isInvalid())
+        return StmtError();
+    
+      Cond = CondE.get();
+    }
+  }
+  
+  Sema::FullExprArg FullCond(getSema().MakeFullExpr(Cond.take()));
+  if (!S->getConditionVariable() && S->getCond() && !FullCond.get())
+    return StmtError();
+  
+  // Transform the "then" branch.
+  StmtResult Then = getDerived().TransformStmt(S->getThen());
+  if (Then.isInvalid())
+    return StmtError();
+
+  // Transform the "else" branch.
+  StmtResult Else = getDerived().TransformStmt(S->getElse());
+  if (Else.isInvalid())
+    return StmtError();
+
+  if (!getDerived().AlwaysRebuild() &&
+      FullCond.get() == S->getCond() &&
+      ConditionVar == S->getConditionVariable() &&
+      Then.get() == S->getThen() &&
+      Else.get() == S->getElse())
+    return SemaRef.Owned(S);
+
+  return getDerived().RebuildIfStmt(S->getIfLoc(), FullCond, ConditionVar,
+                                    Then.get(),
+                                    S->getElseLoc(), Else.get());
+}
+
+template<typename Derived>
+StmtResult
+TreeTransform<Derived>::TransformSwitchStmt(SwitchStmt *S) {
+  // Transform the condition.
+  ExprResult Cond;
+  VarDecl *ConditionVar = 0;
+  if (S->getConditionVariable()) {
+    ConditionVar 
+      = cast_or_null<VarDecl>(
+                   getDerived().TransformDefinition(
+                                      S->getConditionVariable()->getLocation(),
+                                                    S->getConditionVariable()));
+    if (!ConditionVar)
+      return StmtError();
+  } else {
+    Cond = getDerived().TransformExpr(S->getCond());
+    
+    if (Cond.isInvalid())
+      return StmtError();
+  }
+
+  // Rebuild the switch statement.
+  StmtResult Switch
+    = getDerived().RebuildSwitchStmtStart(S->getSwitchLoc(), Cond.get(),
+                                          ConditionVar);
+  if (Switch.isInvalid())
+    return StmtError();
+
+  // Transform the body of the switch statement.
+  StmtResult Body = getDerived().TransformStmt(S->getBody());
+  if (Body.isInvalid())
+    return StmtError();
+
+  // Complete the switch statement.
+  return getDerived().RebuildSwitchStmtBody(S->getSwitchLoc(), Switch.get(),
+                                            Body.get());
+}
+
+template<typename Derived>
+StmtResult
+TreeTransform<Derived>::TransformWhileStmt(WhileStmt *S) {
+  // Transform the condition
+  ExprResult Cond;
+  VarDecl *ConditionVar = 0;
+  if (S->getConditionVariable()) {
+    ConditionVar 
+      = cast_or_null<VarDecl>(
+                   getDerived().TransformDefinition(
+                                      S->getConditionVariable()->getLocation(),
+                                                    S->getConditionVariable()));
+    if (!ConditionVar)
+      return StmtError();
+  } else {
+    Cond = getDerived().TransformExpr(S->getCond());
+    
+    if (Cond.isInvalid())
+      return StmtError();
+
+    if (S->getCond()) {
+      // Convert the condition to a boolean value.
+      ExprResult CondE = getSema().ActOnBooleanCondition(0, S->getWhileLoc(), 
+                                                         Cond.get());
+      if (CondE.isInvalid())
+        return StmtError();
+      Cond = CondE;
+    }
+  }
+
+  Sema::FullExprArg FullCond(getSema().MakeFullExpr(Cond.take()));
+  if (!S->getConditionVariable() && S->getCond() && !FullCond.get())
+    return StmtError();
+
+  // Transform the body
+  StmtResult Body = getDerived().TransformStmt(S->getBody());
+  if (Body.isInvalid())
+    return StmtError();
+
+  if (!getDerived().AlwaysRebuild() &&
+      FullCond.get() == S->getCond() &&
+      ConditionVar == S->getConditionVariable() &&
+      Body.get() == S->getBody())
+    return Owned(S);
+
+  return getDerived().RebuildWhileStmt(S->getWhileLoc(), FullCond,
+                                       ConditionVar, Body.get());
+}
+
+template<typename Derived>
+StmtResult
+TreeTransform<Derived>::TransformDoStmt(DoStmt *S) {
+  // Transform the body
+  StmtResult Body = getDerived().TransformStmt(S->getBody());
+  if (Body.isInvalid())
+    return StmtError();
+
+  // Transform the condition
+  ExprResult Cond = getDerived().TransformExpr(S->getCond());
+  if (Cond.isInvalid())
+    return StmtError();
+  
+  if (!getDerived().AlwaysRebuild() &&
+      Cond.get() == S->getCond() &&
+      Body.get() == S->getBody())
+    return SemaRef.Owned(S);
+
+  return getDerived().RebuildDoStmt(S->getDoLoc(), Body.get(), S->getWhileLoc(),
+                                    /*FIXME:*/S->getWhileLoc(), Cond.get(),
+                                    S->getRParenLoc());
+}
+
+template<typename Derived>
+StmtResult
+TreeTransform<Derived>::TransformForStmt(ForStmt *S) {
+  // Transform the initialization statement
+  StmtResult Init = getDerived().TransformStmt(S->getInit());
+  if (Init.isInvalid())
+    return StmtError();
+
+  // Transform the condition
+  ExprResult Cond;
+  VarDecl *ConditionVar = 0;
+  if (S->getConditionVariable()) {
+    ConditionVar 
+      = cast_or_null<VarDecl>(
+                   getDerived().TransformDefinition(
+                                      S->getConditionVariable()->getLocation(),
+                                                    S->getConditionVariable()));
+    if (!ConditionVar)
+      return StmtError();
+  } else {
+    Cond = getDerived().TransformExpr(S->getCond());
+    
+    if (Cond.isInvalid())
+      return StmtError();
+
+    if (S->getCond()) {
+      // Convert the condition to a boolean value.
+      ExprResult CondE = getSema().ActOnBooleanCondition(0, S->getForLoc(), 
+                                                         Cond.get());
+      if (CondE.isInvalid())
+        return StmtError();
+
+      Cond = CondE.get();
+    }
+  }
+
+  Sema::FullExprArg FullCond(getSema().MakeFullExpr(Cond.take()));  
+  if (!S->getConditionVariable() && S->getCond() && !FullCond.get())
+    return StmtError();
+
+  // Transform the increment
+  ExprResult Inc = getDerived().TransformExpr(S->getInc());
+  if (Inc.isInvalid())
+    return StmtError();
+
+  Sema::FullExprArg FullInc(getSema().MakeFullExpr(Inc.get()));
+  if (S->getInc() && !FullInc.get())
+    return StmtError();
+
+  // Transform the body
+  StmtResult Body = getDerived().TransformStmt(S->getBody());
+  if (Body.isInvalid())
+    return StmtError();
+
+  if (!getDerived().AlwaysRebuild() &&
+      Init.get() == S->getInit() &&
+      FullCond.get() == S->getCond() &&
+      Inc.get() == S->getInc() &&
+      Body.get() == S->getBody())
+    return SemaRef.Owned(S);
+
+  return getDerived().RebuildForStmt(S->getForLoc(), S->getLParenLoc(),
+                                     Init.get(), FullCond, ConditionVar,
+                                     FullInc, S->getRParenLoc(), Body.get());
+}
+
+template<typename Derived>
+StmtResult
+TreeTransform<Derived>::TransformGotoStmt(GotoStmt *S) {
+  Decl *LD = getDerived().TransformDecl(S->getLabel()->getLocation(),
+                                        S->getLabel());
+  if (!LD)
+    return StmtError();
+  
+  // Goto statements must always be rebuilt, to resolve the label.
+  return getDerived().RebuildGotoStmt(S->getGotoLoc(), S->getLabelLoc(),
+                                      cast<LabelDecl>(LD));
+}
+
+template<typename Derived>
+StmtResult
+TreeTransform<Derived>::TransformIndirectGotoStmt(IndirectGotoStmt *S) {
+  ExprResult Target = getDerived().TransformExpr(S->getTarget());
+  if (Target.isInvalid())
+    return StmtError();
+  Target = SemaRef.MaybeCreateExprWithCleanups(Target.take());
+
+  if (!getDerived().AlwaysRebuild() &&
+      Target.get() == S->getTarget())
+    return SemaRef.Owned(S);
+
+  return getDerived().RebuildIndirectGotoStmt(S->getGotoLoc(), S->getStarLoc(),
+                                              Target.get());
+}
+
+template<typename Derived>
+StmtResult
+TreeTransform<Derived>::TransformContinueStmt(ContinueStmt *S) {
+  return SemaRef.Owned(S);
+}
+
+template<typename Derived>
+StmtResult
+TreeTransform<Derived>::TransformBreakStmt(BreakStmt *S) {
+  return SemaRef.Owned(S);
+}
+
+template<typename Derived>
+StmtResult
+TreeTransform<Derived>::TransformReturnStmt(ReturnStmt *S) {
+  ExprResult Result = getDerived().TransformExpr(S->getRetValue());
+  if (Result.isInvalid())
+    return StmtError();
+
+  // FIXME: We always rebuild the return statement because there is no way
+  // to tell whether the return type of the function has changed.
+  return getDerived().RebuildReturnStmt(S->getReturnLoc(), Result.get());
+}
+
+template<typename Derived>
+StmtResult
+TreeTransform<Derived>::TransformDeclStmt(DeclStmt *S) {
+  bool DeclChanged = false;
+  SmallVector<Decl *, 4> Decls;
+  for (DeclStmt::decl_iterator D = S->decl_begin(), DEnd = S->decl_end();
+       D != DEnd; ++D) {
+    Decl *Transformed = getDerived().TransformDefinition((*D)->getLocation(),
+                                                         *D);
+    if (!Transformed)
+      return StmtError();
+
+    if (Transformed != *D)
+      DeclChanged = true;
+
+    Decls.push_back(Transformed);
+  }
+
+  if (!getDerived().AlwaysRebuild() && !DeclChanged)
+    return SemaRef.Owned(S);
+
+  return getDerived().RebuildDeclStmt(Decls.data(), Decls.size(),
+                                      S->getStartLoc(), S->getEndLoc());
+}
+
+template<typename Derived>
+StmtResult
+TreeTransform<Derived>::TransformAsmStmt(AsmStmt *S) {
+  
+  ASTOwningVector<Expr*> Constraints(getSema());
+  ASTOwningVector<Expr*> Exprs(getSema());
+  SmallVector<IdentifierInfo *, 4> Names;
+
+  ExprResult AsmString;
+  ASTOwningVector<Expr*> Clobbers(getSema());
+
+  bool ExprsChanged = false;
+  
+  // Go through the outputs.
+  for (unsigned I = 0, E = S->getNumOutputs(); I != E; ++I) {
+    Names.push_back(S->getOutputIdentifier(I));
+    
+    // No need to transform the constraint literal.
+    Constraints.push_back(S->getOutputConstraintLiteral(I));
+    
+    // Transform the output expr.
+    Expr *OutputExpr = S->getOutputExpr(I);
+    ExprResult Result = getDerived().TransformExpr(OutputExpr);
+    if (Result.isInvalid())
+      return StmtError();
+    
+    ExprsChanged |= Result.get() != OutputExpr;
+    
+    Exprs.push_back(Result.get());
+  }
+  
+  // Go through the inputs.
+  for (unsigned I = 0, E = S->getNumInputs(); I != E; ++I) {
+    Names.push_back(S->getInputIdentifier(I));
+    
+    // No need to transform the constraint literal.
+    Constraints.push_back(S->getInputConstraintLiteral(I));
+    
+    // Transform the input expr.
+    Expr *InputExpr = S->getInputExpr(I);
+    ExprResult Result = getDerived().TransformExpr(InputExpr);
+    if (Result.isInvalid())
+      return StmtError();
+    
+    ExprsChanged |= Result.get() != InputExpr;
+    
+    Exprs.push_back(Result.get());
+  }
+  
+  if (!getDerived().AlwaysRebuild() && !ExprsChanged)
+    return SemaRef.Owned(S);
+
+  // Go through the clobbers.
+  for (unsigned I = 0, E = S->getNumClobbers(); I != E; ++I)
+    Clobbers.push_back(S->getClobber(I));
+
+  // No need to transform the asm string literal.
+  AsmString = SemaRef.Owned(S->getAsmString());
+
+  return getDerived().RebuildAsmStmt(S->getAsmLoc(),
+                                     S->isSimple(),
+                                     S->isVolatile(),
+                                     S->getNumOutputs(),
+                                     S->getNumInputs(),
+                                     Names.data(),
+                                     move_arg(Constraints),
+                                     move_arg(Exprs),
+                                     AsmString.get(),
+                                     move_arg(Clobbers),
+                                     S->getRParenLoc(),
+                                     S->isMSAsm());
+}
+
+
+template<typename Derived>
+StmtResult
+TreeTransform<Derived>::TransformObjCAtTryStmt(ObjCAtTryStmt *S) {
+  // Transform the body of the @try.
+  StmtResult TryBody = getDerived().TransformStmt(S->getTryBody());
+  if (TryBody.isInvalid())
+    return StmtError();
+  
+  // Transform the @catch statements (if present).
+  bool AnyCatchChanged = false;
+  ASTOwningVector<Stmt*> CatchStmts(SemaRef);
+  for (unsigned I = 0, N = S->getNumCatchStmts(); I != N; ++I) {
+    StmtResult Catch = getDerived().TransformStmt(S->getCatchStmt(I));
+    if (Catch.isInvalid())
+      return StmtError();
+    if (Catch.get() != S->getCatchStmt(I))
+      AnyCatchChanged = true;
+    CatchStmts.push_back(Catch.release());
+  }
+  
+  // Transform the @finally statement (if present).
+  StmtResult Finally;
+  if (S->getFinallyStmt()) {
+    Finally = getDerived().TransformStmt(S->getFinallyStmt());
+    if (Finally.isInvalid())
+      return StmtError();
+  }
+
+  // If nothing changed, just retain this statement.
+  if (!getDerived().AlwaysRebuild() &&
+      TryBody.get() == S->getTryBody() &&
+      !AnyCatchChanged &&
+      Finally.get() == S->getFinallyStmt())
+    return SemaRef.Owned(S);
+  
+  // Build a new statement.
+  return getDerived().RebuildObjCAtTryStmt(S->getAtTryLoc(), TryBody.get(),
+                                           move_arg(CatchStmts), Finally.get());
+}
+
+template<typename Derived>
+StmtResult
+TreeTransform<Derived>::TransformObjCAtCatchStmt(ObjCAtCatchStmt *S) {
+  // Transform the @catch parameter, if there is one.
+  VarDecl *Var = 0;
+  if (VarDecl *FromVar = S->getCatchParamDecl()) {
+    TypeSourceInfo *TSInfo = 0;
+    if (FromVar->getTypeSourceInfo()) {
+      TSInfo = getDerived().TransformType(FromVar->getTypeSourceInfo());
+      if (!TSInfo)
+        return StmtError();
+    }
+    
+    QualType T;
+    if (TSInfo)
+      T = TSInfo->getType();
+    else {
+      T = getDerived().TransformType(FromVar->getType());
+      if (T.isNull())
+        return StmtError();        
+    }
+    
+    Var = getDerived().RebuildObjCExceptionDecl(FromVar, TSInfo, T);
+    if (!Var)
+      return StmtError();
+  }
+  
+  StmtResult Body = getDerived().TransformStmt(S->getCatchBody());
+  if (Body.isInvalid())
+    return StmtError();
+  
+  return getDerived().RebuildObjCAtCatchStmt(S->getAtCatchLoc(), 
+                                             S->getRParenLoc(),
+                                             Var, Body.get());
+}
+
+template<typename Derived>
+StmtResult
+TreeTransform<Derived>::TransformObjCAtFinallyStmt(ObjCAtFinallyStmt *S) {
+  // Transform the body.
+  StmtResult Body = getDerived().TransformStmt(S->getFinallyBody());
+  if (Body.isInvalid())
+    return StmtError();
+  
+  // If nothing changed, just retain this statement.
+  if (!getDerived().AlwaysRebuild() &&
+      Body.get() == S->getFinallyBody())
+    return SemaRef.Owned(S);
+
+  // Build a new statement.
+  return getDerived().RebuildObjCAtFinallyStmt(S->getAtFinallyLoc(),
+                                               Body.get());
+}
+
+template<typename Derived>
+StmtResult
+TreeTransform<Derived>::TransformObjCAtThrowStmt(ObjCAtThrowStmt *S) {
+  ExprResult Operand;
+  if (S->getThrowExpr()) {
+    Operand = getDerived().TransformExpr(S->getThrowExpr());
+    if (Operand.isInvalid())
+      return StmtError();
+  }
+  
+  if (!getDerived().AlwaysRebuild() &&
+      Operand.get() == S->getThrowExpr())
+    return getSema().Owned(S);
+    
+  return getDerived().RebuildObjCAtThrowStmt(S->getThrowLoc(), Operand.get());
+}
+
+template<typename Derived>
+StmtResult
+TreeTransform<Derived>::TransformObjCAtSynchronizedStmt(
+                                                  ObjCAtSynchronizedStmt *S) {
+  // Transform the object we are locking.
+  ExprResult Object = getDerived().TransformExpr(S->getSynchExpr());
+  if (Object.isInvalid())
+    return StmtError();
+  Object =
+    getDerived().RebuildObjCAtSynchronizedOperand(S->getAtSynchronizedLoc(),
+                                                  Object.get());
+  if (Object.isInvalid())
+    return StmtError();
+  
+  // Transform the body.
+  StmtResult Body = getDerived().TransformStmt(S->getSynchBody());
+  if (Body.isInvalid())
+    return StmtError();
+  
+  // If nothing change, just retain the current statement.
+  if (!getDerived().AlwaysRebuild() &&
+      Object.get() == S->getSynchExpr() &&
+      Body.get() == S->getSynchBody())
+    return SemaRef.Owned(S);
+
+  // Build a new statement.
+  return getDerived().RebuildObjCAtSynchronizedStmt(S->getAtSynchronizedLoc(),
+                                                    Object.get(), Body.get());
+}
+
+template<typename Derived>
+StmtResult
+TreeTransform<Derived>::TransformObjCAutoreleasePoolStmt(
+                                              ObjCAutoreleasePoolStmt *S) {
+  // Transform the body.
+  StmtResult Body = getDerived().TransformStmt(S->getSubStmt());
+  if (Body.isInvalid())
+    return StmtError();
+  
+  // If nothing changed, just retain this statement.
+  if (!getDerived().AlwaysRebuild() &&
+      Body.get() == S->getSubStmt())
+    return SemaRef.Owned(S);
+
+  // Build a new statement.
+  return getDerived().RebuildObjCAutoreleasePoolStmt(
+                        S->getAtLoc(), Body.get());
+}
+
+template<typename Derived>
+StmtResult
+TreeTransform<Derived>::TransformObjCForCollectionStmt(
+                                                  ObjCForCollectionStmt *S) {
+  // Transform the element statement.
+  StmtResult Element = getDerived().TransformStmt(S->getElement());
+  if (Element.isInvalid())
+    return StmtError();
+  
+  // Transform the collection expression.
+  ExprResult Collection = getDerived().TransformExpr(S->getCollection());
+  if (Collection.isInvalid())
+    return StmtError();
+  Collection = getDerived().RebuildObjCForCollectionOperand(S->getForLoc(),
+                                                            Collection.take());
+  if (Collection.isInvalid())
+    return StmtError();
+  
+  // Transform the body.
+  StmtResult Body = getDerived().TransformStmt(S->getBody());
+  if (Body.isInvalid())
+    return StmtError();
+  
+  // If nothing changed, just retain this statement.
+  if (!getDerived().AlwaysRebuild() &&
+      Element.get() == S->getElement() &&
+      Collection.get() == S->getCollection() &&
+      Body.get() == S->getBody())
+    return SemaRef.Owned(S);
+  
+  // Build a new statement.
+  return getDerived().RebuildObjCForCollectionStmt(S->getForLoc(),
+                                                   /*FIXME:*/S->getForLoc(),
+                                                   Element.get(),
+                                                   Collection.get(),
+                                                   S->getRParenLoc(),
+                                                   Body.get());
+}
+
+
+template<typename Derived>
+StmtResult
+TreeTransform<Derived>::TransformCXXCatchStmt(CXXCatchStmt *S) {
+  // Transform the exception declaration, if any.
+  VarDecl *Var = 0;
+  if (S->getExceptionDecl()) {
+    VarDecl *ExceptionDecl = S->getExceptionDecl();
+    TypeSourceInfo *T = getDerived().TransformType(
+                                            ExceptionDecl->getTypeSourceInfo());
+    if (!T)
+      return StmtError();
+
+    Var = getDerived().RebuildExceptionDecl(ExceptionDecl, T,
+                                            ExceptionDecl->getInnerLocStart(),
+                                            ExceptionDecl->getLocation(),
+                                            ExceptionDecl->getIdentifier());
+    if (!Var || Var->isInvalidDecl())
+      return StmtError();
+  }
+
+  // Transform the actual exception handler.
+  StmtResult Handler = getDerived().TransformStmt(S->getHandlerBlock());
+  if (Handler.isInvalid())
+    return StmtError();
+
+  if (!getDerived().AlwaysRebuild() &&
+      !Var &&
+      Handler.get() == S->getHandlerBlock())
+    return SemaRef.Owned(S);
+
+  return getDerived().RebuildCXXCatchStmt(S->getCatchLoc(),
+                                          Var,
+                                          Handler.get());
+}
+
+template<typename Derived>
+StmtResult
+TreeTransform<Derived>::TransformCXXTryStmt(CXXTryStmt *S) {
+  // Transform the try block itself.
+  StmtResult TryBlock
+    = getDerived().TransformCompoundStmt(S->getTryBlock());
+  if (TryBlock.isInvalid())
+    return StmtError();
+
+  // Transform the handlers.
+  bool HandlerChanged = false;
+  ASTOwningVector<Stmt*> Handlers(SemaRef);
+  for (unsigned I = 0, N = S->getNumHandlers(); I != N; ++I) {
+    StmtResult Handler
+      = getDerived().TransformCXXCatchStmt(S->getHandler(I));
+    if (Handler.isInvalid())
+      return StmtError();
+
+    HandlerChanged = HandlerChanged || Handler.get() != S->getHandler(I);
+    Handlers.push_back(Handler.takeAs<Stmt>());
+  }
+
+  if (!getDerived().AlwaysRebuild() &&
+      TryBlock.get() == S->getTryBlock() &&
+      !HandlerChanged)
+    return SemaRef.Owned(S);
+
+  return getDerived().RebuildCXXTryStmt(S->getTryLoc(), TryBlock.get(),
+                                        move_arg(Handlers));
+}
+
+template<typename Derived>
+StmtResult
+TreeTransform<Derived>::TransformCXXForRangeStmt(CXXForRangeStmt *S) {
+  StmtResult Range = getDerived().TransformStmt(S->getRangeStmt());
+  if (Range.isInvalid())
+    return StmtError();
+
+  StmtResult BeginEnd = getDerived().TransformStmt(S->getBeginEndStmt());
+  if (BeginEnd.isInvalid())
+    return StmtError();
+
+  ExprResult Cond = getDerived().TransformExpr(S->getCond());
+  if (Cond.isInvalid())
+    return StmtError();
+  if (Cond.get())
+    Cond = SemaRef.CheckBooleanCondition(Cond.take(), S->getColonLoc());
+  if (Cond.isInvalid())
+    return StmtError();
+  if (Cond.get())
+    Cond = SemaRef.MaybeCreateExprWithCleanups(Cond.take());
+
+  ExprResult Inc = getDerived().TransformExpr(S->getInc());
+  if (Inc.isInvalid())
+    return StmtError();
+  if (Inc.get())
+    Inc = SemaRef.MaybeCreateExprWithCleanups(Inc.take());
+
+  StmtResult LoopVar = getDerived().TransformStmt(S->getLoopVarStmt());
+  if (LoopVar.isInvalid())
+    return StmtError();
+
+  StmtResult NewStmt = S;
+  if (getDerived().AlwaysRebuild() ||
+      Range.get() != S->getRangeStmt() ||
+      BeginEnd.get() != S->getBeginEndStmt() ||
+      Cond.get() != S->getCond() ||
+      Inc.get() != S->getInc() ||
+      LoopVar.get() != S->getLoopVarStmt())
+    NewStmt = getDerived().RebuildCXXForRangeStmt(S->getForLoc(),
+                                                  S->getColonLoc(), Range.get(),
+                                                  BeginEnd.get(), Cond.get(),
+                                                  Inc.get(), LoopVar.get(),
+                                                  S->getRParenLoc());
+
+  StmtResult Body = getDerived().TransformStmt(S->getBody());
+  if (Body.isInvalid())
+    return StmtError();
+
+  // Body has changed but we didn't rebuild the for-range statement. Rebuild
+  // it now so we have a new statement to attach the body to.
+  if (Body.get() != S->getBody() && NewStmt.get() == S)
+    NewStmt = getDerived().RebuildCXXForRangeStmt(S->getForLoc(),
+                                                  S->getColonLoc(), Range.get(),
+                                                  BeginEnd.get(), Cond.get(),
+                                                  Inc.get(), LoopVar.get(),
+                                                  S->getRParenLoc());
+
+  if (NewStmt.get() == S)
+    return SemaRef.Owned(S);
+
+  return FinishCXXForRangeStmt(NewStmt.get(), Body.get());
+}
+
+template<typename Derived>
+StmtResult
+TreeTransform<Derived>::TransformMSDependentExistsStmt(
+                                                    MSDependentExistsStmt *S) {
+  // Transform the nested-name-specifier, if any.
+  NestedNameSpecifierLoc QualifierLoc;
+  if (S->getQualifierLoc()) {
+    QualifierLoc 
+      = getDerived().TransformNestedNameSpecifierLoc(S->getQualifierLoc());
+    if (!QualifierLoc)
+      return StmtError();
+  }
+
+  // Transform the declaration name.
+  DeclarationNameInfo NameInfo = S->getNameInfo();
+  if (NameInfo.getName()) {
+    NameInfo = getDerived().TransformDeclarationNameInfo(NameInfo);
+    if (!NameInfo.getName())
+      return StmtError();
+  }
+
+  // Check whether anything changed.
+  if (!getDerived().AlwaysRebuild() &&
+      QualifierLoc == S->getQualifierLoc() &&
+      NameInfo.getName() == S->getNameInfo().getName())
+    return S;
+  
+  // Determine whether this name exists, if we can.
+  CXXScopeSpec SS;
+  SS.Adopt(QualifierLoc);
+  bool Dependent = false;
+  switch (getSema().CheckMicrosoftIfExistsSymbol(/*S=*/0, SS, NameInfo)) {
+  case Sema::IER_Exists:
+    if (S->isIfExists())
+      break;
+      
+    return new (getSema().Context) NullStmt(S->getKeywordLoc());
+
+  case Sema::IER_DoesNotExist:
+    if (S->isIfNotExists())
+      break;
+    
+    return new (getSema().Context) NullStmt(S->getKeywordLoc());
+      
+  case Sema::IER_Dependent:
+    Dependent = true;
+    break;
+      
+  case Sema::IER_Error:
+    return StmtError();
+  }
+  
+  // We need to continue with the instantiation, so do so now.
+  StmtResult SubStmt = getDerived().TransformCompoundStmt(S->getSubStmt());
+  if (SubStmt.isInvalid())
+    return StmtError();
+  
+  // If we have resolved the name, just transform to the substatement.
+  if (!Dependent)
+    return SubStmt;
+  
+  // The name is still dependent, so build a dependent expression again.
+  return getDerived().RebuildMSDependentExistsStmt(S->getKeywordLoc(),
+                                                   S->isIfExists(),
+                                                   QualifierLoc,
+                                                   NameInfo,
+                                                   SubStmt.get());
+}
+
+template<typename Derived>
+StmtResult
+TreeTransform<Derived>::TransformSEHTryStmt(SEHTryStmt *S) {
+  StmtResult TryBlock; //  = getDerived().TransformCompoundStmt(S->getTryBlock());
+  if(TryBlock.isInvalid()) return StmtError();
+
+  StmtResult Handler = getDerived().TransformSEHHandler(S->getHandler());
+  if(!getDerived().AlwaysRebuild() &&
+     TryBlock.get() == S->getTryBlock() &&
+     Handler.get() == S->getHandler())
+    return SemaRef.Owned(S);
+
+  return getDerived().RebuildSEHTryStmt(S->getIsCXXTry(),
+                                        S->getTryLoc(),
+                                        TryBlock.take(),
+                                        Handler.take());
+}
+
+template<typename Derived>
+StmtResult
+TreeTransform<Derived>::TransformSEHFinallyStmt(SEHFinallyStmt *S) {
+  StmtResult Block; //  = getDerived().TransformCompoundStatement(S->getBlock());
+  if(Block.isInvalid()) return StmtError();
+
+  return getDerived().RebuildSEHFinallyStmt(S->getFinallyLoc(),
+                                            Block.take());
+}
+
+template<typename Derived>
+StmtResult
+TreeTransform<Derived>::TransformSEHExceptStmt(SEHExceptStmt *S) {
+  ExprResult FilterExpr = getDerived().TransformExpr(S->getFilterExpr());
+  if(FilterExpr.isInvalid()) return StmtError();
+
+  StmtResult Block; //  = getDerived().TransformCompoundStatement(S->getBlock());
+  if(Block.isInvalid()) return StmtError();
+
+  return getDerived().RebuildSEHExceptStmt(S->getExceptLoc(),
+                                           FilterExpr.take(),
+                                           Block.take());
+}
+
+template<typename Derived>
+StmtResult
+TreeTransform<Derived>::TransformSEHHandler(Stmt *Handler) {
+  if(isa<SEHFinallyStmt>(Handler))
+    return getDerived().TransformSEHFinallyStmt(cast<SEHFinallyStmt>(Handler));
+  else
+    return getDerived().TransformSEHExceptStmt(cast<SEHExceptStmt>(Handler));
+}
+
+//===----------------------------------------------------------------------===//
+// Expression transformation
+//===----------------------------------------------------------------------===//
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformPredefinedExpr(PredefinedExpr *E) {
+  return SemaRef.Owned(E);
+}
+
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformDeclRefExpr(DeclRefExpr *E) {
+  NestedNameSpecifierLoc QualifierLoc;
+  if (E->getQualifierLoc()) {
+    QualifierLoc
+      = getDerived().TransformNestedNameSpecifierLoc(E->getQualifierLoc());
+    if (!QualifierLoc)
+      return ExprError();
+  }
+
+  ValueDecl *ND
+    = cast_or_null<ValueDecl>(getDerived().TransformDecl(E->getLocation(),
+                                                         E->getDecl()));
+  if (!ND)
+    return ExprError();
+
+  DeclarationNameInfo NameInfo = E->getNameInfo();
+  if (NameInfo.getName()) {
+    NameInfo = getDerived().TransformDeclarationNameInfo(NameInfo);
+    if (!NameInfo.getName())
+      return ExprError();
+  }
+
+  if (!getDerived().AlwaysRebuild() &&
+      QualifierLoc == E->getQualifierLoc() &&
+      ND == E->getDecl() &&
+      NameInfo.getName() == E->getDecl()->getDeclName() &&
+      !E->hasExplicitTemplateArgs()) {
+
+    // Mark it referenced in the new context regardless.
+    // FIXME: this is a bit instantiation-specific.
+    SemaRef.MarkDeclRefReferenced(E);
+
+    return SemaRef.Owned(E);
+  }
+
+  TemplateArgumentListInfo TransArgs, *TemplateArgs = 0;
+  if (E->hasExplicitTemplateArgs()) {
+    TemplateArgs = &TransArgs;
+    TransArgs.setLAngleLoc(E->getLAngleLoc());
+    TransArgs.setRAngleLoc(E->getRAngleLoc());
+    if (getDerived().TransformTemplateArguments(E->getTemplateArgs(),
+                                                E->getNumTemplateArgs(),
+                                                TransArgs))
+      return ExprError();
+  }
+
+  return getDerived().RebuildDeclRefExpr(QualifierLoc, ND, NameInfo, 
+                                         TemplateArgs);
+}
+
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformIntegerLiteral(IntegerLiteral *E) {
+  return SemaRef.Owned(E);
+}
+
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformFloatingLiteral(FloatingLiteral *E) {
+  return SemaRef.Owned(E);
+}
+
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformImaginaryLiteral(ImaginaryLiteral *E) {
+  return SemaRef.Owned(E);
+}
+
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformStringLiteral(StringLiteral *E) {
+  return SemaRef.Owned(E);
+}
+
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformCharacterLiteral(CharacterLiteral *E) {
+  return SemaRef.Owned(E);
+}
+
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformUserDefinedLiteral(UserDefinedLiteral *E) {
+  return SemaRef.MaybeBindToTemporary(E);
+}
+
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformGenericSelectionExpr(GenericSelectionExpr *E) {
+  ExprResult ControllingExpr =
+    getDerived().TransformExpr(E->getControllingExpr());
+  if (ControllingExpr.isInvalid())
+    return ExprError();
+
+  SmallVector<Expr *, 4> AssocExprs;
+  SmallVector<TypeSourceInfo *, 4> AssocTypes;
+  for (unsigned i = 0; i != E->getNumAssocs(); ++i) {
+    TypeSourceInfo *TS = E->getAssocTypeSourceInfo(i);
+    if (TS) {
+      TypeSourceInfo *AssocType = getDerived().TransformType(TS);
+      if (!AssocType)
+        return ExprError();
+      AssocTypes.push_back(AssocType);
+    } else {
+      AssocTypes.push_back(0);
+    }
+
+    ExprResult AssocExpr = getDerived().TransformExpr(E->getAssocExpr(i));
+    if (AssocExpr.isInvalid())
+      return ExprError();
+    AssocExprs.push_back(AssocExpr.release());
+  }
+
+  return getDerived().RebuildGenericSelectionExpr(E->getGenericLoc(),
+                                                  E->getDefaultLoc(),
+                                                  E->getRParenLoc(),
+                                                  ControllingExpr.release(),
+                                                  AssocTypes.data(),
+                                                  AssocExprs.data(),
+                                                  E->getNumAssocs());
+}
+
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformParenExpr(ParenExpr *E) {
+  ExprResult SubExpr = getDerived().TransformExpr(E->getSubExpr());
+  if (SubExpr.isInvalid())
+    return ExprError();
+
+  if (!getDerived().AlwaysRebuild() && SubExpr.get() == E->getSubExpr())
+    return SemaRef.Owned(E);
+
+  return getDerived().RebuildParenExpr(SubExpr.get(), E->getLParen(),
+                                       E->getRParen());
+}
+
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformUnaryOperator(UnaryOperator *E) {
+  ExprResult SubExpr = getDerived().TransformExpr(E->getSubExpr());
+  if (SubExpr.isInvalid())
+    return ExprError();
+
+  if (!getDerived().AlwaysRebuild() && SubExpr.get() == E->getSubExpr())
+    return SemaRef.Owned(E);
+
+  return getDerived().RebuildUnaryOperator(E->getOperatorLoc(),
+                                           E->getOpcode(),
+                                           SubExpr.get());
+}
+
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformOffsetOfExpr(OffsetOfExpr *E) {
+  // Transform the type.
+  TypeSourceInfo *Type = getDerived().TransformType(E->getTypeSourceInfo());
+  if (!Type)
+    return ExprError();
+  
+  // Transform all of the components into components similar to what the
+  // parser uses.
+  // FIXME: It would be slightly more efficient in the non-dependent case to 
+  // just map FieldDecls, rather than requiring the rebuilder to look for 
+  // the fields again. However, __builtin_offsetof is rare enough in 
+  // template code that we don't care.
+  bool ExprChanged = false;
+  typedef Sema::OffsetOfComponent Component;
+  typedef OffsetOfExpr::OffsetOfNode Node;
+  SmallVector<Component, 4> Components;
+  for (unsigned I = 0, N = E->getNumComponents(); I != N; ++I) {
+    const Node &ON = E->getComponent(I);
+    Component Comp;
+    Comp.isBrackets = true;
+    Comp.LocStart = ON.getSourceRange().getBegin();
+    Comp.LocEnd = ON.getSourceRange().getEnd();
+    switch (ON.getKind()) {
+    case Node::Array: {
+      Expr *FromIndex = E->getIndexExpr(ON.getArrayExprIndex());
+      ExprResult Index = getDerived().TransformExpr(FromIndex);
+      if (Index.isInvalid())
+        return ExprError();
+      
+      ExprChanged = ExprChanged || Index.get() != FromIndex;
+      Comp.isBrackets = true;
+      Comp.U.E = Index.get();
+      break;
+    }
+        
+    case Node::Field:
+    case Node::Identifier:
+      Comp.isBrackets = false;
+      Comp.U.IdentInfo = ON.getFieldName();
+      if (!Comp.U.IdentInfo)
+        continue;
+        
+      break;
+        
+    case Node::Base:
+      // Will be recomputed during the rebuild.
+      continue;
+    }
+    
+    Components.push_back(Comp);
+  }
+  
+  // If nothing changed, retain the existing expression.
+  if (!getDerived().AlwaysRebuild() &&
+      Type == E->getTypeSourceInfo() &&
+      !ExprChanged)
+    return SemaRef.Owned(E);
+  
+  // Build a new offsetof expression.
+  return getDerived().RebuildOffsetOfExpr(E->getOperatorLoc(), Type,
+                                          Components.data(), Components.size(),
+                                          E->getRParenLoc());
+}
+
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformOpaqueValueExpr(OpaqueValueExpr *E) {
+  assert(getDerived().AlreadyTransformed(E->getType()) &&
+         "opaque value expression requires transformation");
+  return SemaRef.Owned(E);
+}
+
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformPseudoObjectExpr(PseudoObjectExpr *E) {
+  // Rebuild the syntactic form.  The original syntactic form has
+  // opaque-value expressions in it, so strip those away and rebuild
+  // the result.  This is a really awful way of doing this, but the
+  // better solution (rebuilding the semantic expressions and
+  // rebinding OVEs as necessary) doesn't work; we'd need
+  // TreeTransform to not strip away implicit conversions.
+  Expr *newSyntacticForm = SemaRef.recreateSyntacticForm(E);
+  ExprResult result = getDerived().TransformExpr(newSyntacticForm);
+  if (result.isInvalid()) return ExprError();
+
+  // If that gives us a pseudo-object result back, the pseudo-object
+  // expression must have been an lvalue-to-rvalue conversion which we
+  // should reapply.
+  if (result.get()->hasPlaceholderType(BuiltinType::PseudoObject))
+    result = SemaRef.checkPseudoObjectRValue(result.take());
+
+  return result;
+}
+
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformUnaryExprOrTypeTraitExpr(
+                                                UnaryExprOrTypeTraitExpr *E) {
+  if (E->isArgumentType()) {
+    TypeSourceInfo *OldT = E->getArgumentTypeInfo();
+
+    TypeSourceInfo *NewT = getDerived().TransformType(OldT);
+    if (!NewT)
+      return ExprError();
+
+    if (!getDerived().AlwaysRebuild() && OldT == NewT)
+      return SemaRef.Owned(E);
+
+    return getDerived().RebuildUnaryExprOrTypeTrait(NewT, E->getOperatorLoc(),
+                                                    E->getKind(),
+                                                    E->getSourceRange());
+  }
+
+  // C++0x [expr.sizeof]p1:
+  //   The operand is either an expression, which is an unevaluated operand
+  //   [...]
+  EnterExpressionEvaluationContext Unevaluated(SemaRef, Sema::Unevaluated);
+
+  ExprResult SubExpr = getDerived().TransformExpr(E->getArgumentExpr());
+  if (SubExpr.isInvalid())
+    return ExprError();
+
+  if (!getDerived().AlwaysRebuild() && SubExpr.get() == E->getArgumentExpr())
+    return SemaRef.Owned(E);
+
+  return getDerived().RebuildUnaryExprOrTypeTrait(SubExpr.get(),
+                                                  E->getOperatorLoc(),
+                                                  E->getKind(),
+                                                  E->getSourceRange());
+}
+
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformArraySubscriptExpr(ArraySubscriptExpr *E) {
+  ExprResult LHS = getDerived().TransformExpr(E->getLHS());
+  if (LHS.isInvalid())
+    return ExprError();
+
+  ExprResult RHS = getDerived().TransformExpr(E->getRHS());
+  if (RHS.isInvalid())
+    return ExprError();
+
+
+  if (!getDerived().AlwaysRebuild() &&
+      LHS.get() == E->getLHS() &&
+      RHS.get() == E->getRHS())
+    return SemaRef.Owned(E);
+
+  return getDerived().RebuildArraySubscriptExpr(LHS.get(),
+                                           /*FIXME:*/E->getLHS()->getLocStart(),
+                                                RHS.get(),
+                                                E->getRBracketLoc());
+}
+
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformCallExpr(CallExpr *E) {
+  // Transform the callee.
+  ExprResult Callee = getDerived().TransformExpr(E->getCallee());
+  if (Callee.isInvalid())
+    return ExprError();
+
+  // Transform arguments.
+  bool ArgChanged = false;
+  ASTOwningVector<Expr*> Args(SemaRef);
+  if (getDerived().TransformExprs(E->getArgs(), E->getNumArgs(), true, Args, 
+                                  &ArgChanged))
+    return ExprError();
+  
+  if (!getDerived().AlwaysRebuild() &&
+      Callee.get() == E->getCallee() &&
+      !ArgChanged)
+    return SemaRef.MaybeBindToTemporary(E);;
+
+  // FIXME: Wrong source location information for the '('.
+  SourceLocation FakeLParenLoc
+    = ((Expr *)Callee.get())->getSourceRange().getBegin();
+  return getDerived().RebuildCallExpr(Callee.get(), FakeLParenLoc,
+                                      move_arg(Args),
+                                      E->getRParenLoc());
+}
+
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformMemberExpr(MemberExpr *E) {
+  ExprResult Base = getDerived().TransformExpr(E->getBase());
+  if (Base.isInvalid())
+    return ExprError();
+
+  NestedNameSpecifierLoc QualifierLoc;
+  if (E->hasQualifier()) {
+    QualifierLoc
+      = getDerived().TransformNestedNameSpecifierLoc(E->getQualifierLoc());
+    
+    if (!QualifierLoc)
+      return ExprError();
+  }
+  SourceLocation TemplateKWLoc = E->getTemplateKeywordLoc();
+
+  ValueDecl *Member
+    = cast_or_null<ValueDecl>(getDerived().TransformDecl(E->getMemberLoc(),
+                                                         E->getMemberDecl()));
+  if (!Member)
+    return ExprError();
+
+  NamedDecl *FoundDecl = E->getFoundDecl();
+  if (FoundDecl == E->getMemberDecl()) {
+    FoundDecl = Member;
+  } else {
+    FoundDecl = cast_or_null<NamedDecl>(
+                   getDerived().TransformDecl(E->getMemberLoc(), FoundDecl));
+    if (!FoundDecl)
+      return ExprError();
+  }
+
+  if (!getDerived().AlwaysRebuild() &&
+      Base.get() == E->getBase() &&
+      QualifierLoc == E->getQualifierLoc() &&
+      Member == E->getMemberDecl() &&
+      FoundDecl == E->getFoundDecl() &&
+      !E->hasExplicitTemplateArgs()) {
+    
+    // Mark it referenced in the new context regardless.
+    // FIXME: this is a bit instantiation-specific.
+    SemaRef.MarkMemberReferenced(E);
+
+    return SemaRef.Owned(E);
+  }
+
+  TemplateArgumentListInfo TransArgs;
+  if (E->hasExplicitTemplateArgs()) {
+    TransArgs.setLAngleLoc(E->getLAngleLoc());
+    TransArgs.setRAngleLoc(E->getRAngleLoc());
+    if (getDerived().TransformTemplateArguments(E->getTemplateArgs(),
+                                                E->getNumTemplateArgs(),
+                                                TransArgs))
+      return ExprError();
+  }
+  
+  // FIXME: Bogus source location for the operator
+  SourceLocation FakeOperatorLoc
+    = SemaRef.PP.getLocForEndOfToken(E->getBase()->getSourceRange().getEnd());
+
+  // FIXME: to do this check properly, we will need to preserve the
+  // first-qualifier-in-scope here, just in case we had a dependent
+  // base (and therefore couldn't do the check) and a
+  // nested-name-qualifier (and therefore could do the lookup).
+  NamedDecl *FirstQualifierInScope = 0;
+
+  return getDerived().RebuildMemberExpr(Base.get(), FakeOperatorLoc,
+                                        E->isArrow(),
+                                        QualifierLoc,
+                                        TemplateKWLoc,
+                                        E->getMemberNameInfo(),
+                                        Member,
+                                        FoundDecl,
+                                        (E->hasExplicitTemplateArgs()
+                                           ? &TransArgs : 0),
+                                        FirstQualifierInScope);
+}
+
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformBinaryOperator(BinaryOperator *E) {
+  ExprResult LHS = getDerived().TransformExpr(E->getLHS());
+  if (LHS.isInvalid())
+    return ExprError();
+
+  ExprResult RHS = getDerived().TransformExpr(E->getRHS());
+  if (RHS.isInvalid())
+    return ExprError();
+
+  if (!getDerived().AlwaysRebuild() &&
+      LHS.get() == E->getLHS() &&
+      RHS.get() == E->getRHS())
+    return SemaRef.Owned(E);
+
+  return getDerived().RebuildBinaryOperator(E->getOperatorLoc(), E->getOpcode(),
+                                            LHS.get(), RHS.get());
+}
+
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformCompoundAssignOperator(
+                                                      CompoundAssignOperator *E) {
+  return getDerived().TransformBinaryOperator(E);
+}
+
+template<typename Derived>
+ExprResult TreeTransform<Derived>::
+TransformBinaryConditionalOperator(BinaryConditionalOperator *e) {
+  // Just rebuild the common and RHS expressions and see whether we
+  // get any changes.
+
+  ExprResult commonExpr = getDerived().TransformExpr(e->getCommon());
+  if (commonExpr.isInvalid())
+    return ExprError();
+
+  ExprResult rhs = getDerived().TransformExpr(e->getFalseExpr());
+  if (rhs.isInvalid())
+    return ExprError();
+
+  if (!getDerived().AlwaysRebuild() &&
+      commonExpr.get() == e->getCommon() &&
+      rhs.get() == e->getFalseExpr())
+    return SemaRef.Owned(e);
+
+  return getDerived().RebuildConditionalOperator(commonExpr.take(),
+                                                 e->getQuestionLoc(),
+                                                 0,
+                                                 e->getColonLoc(),
+                                                 rhs.get());
+}
+
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformConditionalOperator(ConditionalOperator *E) {
+  ExprResult Cond = getDerived().TransformExpr(E->getCond());
+  if (Cond.isInvalid())
+    return ExprError();
+
+  ExprResult LHS = getDerived().TransformExpr(E->getLHS());
+  if (LHS.isInvalid())
+    return ExprError();
+
+  ExprResult RHS = getDerived().TransformExpr(E->getRHS());
+  if (RHS.isInvalid())
+    return ExprError();
+
+  if (!getDerived().AlwaysRebuild() &&
+      Cond.get() == E->getCond() &&
+      LHS.get() == E->getLHS() &&
+      RHS.get() == E->getRHS())
+    return SemaRef.Owned(E);
+
+  return getDerived().RebuildConditionalOperator(Cond.get(),
+                                                 E->getQuestionLoc(),
+                                                 LHS.get(),
+                                                 E->getColonLoc(),
+                                                 RHS.get());
+}
+
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformImplicitCastExpr(ImplicitCastExpr *E) {
+  // Implicit casts are eliminated during transformation, since they
+  // will be recomputed by semantic analysis after transformation.
+  return getDerived().TransformExpr(E->getSubExprAsWritten());
+}
+
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformCStyleCastExpr(CStyleCastExpr *E) {
+  TypeSourceInfo *Type = getDerived().TransformType(E->getTypeInfoAsWritten());
+  if (!Type)
+    return ExprError();
+  
+  ExprResult SubExpr
+    = getDerived().TransformExpr(E->getSubExprAsWritten());
+  if (SubExpr.isInvalid())
+    return ExprError();
+
+  if (!getDerived().AlwaysRebuild() &&
+      Type == E->getTypeInfoAsWritten() &&
+      SubExpr.get() == E->getSubExpr())
+    return SemaRef.Owned(E);
+
+  return getDerived().RebuildCStyleCastExpr(E->getLParenLoc(),
+                                            Type,
+                                            E->getRParenLoc(),
+                                            SubExpr.get());
+}
+
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformCompoundLiteralExpr(CompoundLiteralExpr *E) {
+  TypeSourceInfo *OldT = E->getTypeSourceInfo();
+  TypeSourceInfo *NewT = getDerived().TransformType(OldT);
+  if (!NewT)
+    return ExprError();
+
+  ExprResult Init = getDerived().TransformExpr(E->getInitializer());
+  if (Init.isInvalid())
+    return ExprError();
+
+  if (!getDerived().AlwaysRebuild() &&
+      OldT == NewT &&
+      Init.get() == E->getInitializer())
+    return SemaRef.MaybeBindToTemporary(E);
+
+  // Note: the expression type doesn't necessarily match the
+  // type-as-written, but that's okay, because it should always be
+  // derivable from the initializer.
+
+  return getDerived().RebuildCompoundLiteralExpr(E->getLParenLoc(), NewT,
+                                   /*FIXME:*/E->getInitializer()->getLocEnd(),
+                                                 Init.get());
+}
+
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformExtVectorElementExpr(ExtVectorElementExpr *E) {
+  ExprResult Base = getDerived().TransformExpr(E->getBase());
+  if (Base.isInvalid())
+    return ExprError();
+
+  if (!getDerived().AlwaysRebuild() &&
+      Base.get() == E->getBase())
+    return SemaRef.Owned(E);
+
+  // FIXME: Bad source location
+  SourceLocation FakeOperatorLoc
+    = SemaRef.PP.getLocForEndOfToken(E->getBase()->getLocEnd());
+  return getDerived().RebuildExtVectorElementExpr(Base.get(), FakeOperatorLoc,
+                                                  E->getAccessorLoc(),
+                                                  E->getAccessor());
+}
+
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformInitListExpr(InitListExpr *E) {
+  bool InitChanged = false;
+
+  ASTOwningVector<Expr*, 4> Inits(SemaRef);
+  if (getDerived().TransformExprs(E->getInits(), E->getNumInits(), false, 
+                                  Inits, &InitChanged))
+    return ExprError();
+  
+  if (!getDerived().AlwaysRebuild() && !InitChanged)
+    return SemaRef.Owned(E);
+
+  return getDerived().RebuildInitList(E->getLBraceLoc(), move_arg(Inits),
+                                      E->getRBraceLoc(), E->getType());
+}
+
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformDesignatedInitExpr(DesignatedInitExpr *E) {
+  Designation Desig;
+
+  // transform the initializer value
+  ExprResult Init = getDerived().TransformExpr(E->getInit());
+  if (Init.isInvalid())
+    return ExprError();
+
+  // transform the designators.
+  ASTOwningVector<Expr*, 4> ArrayExprs(SemaRef);
+  bool ExprChanged = false;
+  for (DesignatedInitExpr::designators_iterator D = E->designators_begin(),
+                                             DEnd = E->designators_end();
+       D != DEnd; ++D) {
+    if (D->isFieldDesignator()) {
+      Desig.AddDesignator(Designator::getField(D->getFieldName(),
+                                               D->getDotLoc(),
+                                               D->getFieldLoc()));
+      continue;
+    }
+
+    if (D->isArrayDesignator()) {
+      ExprResult Index = getDerived().TransformExpr(E->getArrayIndex(*D));
+      if (Index.isInvalid())
+        return ExprError();
+
+      Desig.AddDesignator(Designator::getArray(Index.get(),
+                                               D->getLBracketLoc()));
+
+      ExprChanged = ExprChanged || Init.get() != E->getArrayIndex(*D);
+      ArrayExprs.push_back(Index.release());
+      continue;
+    }
+
+    assert(D->isArrayRangeDesignator() && "New kind of designator?");
+    ExprResult Start
+      = getDerived().TransformExpr(E->getArrayRangeStart(*D));
+    if (Start.isInvalid())
+      return ExprError();
+
+    ExprResult End = getDerived().TransformExpr(E->getArrayRangeEnd(*D));
+    if (End.isInvalid())
+      return ExprError();
+
+    Desig.AddDesignator(Designator::getArrayRange(Start.get(),
+                                                  End.get(),
+                                                  D->getLBracketLoc(),
+                                                  D->getEllipsisLoc()));
+
+    ExprChanged = ExprChanged || Start.get() != E->getArrayRangeStart(*D) ||
+      End.get() != E->getArrayRangeEnd(*D);
+
+    ArrayExprs.push_back(Start.release());
+    ArrayExprs.push_back(End.release());
+  }
+
+  if (!getDerived().AlwaysRebuild() &&
+      Init.get() == E->getInit() &&
+      !ExprChanged)
+    return SemaRef.Owned(E);
+
+  return getDerived().RebuildDesignatedInitExpr(Desig, move_arg(ArrayExprs),
+                                                E->getEqualOrColonLoc(),
+                                                E->usesGNUSyntax(), Init.get());
+}
+
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformImplicitValueInitExpr(
+                                                     ImplicitValueInitExpr *E) {
+  TemporaryBase Rebase(*this, E->getLocStart(), DeclarationName());
+  
+  // FIXME: Will we ever have proper type location here? Will we actually
+  // need to transform the type?
+  QualType T = getDerived().TransformType(E->getType());
+  if (T.isNull())
+    return ExprError();
+
+  if (!getDerived().AlwaysRebuild() &&
+      T == E->getType())
+    return SemaRef.Owned(E);
+
+  return getDerived().RebuildImplicitValueInitExpr(T);
+}
+
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformVAArgExpr(VAArgExpr *E) {
+  TypeSourceInfo *TInfo = getDerived().TransformType(E->getWrittenTypeInfo());
+  if (!TInfo)
+    return ExprError();
+
+  ExprResult SubExpr = getDerived().TransformExpr(E->getSubExpr());
+  if (SubExpr.isInvalid())
+    return ExprError();
+
+  if (!getDerived().AlwaysRebuild() &&
+      TInfo == E->getWrittenTypeInfo() &&
+      SubExpr.get() == E->getSubExpr())
+    return SemaRef.Owned(E);
+
+  return getDerived().RebuildVAArgExpr(E->getBuiltinLoc(), SubExpr.get(),
+                                       TInfo, E->getRParenLoc());
+}
+
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformParenListExpr(ParenListExpr *E) {
+  bool ArgumentChanged = false;
+  ASTOwningVector<Expr*, 4> Inits(SemaRef);
+  if (TransformExprs(E->getExprs(), E->getNumExprs(), true, Inits,
+                     &ArgumentChanged))
+    return ExprError();
+  
+  return getDerived().RebuildParenListExpr(E->getLParenLoc(),
+                                           move_arg(Inits),
+                                           E->getRParenLoc());
+}
+
+/// \brief Transform an address-of-label expression.
+///
+/// By default, the transformation of an address-of-label expression always
+/// rebuilds the expression, so that the label identifier can be resolved to
+/// the corresponding label statement by semantic analysis.
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformAddrLabelExpr(AddrLabelExpr *E) {
+  Decl *LD = getDerived().TransformDecl(E->getLabel()->getLocation(),
+                                        E->getLabel());
+  if (!LD)
+    return ExprError();
+  
+  return getDerived().RebuildAddrLabelExpr(E->getAmpAmpLoc(), E->getLabelLoc(),
+                                           cast<LabelDecl>(LD));
+}
+
+template<typename Derived>
+ExprResult 
+TreeTransform<Derived>::TransformStmtExpr(StmtExpr *E) {
+  SemaRef.ActOnStartStmtExpr();
+  StmtResult SubStmt
+    = getDerived().TransformCompoundStmt(E->getSubStmt(), true);
+  if (SubStmt.isInvalid()) {
+    SemaRef.ActOnStmtExprError();
+    return ExprError();
+  }
+
+  if (!getDerived().AlwaysRebuild() &&
+      SubStmt.get() == E->getSubStmt()) {
+    // Calling this an 'error' is unintuitive, but it does the right thing.
+    SemaRef.ActOnStmtExprError();
+    return SemaRef.MaybeBindToTemporary(E);
+  }
+
+  return getDerived().RebuildStmtExpr(E->getLParenLoc(),
+                                      SubStmt.get(),
+                                      E->getRParenLoc());
+}
+
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformChooseExpr(ChooseExpr *E) {
+  ExprResult Cond = getDerived().TransformExpr(E->getCond());
+  if (Cond.isInvalid())
+    return ExprError();
+
+  ExprResult LHS = getDerived().TransformExpr(E->getLHS());
+  if (LHS.isInvalid())
+    return ExprError();
+
+  ExprResult RHS = getDerived().TransformExpr(E->getRHS());
+  if (RHS.isInvalid())
+    return ExprError();
+
+  if (!getDerived().AlwaysRebuild() &&
+      Cond.get() == E->getCond() &&
+      LHS.get() == E->getLHS() &&
+      RHS.get() == E->getRHS())
+    return SemaRef.Owned(E);
+
+  return getDerived().RebuildChooseExpr(E->getBuiltinLoc(),
+                                        Cond.get(), LHS.get(), RHS.get(),
+                                        E->getRParenLoc());
+}
+
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformGNUNullExpr(GNUNullExpr *E) {
+  return SemaRef.Owned(E);
+}
+
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformCXXOperatorCallExpr(CXXOperatorCallExpr *E) {
+  switch (E->getOperator()) {
+  case OO_New:
+  case OO_Delete:
+  case OO_Array_New:
+  case OO_Array_Delete:
+    llvm_unreachable("new and delete operators cannot use CXXOperatorCallExpr");
+    
+  case OO_Call: {
+    // This is a call to an object's operator().
+    assert(E->getNumArgs() >= 1 && "Object call is missing arguments");
+
+    // Transform the object itself.
+    ExprResult Object = getDerived().TransformExpr(E->getArg(0));
+    if (Object.isInvalid())
+      return ExprError();
+
+    // FIXME: Poor location information
+    SourceLocation FakeLParenLoc
+      = SemaRef.PP.getLocForEndOfToken(
+                              static_cast<Expr *>(Object.get())->getLocEnd());
+
+    // Transform the call arguments.
+    ASTOwningVector<Expr*> Args(SemaRef);
+    if (getDerived().TransformExprs(E->getArgs() + 1, E->getNumArgs() - 1, true, 
+                                    Args))
+      return ExprError();
+
+    return getDerived().RebuildCallExpr(Object.get(), FakeLParenLoc,
+                                        move_arg(Args),
+                                        E->getLocEnd());
+  }
+
+#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \
+  case OO_##Name:
+#define OVERLOADED_OPERATOR_MULTI(Name,Spelling,Unary,Binary,MemberOnly)
+#include "clang/Basic/OperatorKinds.def"
+  case OO_Subscript:
+    // Handled below.
+    break;
+
+  case OO_Conditional:
+    llvm_unreachable("conditional operator is not actually overloadable");
+
+  case OO_None:
+  case NUM_OVERLOADED_OPERATORS:
+    llvm_unreachable("not an overloaded operator?");
+  }
+
+  ExprResult Callee = getDerived().TransformExpr(E->getCallee());
+  if (Callee.isInvalid())
+    return ExprError();
+
+  ExprResult First = getDerived().TransformExpr(E->getArg(0));
+  if (First.isInvalid())
+    return ExprError();
+
+  ExprResult Second;
+  if (E->getNumArgs() == 2) {
+    Second = getDerived().TransformExpr(E->getArg(1));
+    if (Second.isInvalid())
+      return ExprError();
+  }
+
+  if (!getDerived().AlwaysRebuild() &&
+      Callee.get() == E->getCallee() &&
+      First.get() == E->getArg(0) &&
+      (E->getNumArgs() != 2 || Second.get() == E->getArg(1)))
+    return SemaRef.MaybeBindToTemporary(E);
+
+  return getDerived().RebuildCXXOperatorCallExpr(E->getOperator(),
+                                                 E->getOperatorLoc(),
+                                                 Callee.get(),
+                                                 First.get(),
+                                                 Second.get());
+}
+
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformCXXMemberCallExpr(CXXMemberCallExpr *E) {
+  return getDerived().TransformCallExpr(E);
+}
+
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformCUDAKernelCallExpr(CUDAKernelCallExpr *E) {
+  // Transform the callee.
+  ExprResult Callee = getDerived().TransformExpr(E->getCallee());
+  if (Callee.isInvalid())
+    return ExprError();
+
+  // Transform exec config.
+  ExprResult EC = getDerived().TransformCallExpr(E->getConfig());
+  if (EC.isInvalid())
+    return ExprError();
+
+  // Transform arguments.
+  bool ArgChanged = false;
+  ASTOwningVector<Expr*> Args(SemaRef);
+  if (getDerived().TransformExprs(E->getArgs(), E->getNumArgs(), true, Args, 
+                                  &ArgChanged))
+    return ExprError();
+
+  if (!getDerived().AlwaysRebuild() &&
+      Callee.get() == E->getCallee() &&
+      !ArgChanged)
+    return SemaRef.MaybeBindToTemporary(E);
+
+  // FIXME: Wrong source location information for the '('.
+  SourceLocation FakeLParenLoc
+    = ((Expr *)Callee.get())->getSourceRange().getBegin();
+  return getDerived().RebuildCallExpr(Callee.get(), FakeLParenLoc,
+                                      move_arg(Args),
+                                      E->getRParenLoc(), EC.get());
+}
+
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformCXXNamedCastExpr(CXXNamedCastExpr *E) {
+  TypeSourceInfo *Type = getDerived().TransformType(E->getTypeInfoAsWritten());
+  if (!Type)
+    return ExprError();
+  
+  ExprResult SubExpr
+    = getDerived().TransformExpr(E->getSubExprAsWritten());
+  if (SubExpr.isInvalid())
+    return ExprError();
+
+  if (!getDerived().AlwaysRebuild() &&
+      Type == E->getTypeInfoAsWritten() &&
+      SubExpr.get() == E->getSubExpr())
+    return SemaRef.Owned(E);
+
+  // FIXME: Poor source location information here.
+  SourceLocation FakeLAngleLoc
+    = SemaRef.PP.getLocForEndOfToken(E->getOperatorLoc());
+  SourceLocation FakeRAngleLoc = E->getSubExpr()->getSourceRange().getBegin();
+  SourceLocation FakeRParenLoc
+    = SemaRef.PP.getLocForEndOfToken(
+                                  E->getSubExpr()->getSourceRange().getEnd());
+  return getDerived().RebuildCXXNamedCastExpr(E->getOperatorLoc(),
+                                              E->getStmtClass(),
+                                              FakeLAngleLoc,
+                                              Type,
+                                              FakeRAngleLoc,
+                                              FakeRAngleLoc,
+                                              SubExpr.get(),
+                                              FakeRParenLoc);
+}
+
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformCXXStaticCastExpr(CXXStaticCastExpr *E) {
+  return getDerived().TransformCXXNamedCastExpr(E);
+}
+
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformCXXDynamicCastExpr(CXXDynamicCastExpr *E) {
+  return getDerived().TransformCXXNamedCastExpr(E);
+}
+
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformCXXReinterpretCastExpr(
+                                                      CXXReinterpretCastExpr *E) {
+  return getDerived().TransformCXXNamedCastExpr(E);
+}
+
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformCXXConstCastExpr(CXXConstCastExpr *E) {
+  return getDerived().TransformCXXNamedCastExpr(E);
+}
+
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformCXXFunctionalCastExpr(
+                                                     CXXFunctionalCastExpr *E) {
+  TypeSourceInfo *Type = getDerived().TransformType(E->getTypeInfoAsWritten());
+  if (!Type)
+    return ExprError();
+
+  ExprResult SubExpr
+    = getDerived().TransformExpr(E->getSubExprAsWritten());
+  if (SubExpr.isInvalid())
+    return ExprError();
+
+  if (!getDerived().AlwaysRebuild() &&
+      Type == E->getTypeInfoAsWritten() &&
+      SubExpr.get() == E->getSubExpr())
+    return SemaRef.Owned(E);
+
+  return getDerived().RebuildCXXFunctionalCastExpr(Type,
+                                      /*FIXME:*/E->getSubExpr()->getLocStart(),
+                                                   SubExpr.get(),
+                                                   E->getRParenLoc());
+}
+
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformCXXTypeidExpr(CXXTypeidExpr *E) {
+  if (E->isTypeOperand()) {
+    TypeSourceInfo *TInfo
+      = getDerived().TransformType(E->getTypeOperandSourceInfo());
+    if (!TInfo)
+      return ExprError();
+
+    if (!getDerived().AlwaysRebuild() &&
+        TInfo == E->getTypeOperandSourceInfo())
+      return SemaRef.Owned(E);
+
+    return getDerived().RebuildCXXTypeidExpr(E->getType(),
+                                             E->getLocStart(),
+                                             TInfo,
+                                             E->getLocEnd());
+  }
+
+  // We don't know whether the subexpression is potentially evaluated until
+  // after we perform semantic analysis.  We speculatively assume it is
+  // unevaluated; it will get fixed later if the subexpression is in fact
+  // potentially evaluated.
+  EnterExpressionEvaluationContext Unevaluated(SemaRef, Sema::Unevaluated);
+
+  ExprResult SubExpr = getDerived().TransformExpr(E->getExprOperand());
+  if (SubExpr.isInvalid())
+    return ExprError();
+
+  if (!getDerived().AlwaysRebuild() &&
+      SubExpr.get() == E->getExprOperand())
+    return SemaRef.Owned(E);
+
+  return getDerived().RebuildCXXTypeidExpr(E->getType(),
+                                           E->getLocStart(),
+                                           SubExpr.get(),
+                                           E->getLocEnd());
+}
+
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformCXXUuidofExpr(CXXUuidofExpr *E) {
+  if (E->isTypeOperand()) {
+    TypeSourceInfo *TInfo
+      = getDerived().TransformType(E->getTypeOperandSourceInfo());
+    if (!TInfo)
+      return ExprError();
+
+    if (!getDerived().AlwaysRebuild() &&
+        TInfo == E->getTypeOperandSourceInfo())
+      return SemaRef.Owned(E);
+
+    return getDerived().RebuildCXXUuidofExpr(E->getType(),
+                                             E->getLocStart(),
+                                             TInfo,
+                                             E->getLocEnd());
+  }
+
+  EnterExpressionEvaluationContext Unevaluated(SemaRef, Sema::Unevaluated);
+
+  ExprResult SubExpr = getDerived().TransformExpr(E->getExprOperand());
+  if (SubExpr.isInvalid())
+    return ExprError();
+
+  if (!getDerived().AlwaysRebuild() &&
+      SubExpr.get() == E->getExprOperand())
+    return SemaRef.Owned(E);
+
+  return getDerived().RebuildCXXUuidofExpr(E->getType(),
+                                           E->getLocStart(),
+                                           SubExpr.get(),
+                                           E->getLocEnd());
+}
+
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformCXXBoolLiteralExpr(CXXBoolLiteralExpr *E) {
+  return SemaRef.Owned(E);
+}
+
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformCXXNullPtrLiteralExpr(
+                                                     CXXNullPtrLiteralExpr *E) {
+  return SemaRef.Owned(E);
+}
+
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformCXXThisExpr(CXXThisExpr *E) {
+  DeclContext *DC = getSema().getFunctionLevelDeclContext();
+  QualType T;
+  if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(DC))
+    T = MD->getThisType(getSema().Context);
+  else
+    T = getSema().Context.getPointerType(
+      getSema().Context.getRecordType(cast<CXXRecordDecl>(DC)));
+
+  if (!getDerived().AlwaysRebuild() && T == E->getType()) {
+    // Make sure that we capture 'this'.
+    getSema().CheckCXXThisCapture(E->getLocStart());
+    return SemaRef.Owned(E);
+  }
+  
+  return getDerived().RebuildCXXThisExpr(E->getLocStart(), T, E->isImplicit());
+}
+
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformCXXThrowExpr(CXXThrowExpr *E) {
+  ExprResult SubExpr = getDerived().TransformExpr(E->getSubExpr());
+  if (SubExpr.isInvalid())
+    return ExprError();
+
+  if (!getDerived().AlwaysRebuild() &&
+      SubExpr.get() == E->getSubExpr())
+    return SemaRef.Owned(E);
+
+  return getDerived().RebuildCXXThrowExpr(E->getThrowLoc(), SubExpr.get(),
+                                          E->isThrownVariableInScope());
+}
+
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformCXXDefaultArgExpr(CXXDefaultArgExpr *E) {
+  ParmVarDecl *Param
+    = cast_or_null<ParmVarDecl>(getDerived().TransformDecl(E->getLocStart(),
+                                                           E->getParam()));
+  if (!Param)
+    return ExprError();
+
+  if (!getDerived().AlwaysRebuild() &&
+      Param == E->getParam())
+    return SemaRef.Owned(E);
+
+  return getDerived().RebuildCXXDefaultArgExpr(E->getUsedLocation(), Param);
+}
+
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformCXXScalarValueInitExpr(
+                                                    CXXScalarValueInitExpr *E) {
+  TypeSourceInfo *T = getDerived().TransformType(E->getTypeSourceInfo());
+  if (!T)
+    return ExprError();
+  
+  if (!getDerived().AlwaysRebuild() &&
+      T == E->getTypeSourceInfo())
+    return SemaRef.Owned(E);
+
+  return getDerived().RebuildCXXScalarValueInitExpr(T, 
+                                          /*FIXME:*/T->getTypeLoc().getEndLoc(),
+                                                    E->getRParenLoc());
+}
+
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformCXXNewExpr(CXXNewExpr *E) {
+  // Transform the type that we're allocating
+  TypeSourceInfo *AllocTypeInfo
+    = getDerived().TransformType(E->getAllocatedTypeSourceInfo());
+  if (!AllocTypeInfo)
+    return ExprError();
+
+  // Transform the size of the array we're allocating (if any).
+  ExprResult ArraySize = getDerived().TransformExpr(E->getArraySize());
+  if (ArraySize.isInvalid())
+    return ExprError();
+
+  // Transform the placement arguments (if any).
+  bool ArgumentChanged = false;
+  ASTOwningVector<Expr*> PlacementArgs(SemaRef);
+  if (getDerived().TransformExprs(E->getPlacementArgs(), 
+                                  E->getNumPlacementArgs(), true,
+                                  PlacementArgs, &ArgumentChanged))
+    return ExprError();
+
+  // Transform the initializer (if any).
+  Expr *OldInit = E->getInitializer();
+  ExprResult NewInit;
+  if (OldInit)
+    NewInit = getDerived().TransformExpr(OldInit);
+  if (NewInit.isInvalid())
+    return ExprError();
+
+  // Transform new operator and delete operator.
+  FunctionDecl *OperatorNew = 0;
+  if (E->getOperatorNew()) {
+    OperatorNew = cast_or_null<FunctionDecl>(
+                                 getDerived().TransformDecl(E->getLocStart(),
+                                                         E->getOperatorNew()));
+    if (!OperatorNew)
+      return ExprError();
+  }
+
+  FunctionDecl *OperatorDelete = 0;
+  if (E->getOperatorDelete()) {
+    OperatorDelete = cast_or_null<FunctionDecl>(
+                                   getDerived().TransformDecl(E->getLocStart(),
+                                                       E->getOperatorDelete()));
+    if (!OperatorDelete)
+      return ExprError();
+  }
+  
+  if (!getDerived().AlwaysRebuild() &&
+      AllocTypeInfo == E->getAllocatedTypeSourceInfo() &&
+      ArraySize.get() == E->getArraySize() &&
+      NewInit.get() == OldInit &&
+      OperatorNew == E->getOperatorNew() &&
+      OperatorDelete == E->getOperatorDelete() &&
+      !ArgumentChanged) {
+    // Mark any declarations we need as referenced.
+    // FIXME: instantiation-specific.
+    if (OperatorNew)
+      SemaRef.MarkFunctionReferenced(E->getLocStart(), OperatorNew);
+    if (OperatorDelete)
+      SemaRef.MarkFunctionReferenced(E->getLocStart(), OperatorDelete);
+    
+    if (E->isArray() && !E->getAllocatedType()->isDependentType()) {
+      QualType ElementType
+        = SemaRef.Context.getBaseElementType(E->getAllocatedType());
+      if (const RecordType *RecordT = ElementType->getAs<RecordType>()) {
+        CXXRecordDecl *Record = cast<CXXRecordDecl>(RecordT->getDecl());
+        if (CXXDestructorDecl *Destructor = SemaRef.LookupDestructor(Record)) {
+          SemaRef.MarkFunctionReferenced(E->getLocStart(), Destructor);
+        }
+      }
+    }
+
+    return SemaRef.Owned(E);
+  }
+
+  QualType AllocType = AllocTypeInfo->getType();
+  if (!ArraySize.get()) {
+    // If no array size was specified, but the new expression was
+    // instantiated with an array type (e.g., "new T" where T is
+    // instantiated with "int[4]"), extract the outer bound from the
+    // array type as our array size. We do this with constant and
+    // dependently-sized array types.
+    const ArrayType *ArrayT = SemaRef.Context.getAsArrayType(AllocType);
+    if (!ArrayT) {
+      // Do nothing
+    } else if (const ConstantArrayType *ConsArrayT
+                                     = dyn_cast<ConstantArrayType>(ArrayT)) {
+      ArraySize 
+        = SemaRef.Owned(IntegerLiteral::Create(SemaRef.Context,
+                                               ConsArrayT->getSize(), 
+                                               SemaRef.Context.getSizeType(),
+                                               /*FIXME:*/E->getLocStart()));
+      AllocType = ConsArrayT->getElementType();
+    } else if (const DependentSizedArrayType *DepArrayT
+                              = dyn_cast<DependentSizedArrayType>(ArrayT)) {
+      if (DepArrayT->getSizeExpr()) {
+        ArraySize = SemaRef.Owned(DepArrayT->getSizeExpr());
+        AllocType = DepArrayT->getElementType();
+      }
+    }
+  }
+
+  return getDerived().RebuildCXXNewExpr(E->getLocStart(),
+                                        E->isGlobalNew(),
+                                        /*FIXME:*/E->getLocStart(),
+                                        move_arg(PlacementArgs),
+                                        /*FIXME:*/E->getLocStart(),
+                                        E->getTypeIdParens(),
+                                        AllocType,
+                                        AllocTypeInfo,
+                                        ArraySize.get(),
+                                        E->getDirectInitRange(),
+                                        NewInit.take());
+}
+
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformCXXDeleteExpr(CXXDeleteExpr *E) {
+  ExprResult Operand = getDerived().TransformExpr(E->getArgument());
+  if (Operand.isInvalid())
+    return ExprError();
+
+  // Transform the delete operator, if known.
+  FunctionDecl *OperatorDelete = 0;
+  if (E->getOperatorDelete()) {
+    OperatorDelete = cast_or_null<FunctionDecl>(
+                                   getDerived().TransformDecl(E->getLocStart(),
+                                                       E->getOperatorDelete()));
+    if (!OperatorDelete)
+      return ExprError();
+  }
+  
+  if (!getDerived().AlwaysRebuild() &&
+      Operand.get() == E->getArgument() &&
+      OperatorDelete == E->getOperatorDelete()) {
+    // Mark any declarations we need as referenced.
+    // FIXME: instantiation-specific.
+    if (OperatorDelete)
+      SemaRef.MarkFunctionReferenced(E->getLocStart(), OperatorDelete);
+    
+    if (!E->getArgument()->isTypeDependent()) {
+      QualType Destroyed = SemaRef.Context.getBaseElementType(
+                                                         E->getDestroyedType());
+      if (const RecordType *DestroyedRec = Destroyed->getAs<RecordType>()) {
+        CXXRecordDecl *Record = cast<CXXRecordDecl>(DestroyedRec->getDecl());
+        SemaRef.MarkFunctionReferenced(E->getLocStart(), 
+                                       SemaRef.LookupDestructor(Record));
+      }
+    }
+    
+    return SemaRef.Owned(E);
+  }
+
+  return getDerived().RebuildCXXDeleteExpr(E->getLocStart(),
+                                           E->isGlobalDelete(),
+                                           E->isArrayForm(),
+                                           Operand.get());
+}
+
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformCXXPseudoDestructorExpr(
+                                                     CXXPseudoDestructorExpr *E) {
+  ExprResult Base = getDerived().TransformExpr(E->getBase());
+  if (Base.isInvalid())
+    return ExprError();
+
+  ParsedType ObjectTypePtr;
+  bool MayBePseudoDestructor = false;
+  Base = SemaRef.ActOnStartCXXMemberReference(0, Base.get(), 
+                                              E->getOperatorLoc(),
+                                        E->isArrow()? tok::arrow : tok::period,
+                                              ObjectTypePtr,
+                                              MayBePseudoDestructor);
+  if (Base.isInvalid())
+    return ExprError();
+                                              
+  QualType ObjectType = ObjectTypePtr.get();
+  NestedNameSpecifierLoc QualifierLoc = E->getQualifierLoc();
+  if (QualifierLoc) {
+    QualifierLoc
+      = getDerived().TransformNestedNameSpecifierLoc(QualifierLoc, ObjectType);
+    if (!QualifierLoc)
+      return ExprError();
+  }
+  CXXScopeSpec SS;
+  SS.Adopt(QualifierLoc);
+
+  PseudoDestructorTypeStorage Destroyed;
+  if (E->getDestroyedTypeInfo()) {
+    TypeSourceInfo *DestroyedTypeInfo
+      = getDerived().TransformTypeInObjectScope(E->getDestroyedTypeInfo(),
+                                                ObjectType, 0, SS);
+    if (!DestroyedTypeInfo)
+      return ExprError();
+    Destroyed = DestroyedTypeInfo;
+  } else if (!ObjectType.isNull() && ObjectType->isDependentType()) {
+    // We aren't likely to be able to resolve the identifier down to a type
+    // now anyway, so just retain the identifier.
+    Destroyed = PseudoDestructorTypeStorage(E->getDestroyedTypeIdentifier(),
+                                            E->getDestroyedTypeLoc());
+  } else {
+    // Look for a destructor known with the given name.
+    ParsedType T = SemaRef.getDestructorName(E->getTildeLoc(),
+                                              *E->getDestroyedTypeIdentifier(),
+                                                E->getDestroyedTypeLoc(),
+                                                /*Scope=*/0,
+                                                SS, ObjectTypePtr,
+                                                false);
+    if (!T)
+      return ExprError();
+    
+    Destroyed
+      = SemaRef.Context.getTrivialTypeSourceInfo(SemaRef.GetTypeFromParser(T),
+                                                 E->getDestroyedTypeLoc());
+  }
+
+  TypeSourceInfo *ScopeTypeInfo = 0;
+  if (E->getScopeTypeInfo()) {
+    ScopeTypeInfo = getDerived().TransformType(E->getScopeTypeInfo());
+    if (!ScopeTypeInfo)
+      return ExprError();
+  }
+  
+  return getDerived().RebuildCXXPseudoDestructorExpr(Base.get(),
+                                                     E->getOperatorLoc(),
+                                                     E->isArrow(),
+                                                     SS,
+                                                     ScopeTypeInfo,
+                                                     E->getColonColonLoc(),
+                                                     E->getTildeLoc(),
+                                                     Destroyed);
+}
+
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformUnresolvedLookupExpr(
+                                                  UnresolvedLookupExpr *Old) {
+  LookupResult R(SemaRef, Old->getName(), Old->getNameLoc(),
+                 Sema::LookupOrdinaryName);
+
+  // Transform all the decls.
+  for (UnresolvedLookupExpr::decls_iterator I = Old->decls_begin(),
+         E = Old->decls_end(); I != E; ++I) {
+    NamedDecl *InstD = static_cast<NamedDecl*>(
+                                 getDerived().TransformDecl(Old->getNameLoc(),
+                                                            *I));
+    if (!InstD) {
+      // Silently ignore these if a UsingShadowDecl instantiated to nothing.
+      // This can happen because of dependent hiding.
+      if (isa<UsingShadowDecl>(*I))
+        continue;
+      else
+        return ExprError();
+    }
+
+    // Expand using declarations.
+    if (isa<UsingDecl>(InstD)) {
+      UsingDecl *UD = cast<UsingDecl>(InstD);
+      for (UsingDecl::shadow_iterator I = UD->shadow_begin(),
+             E = UD->shadow_end(); I != E; ++I)
+        R.addDecl(*I);
+      continue;
+    }
+
+    R.addDecl(InstD);
+  }
+
+  // Resolve a kind, but don't do any further analysis.  If it's
+  // ambiguous, the callee needs to deal with it.
+  R.resolveKind();
+
+  // Rebuild the nested-name qualifier, if present.
+  CXXScopeSpec SS;
+  if (Old->getQualifierLoc()) {
+    NestedNameSpecifierLoc QualifierLoc
+      = getDerived().TransformNestedNameSpecifierLoc(Old->getQualifierLoc());
+    if (!QualifierLoc)
+      return ExprError();
+    
+    SS.Adopt(QualifierLoc);
+  } 
+  
+  if (Old->getNamingClass()) {
+    CXXRecordDecl *NamingClass
+      = cast_or_null<CXXRecordDecl>(getDerived().TransformDecl(
+                                                            Old->getNameLoc(),
+                                                        Old->getNamingClass()));
+    if (!NamingClass)
+      return ExprError();
+    
+    R.setNamingClass(NamingClass);
+  }
+
+  SourceLocation TemplateKWLoc = Old->getTemplateKeywordLoc();
+
+  // If we have neither explicit template arguments, nor the template keyword,
+  // it's a normal declaration name.
+  if (!Old->hasExplicitTemplateArgs() && !TemplateKWLoc.isValid())
+    return getDerived().RebuildDeclarationNameExpr(SS, R, Old->requiresADL());
+
+  // If we have template arguments, rebuild them, then rebuild the
+  // templateid expression.
+  TemplateArgumentListInfo TransArgs(Old->getLAngleLoc(), Old->getRAngleLoc());
+  if (getDerived().TransformTemplateArguments(Old->getTemplateArgs(),
+                                              Old->getNumTemplateArgs(),
+                                              TransArgs))
+    return ExprError();
+
+  return getDerived().RebuildTemplateIdExpr(SS, TemplateKWLoc, R,
+                                            Old->requiresADL(), &TransArgs);
+}
+
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformUnaryTypeTraitExpr(UnaryTypeTraitExpr *E) {
+  TypeSourceInfo *T = getDerived().TransformType(E->getQueriedTypeSourceInfo());
+  if (!T)
+    return ExprError();
+
+  if (!getDerived().AlwaysRebuild() &&
+      T == E->getQueriedTypeSourceInfo())
+    return SemaRef.Owned(E);
+
+  return getDerived().RebuildUnaryTypeTrait(E->getTrait(),
+                                            E->getLocStart(),
+                                            T,
+                                            E->getLocEnd());
+}
+
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformBinaryTypeTraitExpr(BinaryTypeTraitExpr *E) {
+  TypeSourceInfo *LhsT = getDerived().TransformType(E->getLhsTypeSourceInfo());
+  if (!LhsT)
+    return ExprError();
+
+  TypeSourceInfo *RhsT = getDerived().TransformType(E->getRhsTypeSourceInfo());
+  if (!RhsT)
+    return ExprError();
+
+  if (!getDerived().AlwaysRebuild() &&
+      LhsT == E->getLhsTypeSourceInfo() && RhsT == E->getRhsTypeSourceInfo())
+    return SemaRef.Owned(E);
+
+  return getDerived().RebuildBinaryTypeTrait(E->getTrait(),
+                                            E->getLocStart(),
+                                            LhsT, RhsT,
+                                            E->getLocEnd());
+}
+
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformTypeTraitExpr(TypeTraitExpr *E) {
+  bool ArgChanged = false;
+  llvm::SmallVector<TypeSourceInfo *, 4> Args;
+  for (unsigned I = 0, N = E->getNumArgs(); I != N; ++I) {
+    TypeSourceInfo *From = E->getArg(I);
+    TypeLoc FromTL = From->getTypeLoc();
+    if (!isa<PackExpansionTypeLoc>(FromTL)) {
+      TypeLocBuilder TLB;
+      TLB.reserve(FromTL.getFullDataSize());
+      QualType To = getDerived().TransformType(TLB, FromTL);
+      if (To.isNull())
+        return ExprError();
+      
+      if (To == From->getType())
+        Args.push_back(From);
+      else {
+        Args.push_back(TLB.getTypeSourceInfo(SemaRef.Context, To));
+        ArgChanged = true;
+      }
+      continue;
+    }
+    
+    ArgChanged = true;
+    
+    // We have a pack expansion. Instantiate it.
+    PackExpansionTypeLoc ExpansionTL = cast<PackExpansionTypeLoc>(FromTL);      
+    TypeLoc PatternTL = ExpansionTL.getPatternLoc();
+    SmallVector<UnexpandedParameterPack, 2> Unexpanded;
+    SemaRef.collectUnexpandedParameterPacks(PatternTL, Unexpanded);
+    
+    // Determine whether the set of unexpanded parameter packs can and should
+    // be expanded.
+    bool Expand = true;
+    bool RetainExpansion = false;
+    llvm::Optional<unsigned> OrigNumExpansions
+      = ExpansionTL.getTypePtr()->getNumExpansions();
+    llvm::Optional<unsigned> NumExpansions = OrigNumExpansions;
+    if (getDerived().TryExpandParameterPacks(ExpansionTL.getEllipsisLoc(),
+                                             PatternTL.getSourceRange(),
+                                             Unexpanded,
+                                             Expand, RetainExpansion,
+                                             NumExpansions))
+      return ExprError();
+    
+    if (!Expand) {
+      // The transform has determined that we should perform a simple
+      // transformation on the pack expansion, producing another pack 
+      // expansion.
+      Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(getSema(), -1);
+      
+      TypeLocBuilder TLB;
+      TLB.reserve(From->getTypeLoc().getFullDataSize());
+
+      QualType To = getDerived().TransformType(TLB, PatternTL);
+      if (To.isNull())
+        return ExprError();
+
+      To = getDerived().RebuildPackExpansionType(To, 
+                                                 PatternTL.getSourceRange(),
+                                                 ExpansionTL.getEllipsisLoc(),
+                                                 NumExpansions);
+      if (To.isNull())
+        return ExprError();
+      
+      PackExpansionTypeLoc ToExpansionTL
+        = TLB.push<PackExpansionTypeLoc>(To);
+      ToExpansionTL.setEllipsisLoc(ExpansionTL.getEllipsisLoc());
+      Args.push_back(TLB.getTypeSourceInfo(SemaRef.Context, To));
+      continue;
+    }
+
+    // Expand the pack expansion by substituting for each argument in the
+    // pack(s).
+    for (unsigned I = 0; I != *NumExpansions; ++I) {
+      Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(SemaRef, I);
+      TypeLocBuilder TLB;
+      TLB.reserve(PatternTL.getFullDataSize());
+      QualType To = getDerived().TransformType(TLB, PatternTL);
+      if (To.isNull())
+        return ExprError();
+
+      Args.push_back(TLB.getTypeSourceInfo(SemaRef.Context, To));
+    }
+    
+    if (!RetainExpansion)
+      continue;
+    
+    // If we're supposed to retain a pack expansion, do so by temporarily
+    // forgetting the partially-substituted parameter pack.
+    ForgetPartiallySubstitutedPackRAII Forget(getDerived());
+
+    TypeLocBuilder TLB;
+    TLB.reserve(From->getTypeLoc().getFullDataSize());
+    
+    QualType To = getDerived().TransformType(TLB, PatternTL);
+    if (To.isNull())
+      return ExprError();
+    
+    To = getDerived().RebuildPackExpansionType(To, 
+                                               PatternTL.getSourceRange(),
+                                               ExpansionTL.getEllipsisLoc(),
+                                               NumExpansions);
+    if (To.isNull())
+      return ExprError();
+    
+    PackExpansionTypeLoc ToExpansionTL
+      = TLB.push<PackExpansionTypeLoc>(To);
+    ToExpansionTL.setEllipsisLoc(ExpansionTL.getEllipsisLoc());
+    Args.push_back(TLB.getTypeSourceInfo(SemaRef.Context, To));
+  }
+  
+  if (!getDerived().AlwaysRebuild() && !ArgChanged)
+    return SemaRef.Owned(E);
+
+  return getDerived().RebuildTypeTrait(E->getTrait(),
+                                       E->getLocStart(),
+                                       Args,
+                                       E->getLocEnd());
+}
+
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformArrayTypeTraitExpr(ArrayTypeTraitExpr *E) {
+  TypeSourceInfo *T = getDerived().TransformType(E->getQueriedTypeSourceInfo());
+  if (!T)
+    return ExprError();
+
+  if (!getDerived().AlwaysRebuild() &&
+      T == E->getQueriedTypeSourceInfo())
+    return SemaRef.Owned(E);
+
+  ExprResult SubExpr;
+  {
+    EnterExpressionEvaluationContext Unevaluated(SemaRef, Sema::Unevaluated);
+    SubExpr = getDerived().TransformExpr(E->getDimensionExpression());
+    if (SubExpr.isInvalid())
+      return ExprError();
+
+    if (!getDerived().AlwaysRebuild() && SubExpr.get() == E->getDimensionExpression())
+      return SemaRef.Owned(E);
+  }
+
+  return getDerived().RebuildArrayTypeTrait(E->getTrait(),
+                                            E->getLocStart(),
+                                            T,
+                                            SubExpr.get(),
+                                            E->getLocEnd());
+}
+
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformExpressionTraitExpr(ExpressionTraitExpr *E) {
+  ExprResult SubExpr;
+  {
+    EnterExpressionEvaluationContext Unevaluated(SemaRef, Sema::Unevaluated);
+    SubExpr = getDerived().TransformExpr(E->getQueriedExpression());
+    if (SubExpr.isInvalid())
+      return ExprError();
+
+    if (!getDerived().AlwaysRebuild() && SubExpr.get() == E->getQueriedExpression())
+      return SemaRef.Owned(E);
+  }
+
+  return getDerived().RebuildExpressionTrait(
+      E->getTrait(), E->getLocStart(), SubExpr.get(), E->getLocEnd());
+}
+
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformDependentScopeDeclRefExpr(
+                                               DependentScopeDeclRefExpr *E) {
+  NestedNameSpecifierLoc QualifierLoc
+  = getDerived().TransformNestedNameSpecifierLoc(E->getQualifierLoc());
+  if (!QualifierLoc)
+    return ExprError();
+  SourceLocation TemplateKWLoc = E->getTemplateKeywordLoc();
+
+  // TODO: If this is a conversion-function-id, verify that the
+  // destination type name (if present) resolves the same way after
+  // instantiation as it did in the local scope.
+
+  DeclarationNameInfo NameInfo
+    = getDerived().TransformDeclarationNameInfo(E->getNameInfo());
+  if (!NameInfo.getName())
+    return ExprError();
+
+  if (!E->hasExplicitTemplateArgs()) {
+    if (!getDerived().AlwaysRebuild() &&
+        QualifierLoc == E->getQualifierLoc() &&
+        // Note: it is sufficient to compare the Name component of NameInfo:
+        // if name has not changed, DNLoc has not changed either.
+        NameInfo.getName() == E->getDeclName())
+      return SemaRef.Owned(E);
+
+    return getDerived().RebuildDependentScopeDeclRefExpr(QualifierLoc,
+                                                         TemplateKWLoc,
+                                                         NameInfo,
+                                                         /*TemplateArgs*/ 0);
+  }
+
+  TemplateArgumentListInfo TransArgs(E->getLAngleLoc(), E->getRAngleLoc());
+  if (getDerived().TransformTemplateArguments(E->getTemplateArgs(),
+                                              E->getNumTemplateArgs(),
+                                              TransArgs))
+    return ExprError();
+
+  return getDerived().RebuildDependentScopeDeclRefExpr(QualifierLoc,
+                                                       TemplateKWLoc,
+                                                       NameInfo,
+                                                       &TransArgs);
+}
+
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformCXXConstructExpr(CXXConstructExpr *E) {
+  // CXXConstructExprs are always implicit, so when we have a
+  // 1-argument construction we just transform that argument.
+  if (E->getNumArgs() == 1 ||
+      (E->getNumArgs() > 1 && getDerived().DropCallArgument(E->getArg(1))))
+    return getDerived().TransformExpr(E->getArg(0));
+
+  TemporaryBase Rebase(*this, /*FIXME*/E->getLocStart(), DeclarationName());
+
+  QualType T = getDerived().TransformType(E->getType());
+  if (T.isNull())
+    return ExprError();
+
+  CXXConstructorDecl *Constructor
+    = cast_or_null<CXXConstructorDecl>(
+                                getDerived().TransformDecl(E->getLocStart(),
+                                                         E->getConstructor()));
+  if (!Constructor)
+    return ExprError();
+
+  bool ArgumentChanged = false;
+  ASTOwningVector<Expr*> Args(SemaRef);
+  if (getDerived().TransformExprs(E->getArgs(), E->getNumArgs(), true, Args, 
+                                  &ArgumentChanged))
+    return ExprError();
+  
+  if (!getDerived().AlwaysRebuild() &&
+      T == E->getType() &&
+      Constructor == E->getConstructor() &&
+      !ArgumentChanged) {
+    // Mark the constructor as referenced.
+    // FIXME: Instantiation-specific
+    SemaRef.MarkFunctionReferenced(E->getLocStart(), Constructor);
+    return SemaRef.Owned(E);
+  }
+
+  return getDerived().RebuildCXXConstructExpr(T, /*FIXME:*/E->getLocStart(),
+                                              Constructor, E->isElidable(),
+                                              move_arg(Args),
+                                              E->hadMultipleCandidates(),
+                                              E->requiresZeroInitialization(),
+                                              E->getConstructionKind(),
+                                              E->getParenRange());
+}
+
+/// \brief Transform a C++ temporary-binding expression.
+///
+/// Since CXXBindTemporaryExpr nodes are implicitly generated, we just
+/// transform the subexpression and return that.
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformCXXBindTemporaryExpr(CXXBindTemporaryExpr *E) {
+  return getDerived().TransformExpr(E->getSubExpr());
+}
+
+/// \brief Transform a C++ expression that contains cleanups that should
+/// be run after the expression is evaluated.
+///
+/// Since ExprWithCleanups nodes are implicitly generated, we
+/// just transform the subexpression and return that.
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformExprWithCleanups(ExprWithCleanups *E) {
+  return getDerived().TransformExpr(E->getSubExpr());
+}
+
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformCXXTemporaryObjectExpr(
+                                                    CXXTemporaryObjectExpr *E) {
+  TypeSourceInfo *T = getDerived().TransformType(E->getTypeSourceInfo());
+  if (!T)
+    return ExprError();
+
+  CXXConstructorDecl *Constructor
+    = cast_or_null<CXXConstructorDecl>(
+                                  getDerived().TransformDecl(E->getLocStart(), 
+                                                         E->getConstructor()));
+  if (!Constructor)
+    return ExprError();
+
+  bool ArgumentChanged = false;
+  ASTOwningVector<Expr*> Args(SemaRef);
+  Args.reserve(E->getNumArgs());
+  if (TransformExprs(E->getArgs(), E->getNumArgs(), true, Args, 
+                     &ArgumentChanged))
+    return ExprError();
+
+  if (!getDerived().AlwaysRebuild() &&
+      T == E->getTypeSourceInfo() &&
+      Constructor == E->getConstructor() &&
+      !ArgumentChanged) {
+    // FIXME: Instantiation-specific
+    SemaRef.MarkFunctionReferenced(E->getLocStart(), Constructor);
+    return SemaRef.MaybeBindToTemporary(E);
+  }
+  
+  return getDerived().RebuildCXXTemporaryObjectExpr(T,
+                                          /*FIXME:*/T->getTypeLoc().getEndLoc(),
+                                                    move_arg(Args),
+                                                    E->getLocEnd());
+}
+
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformLambdaExpr(LambdaExpr *E) {
+  // Create the local class that will describe the lambda.
+  CXXRecordDecl *Class
+    = getSema().createLambdaClosureType(E->getIntroducerRange(),
+                                        /*KnownDependent=*/false);
+  getDerived().transformedLocalDecl(E->getLambdaClass(), Class);
+  
+  // Transform the type of the lambda parameters and start the definition of
+  // the lambda itself.
+  TypeSourceInfo *MethodTy
+    = TransformType(E->getCallOperator()->getTypeSourceInfo());  
+  if (!MethodTy)
+    return ExprError();
+
+  // Transform lambda parameters.
+  bool Invalid = false;
+  llvm::SmallVector<QualType, 4> ParamTypes;
+  llvm::SmallVector<ParmVarDecl *, 4> Params;
+  if (getDerived().TransformFunctionTypeParams(E->getLocStart(),
+        E->getCallOperator()->param_begin(),
+        E->getCallOperator()->param_size(),
+        0, ParamTypes, &Params))
+    Invalid = true;  
+
+  // Build the call operator.
+  // Note: Once a lambda mangling number and context declaration have been
+  // assigned, they never change.
+  unsigned ManglingNumber = E->getLambdaClass()->getLambdaManglingNumber();
+  Decl *ContextDecl = E->getLambdaClass()->getLambdaContextDecl();  
+  CXXMethodDecl *CallOperator
+    = getSema().startLambdaDefinition(Class, E->getIntroducerRange(),
+                                      MethodTy, 
+                                      E->getCallOperator()->getLocEnd(),
+                                      Params, ManglingNumber, ContextDecl);
+  getDerived().transformAttrs(E->getCallOperator(), CallOperator);
+  
+  // FIXME: Instantiation-specific.
+  CallOperator->setInstantiationOfMemberFunction(E->getCallOperator(), 
+                                                 TSK_ImplicitInstantiation);
+
+  // Introduce the context of the call operator.
+  Sema::ContextRAII SavedContext(getSema(), CallOperator);
+
+  // Enter the scope of the lambda.
+  sema::LambdaScopeInfo *LSI
+    = getSema().enterLambdaScope(CallOperator, E->getIntroducerRange(),
+                                 E->getCaptureDefault(),
+                                 E->hasExplicitParameters(),
+                                 E->hasExplicitResultType(),
+                                 E->isMutable());
+  
+  // Transform captures.
+  bool FinishedExplicitCaptures = false;
+  for (LambdaExpr::capture_iterator C = E->capture_begin(), 
+                                 CEnd = E->capture_end();
+       C != CEnd; ++C) {
+    // When we hit the first implicit capture, tell Sema that we've finished
+    // the list of explicit captures.
+    if (!FinishedExplicitCaptures && C->isImplicit()) {
+      getSema().finishLambdaExplicitCaptures(LSI);
+      FinishedExplicitCaptures = true;
+    }
+    
+    // Capturing 'this' is trivial.
+    if (C->capturesThis()) {
+      getSema().CheckCXXThisCapture(C->getLocation(), C->isExplicit());
+      continue;
+    }
+    
+    // Determine the capture kind for Sema.
+    Sema::TryCaptureKind Kind
+      = C->isImplicit()? Sema::TryCapture_Implicit
+                       : C->getCaptureKind() == LCK_ByCopy
+                           ? Sema::TryCapture_ExplicitByVal
+                           : Sema::TryCapture_ExplicitByRef;
+    SourceLocation EllipsisLoc;
+    if (C->isPackExpansion()) {
+      UnexpandedParameterPack Unexpanded(C->getCapturedVar(), C->getLocation());
+      bool ShouldExpand = false;
+      bool RetainExpansion = false;
+      llvm::Optional<unsigned> NumExpansions;
+      if (getDerived().TryExpandParameterPacks(C->getEllipsisLoc(), 
+                                               C->getLocation(), 
+                                               Unexpanded,
+                                               ShouldExpand, RetainExpansion,
+                                               NumExpansions))
+        return ExprError();
+      
+      if (ShouldExpand) {
+        // The transform has determined that we should perform an expansion;
+        // transform and capture each of the arguments.
+        // expansion of the pattern. Do so.
+        VarDecl *Pack = C->getCapturedVar();
+        for (unsigned I = 0; I != *NumExpansions; ++I) {
+          Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(getSema(), I);
+          VarDecl *CapturedVar
+            = cast_or_null<VarDecl>(getDerived().TransformDecl(C->getLocation(), 
+                                                               Pack));
+          if (!CapturedVar) {
+            Invalid = true;
+            continue;
+          }
+          
+          // Capture the transformed variable.
+          getSema().tryCaptureVariable(CapturedVar, C->getLocation(), Kind);          
+        }          
+        continue;
+      }
+      
+      EllipsisLoc = C->getEllipsisLoc();
+    }
+    
+    // Transform the captured variable.
+    VarDecl *CapturedVar
+      = cast_or_null<VarDecl>(getDerived().TransformDecl(C->getLocation(), 
+                                                         C->getCapturedVar()));
+    if (!CapturedVar) {
+      Invalid = true;
+      continue;
+    }
+  
+    // Capture the transformed variable.
+    getSema().tryCaptureVariable(CapturedVar, C->getLocation(), Kind);
+  }
+  if (!FinishedExplicitCaptures)
+    getSema().finishLambdaExplicitCaptures(LSI);
+
+
+  // Enter a new evaluation context to insulate the lambda from any
+  // cleanups from the enclosing full-expression.
+  getSema().PushExpressionEvaluationContext(Sema::PotentiallyEvaluated);  
+
+  if (Invalid) {
+    getSema().ActOnLambdaError(E->getLocStart(), /*CurScope=*/0, 
+                               /*IsInstantiation=*/true);
+    return ExprError();
+  }
+
+  // Instantiate the body of the lambda expression.
+  StmtResult Body = getDerived().TransformStmt(E->getBody());
+  if (Body.isInvalid()) {
+    getSema().ActOnLambdaError(E->getLocStart(), /*CurScope=*/0, 
+                               /*IsInstantiation=*/true);
+    return ExprError();    
+  }
+
+  return getSema().ActOnLambdaExpr(E->getLocStart(), Body.take(), 
+                                   /*CurScope=*/0, /*IsInstantiation=*/true);
+}
+
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformCXXUnresolvedConstructExpr(
+                                                  CXXUnresolvedConstructExpr *E) {
+  TypeSourceInfo *T = getDerived().TransformType(E->getTypeSourceInfo());
+  if (!T)
+    return ExprError();
+
+  bool ArgumentChanged = false;
+  ASTOwningVector<Expr*> Args(SemaRef);
+  Args.reserve(E->arg_size());
+  if (getDerived().TransformExprs(E->arg_begin(), E->arg_size(), true, Args, 
+                                  &ArgumentChanged))
+    return ExprError();
+  
+  if (!getDerived().AlwaysRebuild() &&
+      T == E->getTypeSourceInfo() &&
+      !ArgumentChanged)
+    return SemaRef.Owned(E);
+
+  // FIXME: we're faking the locations of the commas
+  return getDerived().RebuildCXXUnresolvedConstructExpr(T,
+                                                        E->getLParenLoc(),
+                                                        move_arg(Args),
+                                                        E->getRParenLoc());
+}
+
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformCXXDependentScopeMemberExpr(
+                                             CXXDependentScopeMemberExpr *E) {
+  // Transform the base of the expression.
+  ExprResult Base((Expr*) 0);
+  Expr *OldBase;
+  QualType BaseType;
+  QualType ObjectType;
+  if (!E->isImplicitAccess()) {
+    OldBase = E->getBase();
+    Base = getDerived().TransformExpr(OldBase);
+    if (Base.isInvalid())
+      return ExprError();
+
+    // Start the member reference and compute the object's type.
+    ParsedType ObjectTy;
+    bool MayBePseudoDestructor = false;
+    Base = SemaRef.ActOnStartCXXMemberReference(0, Base.get(),
+                                                E->getOperatorLoc(),
+                                      E->isArrow()? tok::arrow : tok::period,
+                                                ObjectTy,
+                                                MayBePseudoDestructor);
+    if (Base.isInvalid())
+      return ExprError();
+
+    ObjectType = ObjectTy.get();
+    BaseType = ((Expr*) Base.get())->getType();
+  } else {
+    OldBase = 0;
+    BaseType = getDerived().TransformType(E->getBaseType());
+    ObjectType = BaseType->getAs<PointerType>()->getPointeeType();
+  }
+
+  // Transform the first part of the nested-name-specifier that qualifies
+  // the member name.
+  NamedDecl *FirstQualifierInScope
+    = getDerived().TransformFirstQualifierInScope(
+                                            E->getFirstQualifierFoundInScope(),
+                                            E->getQualifierLoc().getBeginLoc());
+
+  NestedNameSpecifierLoc QualifierLoc;
+  if (E->getQualifier()) {
+    QualifierLoc
+      = getDerived().TransformNestedNameSpecifierLoc(E->getQualifierLoc(),
+                                                     ObjectType,
+                                                     FirstQualifierInScope);
+    if (!QualifierLoc)
+      return ExprError();
+  }
+
+  SourceLocation TemplateKWLoc = E->getTemplateKeywordLoc();
+
+  // TODO: If this is a conversion-function-id, verify that the
+  // destination type name (if present) resolves the same way after
+  // instantiation as it did in the local scope.
+
+  DeclarationNameInfo NameInfo
+    = getDerived().TransformDeclarationNameInfo(E->getMemberNameInfo());
+  if (!NameInfo.getName())
+    return ExprError();
+
+  if (!E->hasExplicitTemplateArgs()) {
+    // This is a reference to a member without an explicitly-specified
+    // template argument list. Optimize for this common case.
+    if (!getDerived().AlwaysRebuild() &&
+        Base.get() == OldBase &&
+        BaseType == E->getBaseType() &&
+        QualifierLoc == E->getQualifierLoc() &&
+        NameInfo.getName() == E->getMember() &&
+        FirstQualifierInScope == E->getFirstQualifierFoundInScope())
+      return SemaRef.Owned(E);
+
+    return getDerived().RebuildCXXDependentScopeMemberExpr(Base.get(),
+                                                       BaseType,
+                                                       E->isArrow(),
+                                                       E->getOperatorLoc(),
+                                                       QualifierLoc,
+                                                       TemplateKWLoc,
+                                                       FirstQualifierInScope,
+                                                       NameInfo,
+                                                       /*TemplateArgs*/ 0);
+  }
+
+  TemplateArgumentListInfo TransArgs(E->getLAngleLoc(), E->getRAngleLoc());
+  if (getDerived().TransformTemplateArguments(E->getTemplateArgs(),
+                                              E->getNumTemplateArgs(),
+                                              TransArgs))
+    return ExprError();
+
+  return getDerived().RebuildCXXDependentScopeMemberExpr(Base.get(),
+                                                     BaseType,
+                                                     E->isArrow(),
+                                                     E->getOperatorLoc(),
+                                                     QualifierLoc,
+                                                     TemplateKWLoc,
+                                                     FirstQualifierInScope,
+                                                     NameInfo,
+                                                     &TransArgs);
+}
+
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformUnresolvedMemberExpr(UnresolvedMemberExpr *Old) {
+  // Transform the base of the expression.
+  ExprResult Base((Expr*) 0);
+  QualType BaseType;
+  if (!Old->isImplicitAccess()) {
+    Base = getDerived().TransformExpr(Old->getBase());
+    if (Base.isInvalid())
+      return ExprError();
+    Base = getSema().PerformMemberExprBaseConversion(Base.take(),
+                                                     Old->isArrow());
+    if (Base.isInvalid())
+      return ExprError();
+    BaseType = Base.get()->getType();
+  } else {
+    BaseType = getDerived().TransformType(Old->getBaseType());
+  }
+
+  NestedNameSpecifierLoc QualifierLoc;
+  if (Old->getQualifierLoc()) {
+    QualifierLoc
+    = getDerived().TransformNestedNameSpecifierLoc(Old->getQualifierLoc());
+    if (!QualifierLoc)
+      return ExprError();
+  }
+
+  SourceLocation TemplateKWLoc = Old->getTemplateKeywordLoc();
+
+  LookupResult R(SemaRef, Old->getMemberNameInfo(),
+                 Sema::LookupOrdinaryName);
+
+  // Transform all the decls.
+  for (UnresolvedMemberExpr::decls_iterator I = Old->decls_begin(),
+         E = Old->decls_end(); I != E; ++I) {
+    NamedDecl *InstD = static_cast<NamedDecl*>(
+                                getDerived().TransformDecl(Old->getMemberLoc(),
+                                                           *I));
+    if (!InstD) {
+      // Silently ignore these if a UsingShadowDecl instantiated to nothing.
+      // This can happen because of dependent hiding.
+      if (isa<UsingShadowDecl>(*I))
+        continue;
+      else {
+        R.clear();
+        return ExprError();
+      }
+    }
+
+    // Expand using declarations.
+    if (isa<UsingDecl>(InstD)) {
+      UsingDecl *UD = cast<UsingDecl>(InstD);
+      for (UsingDecl::shadow_iterator I = UD->shadow_begin(),
+             E = UD->shadow_end(); I != E; ++I)
+        R.addDecl(*I);
+      continue;
+    }
+
+    R.addDecl(InstD);
+  }
+
+  R.resolveKind();
+
+  // Determine the naming class.
+  if (Old->getNamingClass()) {
+    CXXRecordDecl *NamingClass 
+      = cast_or_null<CXXRecordDecl>(getDerived().TransformDecl(
+                                                          Old->getMemberLoc(),
+                                                        Old->getNamingClass()));
+    if (!NamingClass)
+      return ExprError();
+    
+    R.setNamingClass(NamingClass);
+  }
+  
+  TemplateArgumentListInfo TransArgs;
+  if (Old->hasExplicitTemplateArgs()) {
+    TransArgs.setLAngleLoc(Old->getLAngleLoc());
+    TransArgs.setRAngleLoc(Old->getRAngleLoc());
+    if (getDerived().TransformTemplateArguments(Old->getTemplateArgs(),
+                                                Old->getNumTemplateArgs(),
+                                                TransArgs))
+      return ExprError();
+  }
+
+  // FIXME: to do this check properly, we will need to preserve the
+  // first-qualifier-in-scope here, just in case we had a dependent
+  // base (and therefore couldn't do the check) and a
+  // nested-name-qualifier (and therefore could do the lookup).
+  NamedDecl *FirstQualifierInScope = 0;
+  
+  return getDerived().RebuildUnresolvedMemberExpr(Base.get(),
+                                                  BaseType,
+                                                  Old->getOperatorLoc(),
+                                                  Old->isArrow(),
+                                                  QualifierLoc,
+                                                  TemplateKWLoc,
+                                                  FirstQualifierInScope,
+                                                  R,
+                                              (Old->hasExplicitTemplateArgs()
+                                                  ? &TransArgs : 0));
+}
+
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformCXXNoexceptExpr(CXXNoexceptExpr *E) {
+  EnterExpressionEvaluationContext Unevaluated(SemaRef, Sema::Unevaluated);
+  ExprResult SubExpr = getDerived().TransformExpr(E->getOperand());
+  if (SubExpr.isInvalid())
+    return ExprError();
+
+  if (!getDerived().AlwaysRebuild() && SubExpr.get() == E->getOperand())
+    return SemaRef.Owned(E);
+
+  return getDerived().RebuildCXXNoexceptExpr(E->getSourceRange(),SubExpr.get());
+}
+
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformPackExpansionExpr(PackExpansionExpr *E) {
+  ExprResult Pattern = getDerived().TransformExpr(E->getPattern());
+  if (Pattern.isInvalid())
+    return ExprError();
+  
+  if (!getDerived().AlwaysRebuild() && Pattern.get() == E->getPattern())
+    return SemaRef.Owned(E);
+
+  return getDerived().RebuildPackExpansion(Pattern.get(), E->getEllipsisLoc(),
+                                           E->getNumExpansions());
+}
+
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformSizeOfPackExpr(SizeOfPackExpr *E) {
+  // If E is not value-dependent, then nothing will change when we transform it.
+  // Note: This is an instantiation-centric view.
+  if (!E->isValueDependent())
+    return SemaRef.Owned(E);
+
+  // Note: None of the implementations of TryExpandParameterPacks can ever
+  // produce a diagnostic when given only a single unexpanded parameter pack,
+  // so 
+  UnexpandedParameterPack Unexpanded(E->getPack(), E->getPackLoc());
+  bool ShouldExpand = false;
+  bool RetainExpansion = false;
+  llvm::Optional<unsigned> NumExpansions;
+  if (getDerived().TryExpandParameterPacks(E->getOperatorLoc(), E->getPackLoc(), 
+                                           Unexpanded,
+                                           ShouldExpand, RetainExpansion,
+                                           NumExpansions))
+    return ExprError();
+  
+  if (RetainExpansion)
+    return SemaRef.Owned(E);
+    
+  NamedDecl *Pack = E->getPack();
+  if (!ShouldExpand) {
+    Pack = cast_or_null<NamedDecl>(getDerived().TransformDecl(E->getPackLoc(), 
+                                                              Pack));
+    if (!Pack)
+      return ExprError();
+  }
+
+  
+  // We now know the length of the parameter pack, so build a new expression
+  // that stores that length.
+  return getDerived().RebuildSizeOfPackExpr(E->getOperatorLoc(), Pack, 
+                                            E->getPackLoc(), E->getRParenLoc(), 
+                                            NumExpansions);
+}
+
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformSubstNonTypeTemplateParmPackExpr(
+                                          SubstNonTypeTemplateParmPackExpr *E) {
+  // Default behavior is to do nothing with this transformation.
+  return SemaRef.Owned(E);
+}
+
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformSubstNonTypeTemplateParmExpr(
+                                          SubstNonTypeTemplateParmExpr *E) {
+  // Default behavior is to do nothing with this transformation.
+  return SemaRef.Owned(E);
+}
+
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformMaterializeTemporaryExpr(
+                                                  MaterializeTemporaryExpr *E) {
+  return getDerived().TransformExpr(E->GetTemporaryExpr());
+}
+  
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformObjCStringLiteral(ObjCStringLiteral *E) {
+  return SemaRef.MaybeBindToTemporary(E);
+}
+
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformObjCBoolLiteralExpr(ObjCBoolLiteralExpr *E) {
+  return SemaRef.Owned(E);
+}
+
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformObjCNumericLiteral(ObjCNumericLiteral *E) {
+  return SemaRef.MaybeBindToTemporary(E);
+}
+
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformObjCArrayLiteral(ObjCArrayLiteral *E) {
+  // Transform each of the elements.
+  llvm::SmallVector<Expr *, 8> Elements;
+  bool ArgChanged = false;
+  if (getDerived().TransformExprs(E->getElements(), E->getNumElements(), 
+                                  /*IsCall=*/false, Elements, &ArgChanged))
+    return ExprError();
+  
+  if (!getDerived().AlwaysRebuild() && !ArgChanged)
+    return SemaRef.MaybeBindToTemporary(E);
+  
+  return getDerived().RebuildObjCArrayLiteral(E->getSourceRange(),
+                                              Elements.data(),
+                                              Elements.size());
+}
+
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformObjCDictionaryLiteral(
+                                                    ObjCDictionaryLiteral *E) {  
+  // Transform each of the elements.
+  llvm::SmallVector<ObjCDictionaryElement, 8> Elements;
+  bool ArgChanged = false;
+  for (unsigned I = 0, N = E->getNumElements(); I != N; ++I) {
+    ObjCDictionaryElement OrigElement = E->getKeyValueElement(I);
+    
+    if (OrigElement.isPackExpansion()) {
+      // This key/value element is a pack expansion.
+      SmallVector<UnexpandedParameterPack, 2> Unexpanded;
+      getSema().collectUnexpandedParameterPacks(OrigElement.Key, Unexpanded);
+      getSema().collectUnexpandedParameterPacks(OrigElement.Value, Unexpanded);
+      assert(!Unexpanded.empty() && "Pack expansion without parameter packs?");
+
+      // Determine whether the set of unexpanded parameter packs can
+      // and should be expanded.
+      bool Expand = true;
+      bool RetainExpansion = false;
+      llvm::Optional<unsigned> OrigNumExpansions = OrigElement.NumExpansions;
+      llvm::Optional<unsigned> NumExpansions = OrigNumExpansions;
+      SourceRange PatternRange(OrigElement.Key->getLocStart(),
+                               OrigElement.Value->getLocEnd());
+     if (getDerived().TryExpandParameterPacks(OrigElement.EllipsisLoc,
+                                               PatternRange,
+                                               Unexpanded,
+                                               Expand, RetainExpansion,
+                                               NumExpansions))
+        return ExprError();
+
+      if (!Expand) {
+        // The transform has determined that we should perform a simple
+        // transformation on the pack expansion, producing another pack 
+        // expansion.
+        Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(getSema(), -1);
+        ExprResult Key = getDerived().TransformExpr(OrigElement.Key);
+        if (Key.isInvalid())
+          return ExprError();
+
+        if (Key.get() != OrigElement.Key)
+          ArgChanged = true;
+
+        ExprResult Value = getDerived().TransformExpr(OrigElement.Value);
+        if (Value.isInvalid())
+          return ExprError();
+        
+        if (Value.get() != OrigElement.Value)
+          ArgChanged = true;
+
+        ObjCDictionaryElement Expansion = { 
+          Key.get(), Value.get(), OrigElement.EllipsisLoc, NumExpansions
+        };
+        Elements.push_back(Expansion);
+        continue;
+      }
+
+      // Record right away that the argument was changed.  This needs
+      // to happen even if the array expands to nothing.
+      ArgChanged = true;
+      
+      // The transform has determined that we should perform an elementwise
+      // expansion of the pattern. Do so.
+      for (unsigned I = 0; I != *NumExpansions; ++I) {
+        Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(getSema(), I);
+        ExprResult Key = getDerived().TransformExpr(OrigElement.Key);
+        if (Key.isInvalid())
+          return ExprError();
+
+        ExprResult Value = getDerived().TransformExpr(OrigElement.Value);
+        if (Value.isInvalid())
+          return ExprError();
+
+        ObjCDictionaryElement Element = { 
+          Key.get(), Value.get(), SourceLocation(), NumExpansions
+        };
+
+        // If any unexpanded parameter packs remain, we still have a
+        // pack expansion.
+        if (Key.get()->containsUnexpandedParameterPack() ||
+            Value.get()->containsUnexpandedParameterPack())
+          Element.EllipsisLoc = OrigElement.EllipsisLoc;
+          
+        Elements.push_back(Element);
+      }
+
+      // We've finished with this pack expansion.
+      continue;
+    }
+
+    // Transform and check key.
+    ExprResult Key = getDerived().TransformExpr(OrigElement.Key);
+    if (Key.isInvalid())
+      return ExprError();
+    
+    if (Key.get() != OrigElement.Key)
+      ArgChanged = true;
+    
+    // Transform and check value.
+    ExprResult Value
+      = getDerived().TransformExpr(OrigElement.Value);
+    if (Value.isInvalid())
+      return ExprError();
+    
+    if (Value.get() != OrigElement.Value)
+      ArgChanged = true;
+    
+    ObjCDictionaryElement Element = { 
+      Key.get(), Value.get(), SourceLocation(), llvm::Optional<unsigned>()
+    };
+    Elements.push_back(Element);
+  }
+  
+  if (!getDerived().AlwaysRebuild() && !ArgChanged)
+    return SemaRef.MaybeBindToTemporary(E);
+
+  return getDerived().RebuildObjCDictionaryLiteral(E->getSourceRange(),
+                                                   Elements.data(),
+                                                   Elements.size());
+}
+
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformObjCEncodeExpr(ObjCEncodeExpr *E) {
+  TypeSourceInfo *EncodedTypeInfo
+    = getDerived().TransformType(E->getEncodedTypeSourceInfo());
+  if (!EncodedTypeInfo)
+    return ExprError();
+
+  if (!getDerived().AlwaysRebuild() &&
+      EncodedTypeInfo == E->getEncodedTypeSourceInfo())
+    return SemaRef.Owned(E);
+
+  return getDerived().RebuildObjCEncodeExpr(E->getAtLoc(),
+                                            EncodedTypeInfo,
+                                            E->getRParenLoc());
+}
+
+template<typename Derived>
+ExprResult TreeTransform<Derived>::
+TransformObjCIndirectCopyRestoreExpr(ObjCIndirectCopyRestoreExpr *E) {
+  ExprResult result = getDerived().TransformExpr(E->getSubExpr());
+  if (result.isInvalid()) return ExprError();
+  Expr *subExpr = result.take();
+
+  if (!getDerived().AlwaysRebuild() &&
+      subExpr == E->getSubExpr())
+    return SemaRef.Owned(E);
+
+  return SemaRef.Owned(new(SemaRef.Context)
+      ObjCIndirectCopyRestoreExpr(subExpr, E->getType(), E->shouldCopy()));
+}
+
+template<typename Derived>
+ExprResult TreeTransform<Derived>::
+TransformObjCBridgedCastExpr(ObjCBridgedCastExpr *E) {
+  TypeSourceInfo *TSInfo 
+    = getDerived().TransformType(E->getTypeInfoAsWritten());
+  if (!TSInfo)
+    return ExprError();
+  
+  ExprResult Result = getDerived().TransformExpr(E->getSubExpr());
+  if (Result.isInvalid()) 
+    return ExprError();
+  
+  if (!getDerived().AlwaysRebuild() &&
+      TSInfo == E->getTypeInfoAsWritten() &&
+      Result.get() == E->getSubExpr())
+    return SemaRef.Owned(E);
+  
+  return SemaRef.BuildObjCBridgedCast(E->getLParenLoc(), E->getBridgeKind(),
+                                      E->getBridgeKeywordLoc(), TSInfo, 
+                                      Result.get());
+}
+
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformObjCMessageExpr(ObjCMessageExpr *E) {
+  // Transform arguments.
+  bool ArgChanged = false;
+  ASTOwningVector<Expr*> Args(SemaRef);
+  Args.reserve(E->getNumArgs());
+  if (getDerived().TransformExprs(E->getArgs(), E->getNumArgs(), false, Args, 
+                                  &ArgChanged))
+    return ExprError();
+  
+  if (E->getReceiverKind() == ObjCMessageExpr::Class) {
+    // Class message: transform the receiver type.
+    TypeSourceInfo *ReceiverTypeInfo
+      = getDerived().TransformType(E->getClassReceiverTypeInfo());
+    if (!ReceiverTypeInfo)
+      return ExprError();
+    
+    // If nothing changed, just retain the existing message send.
+    if (!getDerived().AlwaysRebuild() &&
+        ReceiverTypeInfo == E->getClassReceiverTypeInfo() && !ArgChanged)
+      return SemaRef.MaybeBindToTemporary(E);
+
+    // Build a new class message send.
+    SmallVector<SourceLocation, 16> SelLocs;
+    E->getSelectorLocs(SelLocs);
+    return getDerived().RebuildObjCMessageExpr(ReceiverTypeInfo,
+                                               E->getSelector(),
+                                               SelLocs,
+                                               E->getMethodDecl(),
+                                               E->getLeftLoc(),
+                                               move_arg(Args),
+                                               E->getRightLoc());
+  }
+
+  // Instance message: transform the receiver
+  assert(E->getReceiverKind() == ObjCMessageExpr::Instance &&
+         "Only class and instance messages may be instantiated");
+  ExprResult Receiver
+    = getDerived().TransformExpr(E->getInstanceReceiver());
+  if (Receiver.isInvalid())
+    return ExprError();
+
+  // If nothing changed, just retain the existing message send.
+  if (!getDerived().AlwaysRebuild() &&
+      Receiver.get() == E->getInstanceReceiver() && !ArgChanged)
+    return SemaRef.MaybeBindToTemporary(E);
+  
+  // Build a new instance message send.
+  SmallVector<SourceLocation, 16> SelLocs;
+  E->getSelectorLocs(SelLocs);
+  return getDerived().RebuildObjCMessageExpr(Receiver.get(),
+                                             E->getSelector(),
+                                             SelLocs,
+                                             E->getMethodDecl(),
+                                             E->getLeftLoc(),
+                                             move_arg(Args),
+                                             E->getRightLoc());
+}
+
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformObjCSelectorExpr(ObjCSelectorExpr *E) {
+  return SemaRef.Owned(E);
+}
+
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformObjCProtocolExpr(ObjCProtocolExpr *E) {
+  return SemaRef.Owned(E);
+}
+
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformObjCIvarRefExpr(ObjCIvarRefExpr *E) {
+  // Transform the base expression.
+  ExprResult Base = getDerived().TransformExpr(E->getBase());
+  if (Base.isInvalid())
+    return ExprError();
+
+  // We don't need to transform the ivar; it will never change.
+  
+  // If nothing changed, just retain the existing expression.
+  if (!getDerived().AlwaysRebuild() &&
+      Base.get() == E->getBase())
+    return SemaRef.Owned(E);
+  
+  return getDerived().RebuildObjCIvarRefExpr(Base.get(), E->getDecl(),
+                                             E->getLocation(),
+                                             E->isArrow(), E->isFreeIvar());
+}
+
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformObjCPropertyRefExpr(ObjCPropertyRefExpr *E) {
+  // 'super' and types never change. Property never changes. Just
+  // retain the existing expression.
+  if (!E->isObjectReceiver())
+    return SemaRef.Owned(E);
+  
+  // Transform the base expression.
+  ExprResult Base = getDerived().TransformExpr(E->getBase());
+  if (Base.isInvalid())
+    return ExprError();
+  
+  // We don't need to transform the property; it will never change.
+  
+  // If nothing changed, just retain the existing expression.
+  if (!getDerived().AlwaysRebuild() &&
+      Base.get() == E->getBase())
+    return SemaRef.Owned(E);
+
+  if (E->isExplicitProperty())
+    return getDerived().RebuildObjCPropertyRefExpr(Base.get(),
+                                                   E->getExplicitProperty(),
+                                                   E->getLocation());
+
+  return getDerived().RebuildObjCPropertyRefExpr(Base.get(),
+                                                 SemaRef.Context.PseudoObjectTy,
+                                                 E->getImplicitPropertyGetter(),
+                                                 E->getImplicitPropertySetter(),
+                                                 E->getLocation());
+}
+
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformObjCSubscriptRefExpr(ObjCSubscriptRefExpr *E) {
+  // Transform the base expression.
+  ExprResult Base = getDerived().TransformExpr(E->getBaseExpr());
+  if (Base.isInvalid())
+    return ExprError();
+
+  // Transform the key expression.
+  ExprResult Key = getDerived().TransformExpr(E->getKeyExpr());
+  if (Key.isInvalid())
+    return ExprError();
+
+  // If nothing changed, just retain the existing expression.
+  if (!getDerived().AlwaysRebuild() &&
+      Key.get() == E->getKeyExpr() && Base.get() == E->getBaseExpr())
+    return SemaRef.Owned(E);
+
+  return getDerived().RebuildObjCSubscriptRefExpr(E->getRBracket(), 
+                                                  Base.get(), Key.get(),
+                                                  E->getAtIndexMethodDecl(),
+                                                  E->setAtIndexMethodDecl());
+}
+
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformObjCIsaExpr(ObjCIsaExpr *E) {
+  // Transform the base expression.
+  ExprResult Base = getDerived().TransformExpr(E->getBase());
+  if (Base.isInvalid())
+    return ExprError();
+  
+  // If nothing changed, just retain the existing expression.
+  if (!getDerived().AlwaysRebuild() &&
+      Base.get() == E->getBase())
+    return SemaRef.Owned(E);
+  
+  return getDerived().RebuildObjCIsaExpr(Base.get(), E->getIsaMemberLoc(),
+                                         E->isArrow());
+}
+
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformShuffleVectorExpr(ShuffleVectorExpr *E) {
+  bool ArgumentChanged = false;
+  ASTOwningVector<Expr*> SubExprs(SemaRef);
+  SubExprs.reserve(E->getNumSubExprs());
+  if (getDerived().TransformExprs(E->getSubExprs(), E->getNumSubExprs(), false, 
+                                  SubExprs, &ArgumentChanged))
+    return ExprError();
+
+  if (!getDerived().AlwaysRebuild() &&
+      !ArgumentChanged)
+    return SemaRef.Owned(E);
+
+  return getDerived().RebuildShuffleVectorExpr(E->getBuiltinLoc(),
+                                               move_arg(SubExprs),
+                                               E->getRParenLoc());
+}
+
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformBlockExpr(BlockExpr *E) {
+  BlockDecl *oldBlock = E->getBlockDecl();
+  
+  SemaRef.ActOnBlockStart(E->getCaretLocation(), /*Scope=*/0);
+  BlockScopeInfo *blockScope = SemaRef.getCurBlock();
+
+  blockScope->TheDecl->setIsVariadic(oldBlock->isVariadic());
+  blockScope->TheDecl->setBlockMissingReturnType(
+                         oldBlock->blockMissingReturnType());
+  
+  SmallVector<ParmVarDecl*, 4> params;
+  SmallVector<QualType, 4> paramTypes;
+  
+  // Parameter substitution.
+  if (getDerived().TransformFunctionTypeParams(E->getCaretLocation(),
+                                               oldBlock->param_begin(),
+                                               oldBlock->param_size(),
+                                               0, paramTypes, &params)) {
+    getSema().ActOnBlockError(E->getCaretLocation(), /*Scope=*/0);
+    return ExprError();
+  }
+
+  const FunctionType *exprFunctionType = E->getFunctionType();
+  QualType exprResultType =
+      getDerived().TransformType(exprFunctionType->getResultType());
+
+  // Don't allow returning a objc interface by value.
+  if (exprResultType->isObjCObjectType()) {
+    getSema().Diag(E->getCaretLocation(), 
+                   diag::err_object_cannot_be_passed_returned_by_value) 
+      << 0 << exprResultType;
+    getSema().ActOnBlockError(E->getCaretLocation(), /*Scope=*/0);
+    return ExprError();
+  }
+
+  QualType functionType = getDerived().RebuildFunctionProtoType(
+                                                        exprResultType,
+                                                        paramTypes.data(),
+                                                        paramTypes.size(),
+                                                        oldBlock->isVariadic(),
+                                                        false, 0, RQ_None,
+                                               exprFunctionType->getExtInfo());
+  blockScope->FunctionType = functionType;
+
+  // Set the parameters on the block decl.
+  if (!params.empty())
+    blockScope->TheDecl->setParams(params);
+
+  if (!oldBlock->blockMissingReturnType()) {
+    blockScope->HasImplicitReturnType = false;
+    blockScope->ReturnType = exprResultType;
+  }
+  
+  // Transform the body
+  StmtResult body = getDerived().TransformStmt(E->getBody());
+  if (body.isInvalid()) {
+    getSema().ActOnBlockError(E->getCaretLocation(), /*Scope=*/0);
+    return ExprError();
+  }
+
+#ifndef NDEBUG
+  // In builds with assertions, make sure that we captured everything we
+  // captured before.
+  if (!SemaRef.getDiagnostics().hasErrorOccurred()) {
+    for (BlockDecl::capture_iterator i = oldBlock->capture_begin(),
+           e = oldBlock->capture_end(); i != e; ++i) {
+      VarDecl *oldCapture = i->getVariable();
+
+      // Ignore parameter packs.
+      if (isa<ParmVarDecl>(oldCapture) &&
+          cast<ParmVarDecl>(oldCapture)->isParameterPack())
+        continue;
+
+      VarDecl *newCapture =
+        cast<VarDecl>(getDerived().TransformDecl(E->getCaretLocation(),
+                                                 oldCapture));
+      assert(blockScope->CaptureMap.count(newCapture));
+    }
+    assert(oldBlock->capturesCXXThis() == blockScope->isCXXThisCaptured());
+  }
+#endif
+
+  return SemaRef.ActOnBlockStmtExpr(E->getCaretLocation(), body.get(),
+                                    /*Scope=*/0);
+}
+
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformAsTypeExpr(AsTypeExpr *E) {
+  llvm_unreachable("Cannot transform asType expressions yet");
+}
+
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformAtomicExpr(AtomicExpr *E) {
+  QualType RetTy = getDerived().TransformType(E->getType());
+  bool ArgumentChanged = false;
+  ASTOwningVector<Expr*> SubExprs(SemaRef);
+  SubExprs.reserve(E->getNumSubExprs());
+  if (getDerived().TransformExprs(E->getSubExprs(), E->getNumSubExprs(), false,
+                                  SubExprs, &ArgumentChanged))
+    return ExprError();
+
+  if (!getDerived().AlwaysRebuild() &&
+      !ArgumentChanged)
+    return SemaRef.Owned(E);
+
+  return getDerived().RebuildAtomicExpr(E->getBuiltinLoc(), move_arg(SubExprs),
+                                        RetTy, E->getOp(), E->getRParenLoc());
+}
+  
+//===----------------------------------------------------------------------===//
+// Type reconstruction
+//===----------------------------------------------------------------------===//
+
+template<typename Derived>
+QualType TreeTransform<Derived>::RebuildPointerType(QualType PointeeType,
+                                                    SourceLocation Star) {
+  return SemaRef.BuildPointerType(PointeeType, Star,
+                                  getDerived().getBaseEntity());
+}
+
+template<typename Derived>
+QualType TreeTransform<Derived>::RebuildBlockPointerType(QualType PointeeType,
+                                                         SourceLocation Star) {
+  return SemaRef.BuildBlockPointerType(PointeeType, Star,
+                                       getDerived().getBaseEntity());
+}
+
+template<typename Derived>
+QualType
+TreeTransform<Derived>::RebuildReferenceType(QualType ReferentType,
+                                             bool WrittenAsLValue,
+                                             SourceLocation Sigil) {
+  return SemaRef.BuildReferenceType(ReferentType, WrittenAsLValue,
+                                    Sigil, getDerived().getBaseEntity());
+}
+
+template<typename Derived>
+QualType
+TreeTransform<Derived>::RebuildMemberPointerType(QualType PointeeType,
+                                                 QualType ClassType,
+                                                 SourceLocation Sigil) {
+  return SemaRef.BuildMemberPointerType(PointeeType, ClassType,
+                                        Sigil, getDerived().getBaseEntity());
+}
+
+template<typename Derived>
+QualType
+TreeTransform<Derived>::RebuildArrayType(QualType ElementType,
+                                         ArrayType::ArraySizeModifier SizeMod,
+                                         const llvm::APInt *Size,
+                                         Expr *SizeExpr,
+                                         unsigned IndexTypeQuals,
+                                         SourceRange BracketsRange) {
+  if (SizeExpr || !Size)
+    return SemaRef.BuildArrayType(ElementType, SizeMod, SizeExpr,
+                                  IndexTypeQuals, BracketsRange,
+                                  getDerived().getBaseEntity());
+
+  QualType Types[] = {
+    SemaRef.Context.UnsignedCharTy, SemaRef.Context.UnsignedShortTy,
+    SemaRef.Context.UnsignedIntTy, SemaRef.Context.UnsignedLongTy,
+    SemaRef.Context.UnsignedLongLongTy, SemaRef.Context.UnsignedInt128Ty
+  };
+  const unsigned NumTypes = sizeof(Types) / sizeof(QualType);
+  QualType SizeType;
+  for (unsigned I = 0; I != NumTypes; ++I)
+    if (Size->getBitWidth() == SemaRef.Context.getIntWidth(Types[I])) {
+      SizeType = Types[I];
+      break;
+    }
+
+  // Note that we can return a VariableArrayType here in the case where
+  // the element type was a dependent VariableArrayType.
+  IntegerLiteral *ArraySize
+      = IntegerLiteral::Create(SemaRef.Context, *Size, SizeType,
+                               /*FIXME*/BracketsRange.getBegin());
+  return SemaRef.BuildArrayType(ElementType, SizeMod, ArraySize,
+                                IndexTypeQuals, BracketsRange,
+                                getDerived().getBaseEntity());
+}
+
+template<typename Derived>
+QualType
+TreeTransform<Derived>::RebuildConstantArrayType(QualType ElementType,
+                                                 ArrayType::ArraySizeModifier SizeMod,
+                                                 const llvm::APInt &Size,
+                                                 unsigned IndexTypeQuals,
+                                                 SourceRange BracketsRange) {
+  return getDerived().RebuildArrayType(ElementType, SizeMod, &Size, 0,
+                                        IndexTypeQuals, BracketsRange);
+}
+
+template<typename Derived>
+QualType
+TreeTransform<Derived>::RebuildIncompleteArrayType(QualType ElementType,
+                                          ArrayType::ArraySizeModifier SizeMod,
+                                                 unsigned IndexTypeQuals,
+                                                   SourceRange BracketsRange) {
+  return getDerived().RebuildArrayType(ElementType, SizeMod, 0, 0,
+                                       IndexTypeQuals, BracketsRange);
+}
+
+template<typename Derived>
+QualType
+TreeTransform<Derived>::RebuildVariableArrayType(QualType ElementType,
+                                          ArrayType::ArraySizeModifier SizeMod,
+                                                 Expr *SizeExpr,
+                                                 unsigned IndexTypeQuals,
+                                                 SourceRange BracketsRange) {
+  return getDerived().RebuildArrayType(ElementType, SizeMod, 0,
+                                       SizeExpr,
+                                       IndexTypeQuals, BracketsRange);
+}
+
+template<typename Derived>
+QualType
+TreeTransform<Derived>::RebuildDependentSizedArrayType(QualType ElementType,
+                                          ArrayType::ArraySizeModifier SizeMod,
+                                                       Expr *SizeExpr,
+                                                       unsigned IndexTypeQuals,
+                                                   SourceRange BracketsRange) {
+  return getDerived().RebuildArrayType(ElementType, SizeMod, 0,
+                                       SizeExpr,
+                                       IndexTypeQuals, BracketsRange);
+}
+
+template<typename Derived>
+QualType TreeTransform<Derived>::RebuildVectorType(QualType ElementType,
+                                               unsigned NumElements,
+                                               VectorType::VectorKind VecKind) {
+  // FIXME: semantic checking!
+  return SemaRef.Context.getVectorType(ElementType, NumElements, VecKind);
+}
+
+template<typename Derived>
+QualType TreeTransform<Derived>::RebuildExtVectorType(QualType ElementType,
+                                                      unsigned NumElements,
+                                                 SourceLocation AttributeLoc) {
+  llvm::APInt numElements(SemaRef.Context.getIntWidth(SemaRef.Context.IntTy),
+                          NumElements, true);
+  IntegerLiteral *VectorSize
+    = IntegerLiteral::Create(SemaRef.Context, numElements, SemaRef.Context.IntTy,
+                             AttributeLoc);
+  return SemaRef.BuildExtVectorType(ElementType, VectorSize, AttributeLoc);
+}
+
+template<typename Derived>
+QualType
+TreeTransform<Derived>::RebuildDependentSizedExtVectorType(QualType ElementType,
+                                                           Expr *SizeExpr,
+                                                  SourceLocation AttributeLoc) {
+  return SemaRef.BuildExtVectorType(ElementType, SizeExpr, AttributeLoc);
+}
+
+template<typename Derived>
+QualType TreeTransform<Derived>::RebuildFunctionProtoType(QualType T,
+                                                          QualType *ParamTypes,
+                                                        unsigned NumParamTypes,
+                                                          bool Variadic,
+                                                         bool HasTrailingReturn,
+                                                          unsigned Quals,
+                                                  RefQualifierKind RefQualifier,
+                                            const FunctionType::ExtInfo &Info) {
+  return SemaRef.BuildFunctionType(T, ParamTypes, NumParamTypes, Variadic,
+                                   HasTrailingReturn, Quals, RefQualifier,
+                                   getDerived().getBaseLocation(),
+                                   getDerived().getBaseEntity(),
+                                   Info);
+}
+
+template<typename Derived>
+QualType TreeTransform<Derived>::RebuildFunctionNoProtoType(QualType T) {
+  return SemaRef.Context.getFunctionNoProtoType(T);
+}
+
+template<typename Derived>
+QualType TreeTransform<Derived>::RebuildUnresolvedUsingType(Decl *D) {
+  assert(D && "no decl found");
+  if (D->isInvalidDecl()) return QualType();
+
+  // FIXME: Doesn't account for ObjCInterfaceDecl!
+  TypeDecl *Ty;
+  if (isa<UsingDecl>(D)) {
+    UsingDecl *Using = cast<UsingDecl>(D);
+    assert(Using->isTypeName() &&
+           "UnresolvedUsingTypenameDecl transformed to non-typename using");
+
+    // A valid resolved using typename decl points to exactly one type decl.
+    assert(++Using->shadow_begin() == Using->shadow_end());
+    Ty = cast<TypeDecl>((*Using->shadow_begin())->getTargetDecl());
+    
+  } else {
+    assert(isa<UnresolvedUsingTypenameDecl>(D) &&
+           "UnresolvedUsingTypenameDecl transformed to non-using decl");
+    Ty = cast<UnresolvedUsingTypenameDecl>(D);
+  }
+
+  return SemaRef.Context.getTypeDeclType(Ty);
+}
+
+template<typename Derived>
+QualType TreeTransform<Derived>::RebuildTypeOfExprType(Expr *E,
+                                                       SourceLocation Loc) {
+  return SemaRef.BuildTypeofExprType(E, Loc);
+}
+
+template<typename Derived>
+QualType TreeTransform<Derived>::RebuildTypeOfType(QualType Underlying) {
+  return SemaRef.Context.getTypeOfType(Underlying);
+}
+
+template<typename Derived>
+QualType TreeTransform<Derived>::RebuildDecltypeType(Expr *E,
+                                                     SourceLocation Loc) {
+  return SemaRef.BuildDecltypeType(E, Loc);
+}
+
+template<typename Derived>
+QualType TreeTransform<Derived>::RebuildUnaryTransformType(QualType BaseType,
+                                            UnaryTransformType::UTTKind UKind,
+                                            SourceLocation Loc) {
+  return SemaRef.BuildUnaryTransformType(BaseType, UKind, Loc);
+}
+
+template<typename Derived>
+QualType TreeTransform<Derived>::RebuildTemplateSpecializationType(
+                                                      TemplateName Template,
+                                             SourceLocation TemplateNameLoc,
+                                     TemplateArgumentListInfo &TemplateArgs) {
+  return SemaRef.CheckTemplateIdType(Template, TemplateNameLoc, TemplateArgs);
+}
+
+template<typename Derived>
+QualType TreeTransform<Derived>::RebuildAtomicType(QualType ValueType,
+                                                   SourceLocation KWLoc) {
+  return SemaRef.BuildAtomicType(ValueType, KWLoc);
+}
+
+template<typename Derived>
+TemplateName
+TreeTransform<Derived>::RebuildTemplateName(CXXScopeSpec &SS,
+                                            bool TemplateKW,
+                                            TemplateDecl *Template) {
+  return SemaRef.Context.getQualifiedTemplateName(SS.getScopeRep(), TemplateKW,
+                                                  Template);
+}
+
+template<typename Derived>
+TemplateName
+TreeTransform<Derived>::RebuildTemplateName(CXXScopeSpec &SS,
+                                            const IdentifierInfo &Name,
+                                            SourceLocation NameLoc,
+                                            QualType ObjectType,
+                                            NamedDecl *FirstQualifierInScope) {
+  UnqualifiedId TemplateName;
+  TemplateName.setIdentifier(&Name, NameLoc);
+  Sema::TemplateTy Template;
+  SourceLocation TemplateKWLoc; // FIXME: retrieve it from caller.
+  getSema().ActOnDependentTemplateName(/*Scope=*/0,
+                                       SS, TemplateKWLoc, TemplateName,
+                                       ParsedType::make(ObjectType),
+                                       /*EnteringContext=*/false,
+                                       Template);
+  return Template.get();
+}
+
+template<typename Derived>
+TemplateName
+TreeTransform<Derived>::RebuildTemplateName(CXXScopeSpec &SS,
+                                            OverloadedOperatorKind Operator,
+                                            SourceLocation NameLoc,
+                                            QualType ObjectType) {
+  UnqualifiedId Name;
+  // FIXME: Bogus location information.
+  SourceLocation SymbolLocations[3] = { NameLoc, NameLoc, NameLoc };
+  Name.setOperatorFunctionId(NameLoc, Operator, SymbolLocations);
+  SourceLocation TemplateKWLoc; // FIXME: retrieve it from caller.
+  Sema::TemplateTy Template;
+  getSema().ActOnDependentTemplateName(/*Scope=*/0,
+                                       SS, TemplateKWLoc, Name,
+                                       ParsedType::make(ObjectType),
+                                       /*EnteringContext=*/false,
+                                       Template);
+  return Template.template getAsVal<TemplateName>();
+}
+  
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::RebuildCXXOperatorCallExpr(OverloadedOperatorKind Op,
+                                                   SourceLocation OpLoc,
+                                                   Expr *OrigCallee,
+                                                   Expr *First,
+                                                   Expr *Second) {
+  Expr *Callee = OrigCallee->IgnoreParenCasts();
+  bool isPostIncDec = Second && (Op == OO_PlusPlus || Op == OO_MinusMinus);
+
+  // Determine whether this should be a builtin operation.
+  if (Op == OO_Subscript) {
+    if (!First->getType()->isOverloadableType() &&
+        !Second->getType()->isOverloadableType())
+      return getSema().CreateBuiltinArraySubscriptExpr(First,
+                                                       Callee->getLocStart(),
+                                                       Second, OpLoc);
+  } else if (Op == OO_Arrow) {
+    // -> is never a builtin operation.
+    return SemaRef.BuildOverloadedArrowExpr(0, First, OpLoc);
+  } else if (Second == 0 || isPostIncDec) {
+    if (!First->getType()->isOverloadableType()) {
+      // The argument is not of overloadable type, so try to create a
+      // built-in unary operation.
+      UnaryOperatorKind Opc
+        = UnaryOperator::getOverloadedOpcode(Op, isPostIncDec);
+
+      return getSema().CreateBuiltinUnaryOp(OpLoc, Opc, First);
+    }
+  } else {
+    if (!First->getType()->isOverloadableType() &&
+        !Second->getType()->isOverloadableType()) {
+      // Neither of the arguments is an overloadable type, so try to
+      // create a built-in binary operation.
+      BinaryOperatorKind Opc = BinaryOperator::getOverloadedOpcode(Op);
+      ExprResult Result
+        = SemaRef.CreateBuiltinBinOp(OpLoc, Opc, First, Second);
+      if (Result.isInvalid())
+        return ExprError();
+
+      return move(Result);
+    }
+  }
+
+  // Compute the transformed set of functions (and function templates) to be
+  // used during overload resolution.
+  UnresolvedSet<16> Functions;
+
+  if (UnresolvedLookupExpr *ULE = dyn_cast<UnresolvedLookupExpr>(Callee)) {
+    assert(ULE->requiresADL());
+
+    // FIXME: Do we have to check
+    // IsAcceptableNonMemberOperatorCandidate for each of these?
+    Functions.append(ULE->decls_begin(), ULE->decls_end());
+  } else {
+    Functions.addDecl(cast<DeclRefExpr>(Callee)->getDecl());
+  }
+
+  // Add any functions found via argument-dependent lookup.
+  Expr *Args[2] = { First, Second };
+  unsigned NumArgs = 1 + (Second != 0);
+
+  // Create the overloaded operator invocation for unary operators.
+  if (NumArgs == 1 || isPostIncDec) {
+    UnaryOperatorKind Opc
+      = UnaryOperator::getOverloadedOpcode(Op, isPostIncDec);
+    return SemaRef.CreateOverloadedUnaryOp(OpLoc, Opc, Functions, First);
+  }
+
+  if (Op == OO_Subscript) {
+    SourceLocation LBrace;
+    SourceLocation RBrace;
+
+    if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(Callee)) {
+        DeclarationNameLoc &NameLoc = DRE->getNameInfo().getInfo();
+        LBrace = SourceLocation::getFromRawEncoding(
+                    NameLoc.CXXOperatorName.BeginOpNameLoc);
+        RBrace = SourceLocation::getFromRawEncoding(
+                    NameLoc.CXXOperatorName.EndOpNameLoc);
+    } else {
+        LBrace = Callee->getLocStart();
+        RBrace = OpLoc;
+    }
+
+    return SemaRef.CreateOverloadedArraySubscriptExpr(LBrace, RBrace,
+                                                      First, Second);
+  }
+
+  // Create the overloaded operator invocation for binary operators.
+  BinaryOperatorKind Opc = BinaryOperator::getOverloadedOpcode(Op);
+  ExprResult Result
+    = SemaRef.CreateOverloadedBinOp(OpLoc, Opc, Functions, Args[0], Args[1]);
+  if (Result.isInvalid())
+    return ExprError();
+
+  return move(Result);
+}
+
+template<typename Derived>
+ExprResult 
+TreeTransform<Derived>::RebuildCXXPseudoDestructorExpr(Expr *Base,
+                                                     SourceLocation OperatorLoc,
+                                                       bool isArrow,
+                                                       CXXScopeSpec &SS,
+                                                     TypeSourceInfo *ScopeType,
+                                                       SourceLocation CCLoc,
+                                                       SourceLocation TildeLoc,
+                                        PseudoDestructorTypeStorage Destroyed) {
+  QualType BaseType = Base->getType();
+  if (Base->isTypeDependent() || Destroyed.getIdentifier() ||
+      (!isArrow && !BaseType->getAs<RecordType>()) ||
+      (isArrow && BaseType->getAs<PointerType>() && 
+       !BaseType->getAs<PointerType>()->getPointeeType()
+                                              ->template getAs<RecordType>())){
+    // This pseudo-destructor expression is still a pseudo-destructor.
+    return SemaRef.BuildPseudoDestructorExpr(Base, OperatorLoc,
+                                             isArrow? tok::arrow : tok::period,
+                                             SS, ScopeType, CCLoc, TildeLoc,
+                                             Destroyed,
+                                             /*FIXME?*/true);
+  }
+
+  TypeSourceInfo *DestroyedType = Destroyed.getTypeSourceInfo();
+  DeclarationName Name(SemaRef.Context.DeclarationNames.getCXXDestructorName(
+                 SemaRef.Context.getCanonicalType(DestroyedType->getType())));
+  DeclarationNameInfo NameInfo(Name, Destroyed.getLocation());
+  NameInfo.setNamedTypeInfo(DestroyedType);
+
+  // FIXME: the ScopeType should be tacked onto SS.
+
+  SourceLocation TemplateKWLoc; // FIXME: retrieve it from caller.
+  return getSema().BuildMemberReferenceExpr(Base, BaseType,
+                                            OperatorLoc, isArrow,
+                                            SS, TemplateKWLoc,
+                                            /*FIXME: FirstQualifier*/ 0,
+                                            NameInfo,
+                                            /*TemplateArgs*/ 0);
+}
+
+} // end namespace clang
+
+#endif // LLVM_CLANG_SEMA_TREETRANSFORM_H
diff --git a/clang/lib/Sema/TypeLocBuilder.h b/clang/lib/Sema/TypeLocBuilder.h
new file mode 100644
index 0000000..7a5e43e
--- /dev/null
+++ b/clang/lib/Sema/TypeLocBuilder.h
@@ -0,0 +1,201 @@
+//===--- TypeLocBuilder.h - Type Source Info collector ----------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+//  This files defines TypeLocBuilder, a class for building TypeLocs
+//  bottom-up.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_SEMA_TYPELOCBUILDER_H
+#define LLVM_CLANG_SEMA_TYPELOCBUILDER_H
+
+#include "clang/AST/TypeLoc.h"
+#include "clang/AST/ASTContext.h"
+
+namespace clang {
+
+class TypeLocBuilder {
+  enum { InlineCapacity = 8 * sizeof(SourceLocation) };
+
+  /// The underlying location-data buffer.  Data grows from the end
+  /// of the buffer backwards.
+  char *Buffer;
+
+  /// The capacity of the current buffer.
+  size_t Capacity;
+
+  /// The index of the first occupied byte in the buffer.
+  size_t Index;
+
+#ifndef NDEBUG
+  /// The last type pushed on this builder.
+  QualType LastTy;
+#endif
+    
+  /// The inline buffer.
+  char InlineBuffer[InlineCapacity];
+
+ public:
+  TypeLocBuilder()
+    : Buffer(InlineBuffer), Capacity(InlineCapacity), Index(InlineCapacity) {}
+
+  ~TypeLocBuilder() {
+    if (Buffer != InlineBuffer)
+      delete[] Buffer;
+  }
+
+  /// Ensures that this buffer has at least as much capacity as described.
+  void reserve(size_t Requested) {
+    if (Requested > Capacity)
+      // For now, match the request exactly.
+      grow(Requested);
+  }
+
+  /// Pushes a copy of the given TypeLoc onto this builder.  The builder
+  /// must be empty for this to work.
+  void pushFullCopy(TypeLoc L) {
+    size_t Size = L.getFullDataSize();
+    TypeLoc Copy = pushFullUninitializedImpl(L.getType(), Size);
+    memcpy(Copy.getOpaqueData(), L.getOpaqueData(), Size);
+  }
+
+  /// Pushes uninitialized space for the given type.  The builder must
+  /// be empty.
+  TypeLoc pushFullUninitialized(QualType T) {
+    return pushFullUninitializedImpl(T, TypeLoc::getFullDataSizeForType(T));
+  }
+
+  /// Pushes space for a typespec TypeLoc.  Invalidates any TypeLocs
+  /// previously retrieved from this builder.
+  TypeSpecTypeLoc pushTypeSpec(QualType T) {
+    size_t LocalSize = TypeSpecTypeLoc::LocalDataSize;
+    return cast<TypeSpecTypeLoc>(pushImpl(T, LocalSize));
+  }
+
+  /// Resets this builder to the newly-initialized state.
+  void clear() {
+#ifndef NDEBUG
+    LastTy = QualType();
+#endif
+    Index = Capacity;
+  }  
+
+  /// \brief Tell the TypeLocBuilder that the type it is storing has been
+  /// modified in some safe way that doesn't affect type-location information.
+  void TypeWasModifiedSafely(QualType T) {
+#ifndef NDEBUG
+    LastTy = T;
+#endif
+  }
+  
+  /// Pushes space for a new TypeLoc of the given type.  Invalidates
+  /// any TypeLocs previously retrieved from this builder.
+  template <class TyLocType> TyLocType push(QualType T) {
+    size_t LocalSize = cast<TyLocType>(TypeLoc(T, 0)).getLocalDataSize();
+    return cast<TyLocType>(pushImpl(T, LocalSize));
+  }
+
+  /// Creates a TypeSourceInfo for the given type.
+  TypeSourceInfo *getTypeSourceInfo(ASTContext& Context, QualType T) {
+#ifndef NDEBUG
+    assert(T == LastTy && "type doesn't match last type pushed!");
+#endif
+
+    size_t FullDataSize = Capacity - Index;
+    TypeSourceInfo *DI = Context.CreateTypeSourceInfo(T, FullDataSize);
+    memcpy(DI->getTypeLoc().getOpaqueData(), &Buffer[Index], FullDataSize);
+    return DI;
+  }
+
+  /// \brief Copies the type-location information to the given AST context and 
+  /// returns a \c TypeLoc referring into the AST context.
+  TypeLoc getTypeLocInContext(ASTContext &Context, QualType T) {
+#ifndef NDEBUG
+    assert(T == LastTy && "type doesn't match last type pushed!");
+#endif
+    
+    size_t FullDataSize = Capacity - Index;
+    void *Mem = Context.Allocate(FullDataSize);
+    memcpy(Mem, &Buffer[Index], FullDataSize);
+    return TypeLoc(T, Mem);
+  }
+
+private:
+  TypeLoc pushImpl(QualType T, size_t LocalSize) {
+#ifndef NDEBUG
+    QualType TLast = TypeLoc(T, 0).getNextTypeLoc().getType();
+    assert(TLast == LastTy &&
+           "mismatch between last type and new type's inner type");
+    LastTy = T;
+#endif
+
+    // If we need to grow, grow by a factor of 2.
+    if (LocalSize > Index) {
+      size_t RequiredCapacity = Capacity + (LocalSize - Index);
+      size_t NewCapacity = Capacity * 2;
+      while (RequiredCapacity > NewCapacity)
+        NewCapacity *= 2;
+      grow(NewCapacity);
+    }
+
+    Index -= LocalSize;
+
+    return getTemporaryTypeLoc(T);
+  }
+
+  /// Grow to the given capacity.
+  void grow(size_t NewCapacity) {
+    assert(NewCapacity > Capacity);
+
+    // Allocate the new buffer and copy the old data into it.
+    char *NewBuffer = new char[NewCapacity];
+    unsigned NewIndex = Index + NewCapacity - Capacity;
+    memcpy(&NewBuffer[NewIndex],
+           &Buffer[Index],
+           Capacity - Index);
+
+    if (Buffer != InlineBuffer)
+      delete[] Buffer;
+
+    Buffer = NewBuffer;
+    Capacity = NewCapacity;
+    Index = NewIndex;
+  }
+
+  TypeLoc pushFullUninitializedImpl(QualType T, size_t Size) {
+#ifndef NDEBUG
+    assert(LastTy.isNull() && "pushing full on non-empty TypeLocBuilder");
+    LastTy = T;
+#endif
+    assert(Index == Capacity && "pushing full on non-empty TypeLocBuilder");
+
+    reserve(Size);
+    Index -= Size;
+
+    return getTemporaryTypeLoc(T);
+  }
+
+public:
+  /// \brief Retrieve a temporary TypeLoc that refers into this \c TypeLocBuilder
+  /// object.
+  ///
+  /// The resulting \c TypeLoc should only be used so long as the 
+  /// \c TypeLocBuilder is active and has not had more type information
+  /// pushed into it.
+  TypeLoc getTemporaryTypeLoc(QualType T) {
+#ifndef NDEBUG
+    assert(LastTy == T && "type doesn't match last type pushed!");
+#endif
+    return TypeLoc(T, &Buffer[Index]);
+  }
+};
+
+}
+
+#endif
-- 
cgit v1.2.3